8

I'm trying to develop a client application for a WebService using Apache's CXF library. In this specific server implementation, when there's some data missing in the request (e.g. Some person's ID number), it returns HTTP code 403 (Forbidden) but with a response body containing the application specific error details as a Soap Fault.

As an example, here's a response I gathered using SoapUI:

Response in the SoapUI
As you can see in the highlighted text, there's a response body in this request.


Now I need to retrieve the response body from within my application. I tried using interceptors in different phases such as SEND_ENDING and POST_PROTOCOL, but can't seem to find it within the Message parameter given to the handleMessage() method.

What am I missing?

Here's the exception and stack trace I'm getting:

org.apache.cxf.interceptor.Fault: Could not send Message.
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:67)
    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)
    at com.sun.proxy.$Proxy36.arquivo(Unknown Source)
    at br.com.dgsistemas.TesteWS.main(TesteWS.java:133)
Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '403: Forbidden' when communicating with https://www.wsrestrito.caixa.gov.br/siies/WsSolicitacao
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.doProcessResponseCode(HTTPConduit.java:1620)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1627)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1572)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1373)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:673)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:63)
    ... 9 more

Thank you!

Leandragem
  • 100
  • 1
  • 12

3 Answers3

0

You have two independent problem.

First you have to remove the chunked message. http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html#ClientHTTPTransport(includingSSLsupport)-ANoteAboutChunking

Before you call the endpoint, you have to disable the chunked communication:

   HTTPConduit conduit = (HTTPConduit) client.getConduit();
   HTTPClientPolicy policy = new HTTPClientPolicy();


   // Chunking is by default enabled in CXF webservices so we have to disable it.     
   policy.setAllowChunking(false);
   conduit.setClient(policy); // update HTTP client's conduit

Second I think you have to remove a BOM. You can see what is it in the following wikipedia note: https://en.wikipedia.org/wiki/Byte_order_mark

If you want to remove BOM check this: Byte order mark screws up file reading in Java

NOTE1: The chunked messages depends on server settings, the server may ignore your request setting.

NOTE2: You can handle BOM and chunked message both if you write a stream interceptor. The chunked messages don't have a Content-Length header, and while actual length lesser than the expected, you have to wait more message from server.

rockfarkas
  • 132
  • 2
  • 8
  • Can I remove the BOM from within an Interceptor? – Leandragem Feb 05 '19 at 18:30
  • You should write an input stream wrapper. Check this example how to create an input stream from message: https://github.com/apache/cxf/blob/master/core/src/main/java/org/apache/cxf/interceptor/StaxInInterceptor.java – rockfarkas Feb 06 '19 at 19:39
  • Unfortunately the `message.getContent(XMLStreamReader.class)` returns `null`, so the Interceptor gets skipped... – Leandragem Feb 07 '19 at 21:19
  • Overriding this verification, `message.getContent(InputStream.class)` is also `null` – Leandragem Feb 07 '19 at 21:36
0

You should be able to extend AbstractSoapInterceptor, register this in the Phase.MARSHAL phase, and extract the message in your handleMessage override.

Use SoapMessage.getExchange().getInMessage() or .getInFaultMessage() to extract the message from the SOAP response.

Aaron Saarela
  • 3,956
  • 1
  • 19
  • 17
  • Nothing here.. I casted the Message type to SoapMessage and then tried to call in the methods that you suggested, but they're null. Maybe it's because the message is chunked? – Leandragem Feb 09 '19 at 19:24
-1

Did you try using the LoggingInInterceptor for that (See description), or extend it and overwrite the handleMessage method. It can be used to monitor all SOAP IN messages

Example for usage can be found here

pombdev
  • 39
  • 1
  • 3