4

I am writing a CXF OutFaultInterceptor to throw a custom SOAP Fault message while implementing a SOAP Web service in Mule ESB version 3.8.1

The problem is for every SOAP Fault, I am getting HTTP STATUS CODE 500 from server. I will like to change the STATUS CODE based on the error type like 400 for bad request.

How to do this?

I have tried setting the MESSAGE.RESPONSE_CODE to 400 and the PHASE to PRE_STREAM and MARSHAL.

But it does not work. Below is the sample code:

public class SampleCxfFaultInterceptor extends AbstractSoapInterceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(EservicesCxfFaultInterceptor.class);

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

    public void handleMessage(SoapMessage soapMessage) throws Fault {

        Fault fault = (Fault) soapMessage.getContent(Exception.class);

        if (fault.getCause() instanceof org.mule.api.transformer.TransformerMessagingException) {

                LOGGER.error("INTERNAL ERROR OCCURED WHILE PROCESSING REQUEST);
                soapMessage.remove(Message.RESPONSE_CODE);
                soapMessage.put(Message.RESPONSE_CODE,new Integer(400));
                Element detail = fault.getOrCreateDetail();
                Element errorDetail = detail.getOwnerDocument().createElement("errorDetail");
                Element errorCode = errorDetail.getOwnerDocument().createElement("errorCode");
                Element message = errorDetail.getOwnerDocument().createElement("message");
                errorCode.setTextContent("500");
                message.setTextContent("INTERNAL_ERROR");
                errorDetail.appendChild(errorCode);
                errorDetail.appendChild(message);
                detail.appendChild(errorDetail);                

        }

    }

    private Throwable getOriginalCause(Throwable t) {
        if (t instanceof ComponentException && t.getCause() != null) {
            return t.getCause();
        } else {
            return t;
        }
    }

Expected result would be to get HTTP STATUS Code as 400.

But I am getting something like this : HTTP/1.1 500

Bibek Kr. Bazaz
  • 505
  • 10
  • 34

2 Answers2

2

Make sure you override the handleFault method as well and set the status on the HttpServletResponse object directly:

import javax.servlet.http.HttpServletResponse;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.transport.http.AbstractHTTPDestination;

public class SampleCxfFaultInterceptor extends AbstractSoapInterceptor
{
    ...

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

    private void setHttpResponseStatus(final SoapMessage message, final int status)
    {
        // skip if inbound
        if (!MessageUtils.isOutbound(message))
        {
            return;
        }

        // outbound
        final Exchange exchange = message.getExchange();
        final Message outMessage = Optional.ofNullable(exchange.getOutMessage()).orElse(exchange.getOutFaultMessage());
        final HttpServletResponse httpResponse = (HttpServletResponse) outMessage.get(AbstractHTTPDestination.HTTP_RESPONSE);
        if (httpResponse != null)
        {
            httpResponse.setStatus(status);
        }
        /*
         * else this is likely SOAP over some non-HTTP transport protocol
         */
        /*
         * Prevent any further processing by other interceptors
         */
        message.getInterceptorChain().abort();

    }

    @Override
    public void handleMessage(final SoapMessage message) throws Fault
    {
        // example setting HTTP status to 400
        setHttpResponseStatus(message, 400);
    }

    @Override
    public void handleFault(final SoapMessage message)
    {
        // example setting HTTP status to 400
        setHttpResponseStatus(message, 400);
    }
}

Verified with CXF 3.x APIs.

cdan
  • 3,470
  • 13
  • 27
  • Thanks @Cyril Dangerville for the answer. i Will try this approach and get back to you. – Bibek Kr. Bazaz Feb 17 '19 at 10:16
  • @Cyril - I dont see `SOAPMessage` has `message.getExchange();` could you please share complete file or import statements ? – PAA May 06 '20 at 12:18
  • @Ash_P I've added the import statements to my answer now. – cdan May 06 '20 at 23:59
  • @CyrilDangerville - I am still facing issue and unable to return the status other than 500. Could you please share sample code ? – PAA May 07 '20 at 08:29
  • @Ash_P Maybe apply to later phase. Could you try with 'Phase.POST_STREAM_ENDING' instead of 'Phase.PRE_STREAM'? I don't have a sample code easy to share yet, but if you have one to share already (and changing the phase fails again), I can check it out. – cdan May 09 '20 at 15:20
0

For me setting status with

httpResponse.setStatus(status);

did not work.

I've managed to find that getReponseCodeFromMessage method of AbstractHTTPDestination class was fired at the end of the sending process where status is set by Message.RESPONSE_CODE header in out message.

What i've done was setting this header in out interceptor like this:

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.springframework.stereotype.Component;
import org.apache.cxf.message.Message;

import static org.apache.cxf.phase.Phase.POST_PROTOCOL;

@Component
public class TestOutIInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
    
        public TestOutIInterceptor() {
            super(POST_PROTOCOL);
        }
    
        @Override
        public void handleMessage(SoapMessage message) throws Fault {
            int customHttpHeaderValue = 400;
            message.getExchange().getOutMessage().put(Message.RESPONSE_CODE, customHttpHeaderValue);
        }
    }
}

Http status is being set to 400

qbabor4
  • 35
  • 9