Jax-WS 请求-响应负载日志记录中的线程安全

Thread Safety in Jax-WS Request-Response Payload Logging

我正在研究 SoapHandler 实现。基本上我的目标是获取请求和响应有效负载并将它们插入数据库。

虽然我可以获得请求和响应有效负载,但我无法确定我的代码是否线程安全。换句话说,我不确定响应是否与正确的请求匹配。

public boolean handleMessage(SOAPMessageContext mContext) {

    boolean isResponse = (Boolean) mContext
            .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

    if (!isResponse) {
        try {
            mContext.put("currentStream", new ByteArrayOutputStream());
            mContext.getMessage().writeTo((OutputStream) mContext.get("currentStream"));

        } catch (SOAPException | IOException e) {
            e.printStackTrace();
        }
    } else {
        try {
            mContext.getMessage().writeTo(
                    (OutputStream) mContext.get("currentStream"));
            System.out.println(((OutputStream) mContext.get("currentStream"))
                    .toString());
            ((OutputStream) mContext.get("currentStream")).flush();
        } catch (SOAPException | IOException e) {
            e.printStackTrace();
        }
    }

    return true;
}

我在 JCP 规范中找到了这个:

9.3.3 Handler Implementation Considerations

Handler instances may be pooled by a JAX-RPC runtime system. All instances of a specific handler are considered equivalent by a JAX-RPC runtime system and any instance may be chosen to handle a particular message. Different handler instances may be used to handle each messages of an MEP. Different threads may be used for each handler in a handler chain, for each message in an MEP or any combination of the two. Handlers should not rely on thread local state to share information. Handlers should instead use the message context, see section 9.4.

9.4 Message Context

Handlers are invoked with a message context that provides methods to access and modify inbound and outbound messages and to manage a set of properties. Different types of handler are invoked with different types of message context. Sections 9.4.1 and 9.4.2 describe MessageContext and LogicalMessageContext respectively. In addition, JAX-RPC bindings 12 may define a message context subtype for their particular protocol binding that provides access to protocol specific features. Section10.3 describes the message context subtype for the JAX-RPC SOAP binding.

http://download.oracle.com/otn-pub/jcp/jaxrpc-2.0-edr2-spec-oth-JSpec/jaxrpc-2_0-edr2-spec.pdf?AuthParam=1431341511_1ac4403a34d7db108bce79eda126df49

这是否意味着为每个请求创建一个新的 MessageContext 对象(在这种情况下我认为代码将是线程安全的),或者同一个 MessageContext 对象可以用于多个请求(那么我的代码将不会线程安全)。

任何帮助/替代解决方案将不胜感激。

经验法则:FooContext 对象根据定义是 上下文相关的 ,与特定的执行上下文相关。 EJBContext 与单个 EJB 相关; FacesContext 与单个 Faces 请求上下文有关; SOAPMessageContext 与单个 SOAPMessage 相关。来自 JSR-109 文档:

The container must share the same MessageContext instance across all Handler instances and the target endpoint that are invoked during a single request and response or fault processing on a specific node.

因此,您可以确定每个请求有一个 SOAPMessageContext 实例 。但是,在单个请求的上下文中,该实例由您处理。所以真正的问题是,you 和 "threadsafety" 是什么意思?您是否计划让多个线程在每个请求期间处理一个 SOAPMessageContext?不推荐

编辑:虽然规范没有白纸黑字地说明 MessageContext 是线程安全的,但在整个规范中都暗示了这一点。以下是规范部分的摘录,该部分说明了 MessageContext 在处理程序中的可能性:

Handlers may manipulate the values and scope of properties within the message context as desired. E.g. ... a handler in a server-side SOAP binding might add application scoped properties tot he message context from the contents of a header in a request SOAP message...


SOAP handlers are passed a SOAPMessageContext when invoked. SOAPMessageContext extends MessageContext with methods to obtain and modify the SOAP message payload

规范不会要求程序员在不安全的情况下修改上下文的内容。