Как установить код HTTP STATUS, отличный от 500, в CXF Out Fault Interceptor?

Я пишу CXF OutFaultInterceptor, чтобы выдать собственное сообщение об ошибке SOAP при реализации веб-службы SOAP в Mule ESB версии 3.8.1.

Проблема в том, что для каждой ошибки SOAP я получаю HTTP STATUS CODE 500 с сервера. Я хотел бы изменить КОД СОСТОЯНИЯ на основе типа ошибки, такого как 400 для неправильного запроса.

Как это сделать?

Я попытался установить MESSAGE.RESPONSE_CODE на 400 и PHASE на PRE_STREAM и MARSHAL.

Но это не работает. Ниже приведен пример кода:

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;
        }
    }

Ожидаемым результатом будет получение кода HTTP STATUS как 400.

Но я получаю что-то вроде этого: HTTP/1.1 500


person Bibek Kr. Bazaz    schedule 01.02.2019    source источник


Ответы (1)


Убедитесь, что вы также переопределили метод handleFault и установили статус объекта HttpServletResponse напрямую:

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);
    }
}

Проверено с помощью CXF 3.x API.

person cdan    schedule 09.02.2019
comment
Спасибо @Cyril Dangerville за ответ. Я попробую этот подход и свяжусь с вами. - person Bibek Kr. Bazaz; 17.02.2019
comment
@Cyril - я не вижу, чтобы SOAPMessage имел message.getExchange();, не могли бы вы поделиться полным файлом или операторами импорта? - person Pra_A; 06.05.2020
comment
@Ash_P Теперь я добавил операторы импорта в свой ответ. - person cdan; 07.05.2020
comment
@CyrilDangerville - я все еще сталкиваюсь с проблемой и не могу вернуть статус, отличный от 500. Не могли бы вы поделиться примером кода? - person Pra_A; 07.05.2020
comment
@Ash_P Может быть, применить к более позднему этапу. Не могли бы вы попробовать использовать «Phase.POST_STREAM_ENDING» вместо «Phase.PRE_STREAM»? У меня пока нет примера кода, которым легко поделиться, но если у вас уже есть такой (и изменение фазы снова не удается), я могу проверить его. - person cdan; 09.05.2020