soap - 连接失败时如何使用 WSS4JOutInterceptor 在 CXF 中捕获 SOAP 请求消息

标签 soap cxf wss4j saaj

我可以根据 this SO answer .

但是,如果服务器不可用,我会从 SAAJOutInterceptor(由 WSS4JOutInterceptor 添加)得到以下异常,并且不会调用 LoggingCallback,因此消息不是错误的:

org.apache.cxf.binding.soap.SoapFault: Connection refused: connect
        at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:221)
        at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:174)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
        at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:440)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:355)
        at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:313)
        at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
        at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140)
        ...
Caused by: com.ctc.wstx.exc.WstxIOException: Connection refused: connect
        at com.ctc.wstx.sw.BaseStreamWriter.flush(BaseStreamWriter.java:262)
        at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:215)
        ...
Caused by: java.net.ConnectException: Connection refused: connect
        at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
        at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:589)
        at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
        at sun.net.www.http.HttpClient.openServer(HttpClient.java:463)
        at sun.net.www.http.HttpClient.openServer(HttpClient.java:558)
        at sun.net.www.http.HttpClient.<init>(HttpClient.java:242)
        at sun.net.www.http.HttpClient.New(HttpClient.java:339)
        at sun.net.www.http.HttpClient.New(HttpClient.java:357)
        at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1220)
        at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1199)
        at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1050)
        at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:984)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1334)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1309)
        at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.setupWrappedStream(URLConnectionHTTPConduit.java:274)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1345)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1306)
        at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.onFirstWrite(URLConnectionHTTPConduit.java:307)
        at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
        at org.apache.cxf.io.AbstractThresholdOutputStream.unBuffer(AbstractThresholdOutputStream.java:89)
        at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:63)
        at org.apache.cxf.io.CacheAndWriteOutputStream.write(CacheAndWriteOutputStream.java:80)
        at org.apache.cxf.io.CacheAndWriteOutputStream.write(CacheAndWriteOutputStream.java:80)
        at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:51)
        at com.ctc.wstx.io.UTF8Writer.flush(UTF8Writer.java:100)
        at com.ctc.wstx.sw.BufferingXmlWriter.flush(BufferingXmlWriter.java:242)
        at com.ctc.wstx.sw.BaseStreamWriter.flush(BaseStreamWriter.java:260)
        ...

我需要用 WSS4JOutInterceptor 添加的所有安全内容(证书、签名...)保存请求 SOAP 消息,无论消息是否成功发送或服务器是否正常运行。

最佳答案

问题是你必须首先写入你捕获消息的输出流,然后只在 onClose 回调中写入网络连接:

class RequestInterceptor extends AbstractPhaseInterceptor<Message> {

    OutputStream outputStream
    OutputStream originalOutputStream

    public RequestInterceptor() {
        super(Phase.PRE_STREAM);
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        originalOutputStream = message.getContent(OutputStream.class)
        CacheAndWriteOutputStream newOutputStream = new CacheAndWriteOutputStream(outputStream)
        message.setContent(OutputStream.class, newOutputStream)
        newOutputStream.registerCallback(new CachedOutputStreamCallback() {
            void onFlush(CachedOutputStream cos) {
            }
            void onClose(CachedOutputStream cos) {
                cos.writeCacheTo(originalOutputStream)
                originalOutputStream.close()
            }
        })
    }

}

关于soap - 连接失败时如何使用 WSS4JOutInterceptor 在 CXF 中捕获 SOAP 请求消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56091069/

相关文章:

asp.net - 使用客户端证书获取 SOAP 服务器 WSDL 文件

java - Azure - 尝试连接到外部 MySQL 数据库时权限被拒绝

java - NoSuchMethodError : What version of Apache Xml Security do I need? 错误

soap - spring-ws 2.2.1 中的无效属性 'securementCallbackHandlers'

Java WSS4J 证书在签名请求后从 keystore 中消失

带有 SSL 证书的 PHP SOAP 客户端

java - 如何通过 HTTPS/SSL 连接到 soap 网络服务?

java - 使用 CXF Rest 客户端解析响应实体

java - WSDL 中缺少 PortType 操作输入名称

java - 没有wsdl的apache cxf客户端