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
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.