【问题标题】:Thread Safety in Jax-WS Request-Response Payload LoggingJax-WS 请求-响应负载日志中的线程安全
【发布时间】:2024-01-20 01:38:01
【问题描述】:

我正在开发一个 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 处理程序实现注意事项

处理程序实例可以由 JAX-RPC 运行时系统汇集。特定处理程序的所有实例都是 JAX-RPC 运行时系统认为是等效的,并且可以选择任何实例来处理特定的 信息。可以使用不同的处理程序实例来处理 MEP 的每条消息。不同的线程 可以用于处理程序链中的每个处理程序,用于 MEP 中的每个消息或任何组合 二。处理程序不应依赖线程本地状态来共享信息。处理程序应改为使用 消息上下文,见第 9.4 节。

9.4 消息上下文

使用消息上下文调用处理程序,该消息上下文提供访问和修改入站和 出站消息并管理一组属性。 使用不同类型的消息上下文调用不同类型的处理程序。第 9.4.1 和 9.4.2 节 分别描述 MessageContext 和 LogicalMessageContext。此外,JAX-RPC 绑定 12 可以为它们的特定协议绑定定义一个消息上下文子类型,提供对协议的访问 具体功能。第 10.3 节描述了 JAX-RPC SOAP 绑定的消息上下文子类型。

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 对象可以用于多个请求(那么我的代码将不是线程安全的)。

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

【问题讨论】:

    标签: web-services soap thread-safety jax-ws soaphandler


    【解决方案1】:

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

    容器必须在单个请求期间调用的所有 Handler 实例和目标端点共享相同的 MessageContext 实例,并在特定节点上进行响应或故障处理。

    所以,您可以确定 SOAPMessageContext 实例每个请求。然而,在单个请求的上下文中,该实例是你的。所以真正的问题是,you 所说的“线程安全”是什么意思?您是否计划在每个请求期间让多个线程处理单个SOAPMessageContext?我不推荐它

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

    处理程序可以根据需要在消息上下文中操作属性的值和范围。例如。 ...服务器端 SOAP 绑定中的处理程序可能会从请求 SOAP 消息中的标头内容将应用程序范围的属性添加到消息上下文中...


    SOAP 处理程序在调用时会传递一个SOAPMessageContextSOAPMessageContext 扩展了 MessageContext获取和修改 SOAP 消息有效负载的方法

    如果这样做不安全,规范不会期望程序员修改上下文的内容。

    【讨论】:

    • 我所说的线程安全是指:第一个请求的messageContext中的outputStream只能被第一个响应的messageContext访问。第二个响应的 messageContext 应该不能访问第一个请求的 messageContext。如果是这种情况,我可以确保第二个请求无法访问为第一个请求创建的 outputStream。否则,可能是其中一个 outputStreams 可以包含 requestA 的请求负载和 requestB 的响应负载,这基本上是我想要避免的。
    • 第二个请求肯定会有自己的输出流来破坏@HüseyinKılıç。我从规范中添加了更多说明该保证的块
    最近更新 更多