用于管理错误的CXF自定义验证和FaultOutInterceptors

时间:2014-03-10 12:12:51

标签: cxf

我使用cxf开发了一个Web服务。如果由于请求不符合xsd架构的错误而导致错误,我会自定义发送给客户端的错误。为此:

1-我在web-services.xml中添加了一个特定的EventHandlerValidator和一个特定的FaultOutInterceptor

<jaxws:endpoint id="getNewCustomerOrderId" implementor="#getNewCustomerOrderIdWS" address="/GetNewCustomerOrderId">
    <jaxws:properties>
        <entry key="jaxb-validation-event-handler">
            <ref bean="getNewCustomerOrderIdEventHandlerValidator"/>
        </entry>
        <entry key="schema-validation-enabled" value="IN"/>
        <entry key="set-jaxb-validation-event-handler" value="true"/>
    </jaxws:properties>
    <jaxws:outFaultInterceptors>
        <ref bean="getNewCustomerOrderIdCXFFaultOutInterceptor"/>
    </jaxws:outFaultInterceptors>
</jaxws:endpoint>`enter code here

2 - 我已经实现了这些类:

在handleValidator中,我只是用代码和消息

抛出我自己的异常
public class GetNewCustomerOrderIdEventHandlerValidator implements ValidationEventHandler {

@Override
public boolean handleEvent(ValidationEvent event) {
    throw new MyException(MyExceptionCode.ERCC_GNCOI_100, event.getMessage());

}

}

FaultExceptionInterceptor为webservice调用期间抛出的每个异常运行。我只想用代码ERCC_GNCOI_100来捕获MyException以进行自定义,所以:

public class GetNewCustomerOrderIdCXFFaultOutInterceptor extends AbstractSoapInterceptor {

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

@Inject
private CreateCustomerOrderFaultExceptionService createCustomerOrderFaultExceptionService;

private static final JAXBContext jaxbContext;

static {
    try {
        jaxbContext = JAXBContext.newInstance(CreateCustomerOrderException.class);
    } catch (JAXBException e) {
        LOGGER.error(CormoranMarker.TECH, "Error during JAXBContext instantiation");
        throw new RuntimeException(e);
    }
}

public GetNewCustomerOrderIdCXFFaultOutInterceptor() {
    super(Phase.MARSHAL);
}


@Override
public void handleMessage(SoapMessage message) throws Fault {
    Fault exceptionFault = (Fault) message.getContent(Exception.class);
    exceptionFault.setMessage("My custom message");
    if (exceptionFault.getCause() instanceof MyException) {
        MyException myException = (MyException) exceptionFault
                .getCause();

        if (myException.getCode().equals(myException.ERCC_GNCOI_100)) {// validation
                                                                                                            // schema
                                                                                                            // errors
            Element elt = buildExceptionFaultDetail(cormoranFunctionalException);
            exceptionFault.setDetail(elt);
        }

    }

}

private Element buildExceptionFaultDetail(CormoranFunctionalException cormoranFunctionalException) {
    // Build custom response

}

}

然而,在拦截器中我无法捕捉到我的异常:

Fault exceptionFault = (Fault) message.getContent(Exception.class);

这一行得到一个解组异常:

Unmarshalling Error: cvc-complex-type.2.4.a: Invalid content was found starting with element 'customerOrderType1'. One of '{customerOrderID, version, customerOrderType, depositDate}' is expected. 

在日志中,我看到我的异常已被抛出:

12:32:27.338 [qtp200426125-38] ERROR c.o.c.c.e.MyException - [] - MyException : Non-respect du schéma (XSD) du WebService exposé par Cormoran : cvc-complex-type.2.4.a: Invalid content was found starting with element 'customerOrderType1'. One of '{customerOrderID, version, customerOrderType, depositDate}' is expected.

你能帮帮我吗?

提前谢谢!

AURI

2 个答案:

答案 0 :(得分:1)

Interceptor有两个问题。

首先,您需要在进行更改后将新内容设置为消息。为此,您可以在代码

后面的handleMessage方法中添加以下内容

message.setContent(Exception.class, exceptionFault);

其次,您选择的阶段为时已晚,无法更改Fault对象。看起来PRE_STREAM是允许更改的最新阶段。 CXF Interceptor documentation有完整的阶段列表。

答案 1 :(得分:0)

您可以按如下方式修改消息。

Fault exceptionFault = (Fault) message..getExchange().getContent(Exception.class);