0
votes

I have developed a web service using cxf. In case of an error due to a request that doesn't respect the xsd schema asociated I would custom the error sent to the client. For that:

1- I have added a specific EventHandlerValidator and a specific FaultOutInterceptor in web-services.xml

<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 - I have implemented these classes:

In the handleValidator I just throw my own exception with a code and message

public class GetNewCustomerOrderIdEventHandlerValidator implements ValidationEventHandler {

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

}

}

FaultExceptionInterceptor runs for every exception thrown during webservice call. I only want to catch MyException with code ERCC_GNCOI_100 for customizing it, so:

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

}

}

However, in the interceptor I'm not able to catch my exception:

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

This line gets an unmarshalling exception:

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

In the logs I see that My exception has been thrown:

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.

Could you help me?

Thank you in advance!

Auri

2
hi can you share updated project. same issue i am facing if you share it is useful for me. mail id is [email protected] - Ranga Reddy

2 Answers

1
votes

There are two problems with the Interceptor as written.

First, you need to set the new content to the message after you make your changes. To do that, you can add the following to the handleMessage method after your code

message.setContent(Exception.class, exceptionFault);

Second, the phase you chose was too late to make changes to the Fault object. It looks like PRE_STREAM is the latest phase that allows the change. The CXF Interceptor documentation has the full list of phases.

0
votes

You can modify the message as below.

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