1

我的应用程序有两个传出 SOAP 连接。对于那些,我想实现 TLS。两者都是使用 CXF 创建的。

返回一个单独的javax.xml.ws.Service.getPort()bindingProvider(两个连接都使用自己的 WSDL),但都使用相同的org.apache.cxf.bus.spring.SpringBus实例。

在使用 bindingProvider 之前,我在 Conduit 上设置了 TLS 客户端参数:

Client client = ClientProxy.getClient(bindingProvider); // different
HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); // same for both connections
TLSClientParameters tlsClientParameters = new TLSClientParameters();
tlsClientParameters.setTrustManagers(getTrustmanagers());
httpConduit.setTlsClientParameters(tlsClientParameters);

问题是,检索到的客户端对于两个连接都不同,但管道是同一个对象。因此,当我在同一对象上设置第二个连接的参数时,我会覆盖先前设置的设置。

常见问题解答是否 CXF 是线程安全的,“是”和一些例外情况。我认为第二个例外适用于此。它说:

CXF 回答: CXF 代理对于许多用例来说都是线程安全的。例外情况是:

  • [...]

  • 管道上的设置 - 如果您使用代码或配置直接操作管道(例如设置 TLS 设置或类似设置),则这些不是线程安全的。管道是每个实例的,因此这些设置将被共享。此外,如果您使用 FailoverFeature 和 LoadBalanceFeatures,则会即时更换管道。因此,在导管上设置的设置在用于设置线程之前可能会丢失。

  • [...]

对于导管问题,您可以安装一个使用本地线程或类似线程的新 ConduitSelector。不过这有点复杂。

我不完全确定线程安全是否是我的问题。我在各自的组件中创建了两个连接。Springs 只使用一个线程来初始化所有组件,因此两个连接都由同一个线程初始化。但之后,连接使用了来自池的线程。覆盖设置发生在初始化期间,因此在使用不同线程发送实际 SOAP 消息之前。

当在 中创建 Conduit 时org.apache.cxf.endpoint.AbstractConduitSelector#getSelectedConduit,它是使用SpringBus两个对象的相同实例来完成的。

所以,FAQ 告诉我使用我自己的自定义 ConduitSelector。我尝试在上面的初始化之前设置它:

Client client = ClientProxy.getClient(bindingProvider);
client.setConduitSelector(
    new UpfrontConduitSelector(
        new URLConnectionHTTPConduit(client.getBus(), 
                                     client.getEndpoint().getEndpointInfo())));

我在初始化后尝试了同样的方法。在这两种情况下,在设置了管道选择器之后,当某些东西使用 BindingProvider(它是一个代理对象)时,它会得到一个 NullPointerException,尽管该对象不为空。

我的问题是让自定义管道选择器运行,或者看看我的问题可以完全不同地解决,或者只是为了获得一些灵感:)

SO上的某个人似乎在这里解决了这个问题,但他的问题的答案对我没有帮助。

4

1 回答 1

1

我找到了解决方案。

这个问题确实与多线程无关,但与 SpringBus 连接到我的对象的方式以及如何从中创建导管有关。

解决方案是为每个服务提供自己的 SpringBus。

因此,在通过调用其 c'tor in 创建每个 SOAP 服务之前javax.xml.ws.Service,我会

BusFactory bf = BusFactory.newInstance();
Bus b = bf.createBus();
BusFactory.setThreadDefaultBus(b);

它设置了一个新的线程本地默认总线,然后用于创建的服务。因此,我的两个服务都有自己的 SpringBus 并且它们都创建了自己的 Conduit。

这是因为每个服务都是一个弹簧@Component,所有弹簧组件都是由主线程创建的。所以只有一个线程,这段代码不可能不按顺序执行。

于 2018-08-24T15:26:08.060 回答