Hi Mandy
In this case, an exception is thrown from a custom CXF out interceptor
(not part of the out JAX-RS chain) and as we discussed earlier, the
mapping of such exceptions is not supported in earlier CXF versions, but
only starting from CXF 2.7.8 (see the link I posted in another message).
However in this case in the default mapping won't help because
RuntimeException is thrown, CXF JAX-RS only has a default
WebApplicationException mapper.
Now, assuming it is CXF 2.7.8(-SNAPSHOT) and if no ExceptionMapper is
available, or earlier CXF version, then we have a not-mapped exception
escaping as per JAX-RS spec rules, with HTTP you'd get 500 indeed, but
with LocalTransport you have that RuntimeException escaping directly
into the client.
In my tests I was not getting NPE, I was getting the original
RuntimeException wrapped in a client exception, but that is not good
enough because I agree you should get a populated Response with 500 status,
Given that it is LocalTransport direct dispatch client which has an
escaped server exception, the only way to intercept it internally and
adapt to JAX-RS Response is to use in fault interceptors on the client
side, which as it happens have not been supported by JAX-RS client
runtime before :-), so we looked at how it can be done initially and now
it is supported starting from CXF 2.7.8 as well, see this test:
http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLocalTransportTest.java
#testProxyServerInFaultDirectDispatch
#testProxyServerOutFault()
Note, the out fault is actually mapped correctly, the in fault
interceptor is not even needed there, only needed in
#testProxyServerInFaultDirectDispatch
Cheers, Sergey
On 29/09/13 22:37, Mandy Warren wrote:
Hi,
I am running some unit tests using local transport to see what happens when
an interceptor throws a Fault. I was expecting to get a Response back with
a status code of 500 but instead I get this:
javax.ws.rs.client.ClientException: java.lang.NullPointerException
at
org.apache.cxf.jaxrs.client.AbstractClient.setResponseBuilder(AbstractClient.java:374)
at
org.apache.cxf.jaxrs.client.WebClient.handleResponse(WebClient.java:1101)
at
org.apache.cxf.jaxrs.client.WebClient.doResponse(WebClient.java:1088)
at
org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1038)
at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:858)
at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:832)
at org.apache.cxf.jaxrs.client.WebClient.invoke(WebClient.java:395)
at org.apache.cxf.jaxrs.client.WebClient.get(WebClient.java:574)
My test setup is as follows:-
I declare a DummyInterceptor which throws a Fault..
public class DummyInterceptor extends AbstractPhaseInterceptor<Message> {
public DummyInterceptor() {
super(Phase.MARSHAL);
}
public void handleMessage(Message message) throws Fault {
throw new Fault(new RuntimeException("hello from runtime
exception"));
}
}
My test case configures local transport & registers the DummyInterceptor
@Before
public void setup() {
// enable local transport
bus = BusFactory.newInstance().createBus();
LocalTransportFactory localTransport = new LocalTransportFactory();
DestinationFactoryManager dfm = bus
.getExtension(DestinationFactoryManager.class);
dfm.registerDestinationFactory("
http://schemas.xmlsoap.org/soap/http",
localTransport);
dfm.registerDestinationFactory(
"http://schemas.xmlsoap.org/wsdl/soap/http",
localTransport);
dfm.registerDestinationFactory(
"http://cxf.apache.org/bindings/xformat", localTransport);
dfm.registerDestinationFactory(
"http://cxf.apache.org/transports/local", localTransport);
ConduitInitiatorManager extension = bus
.getExtension(ConduitInitiatorManager.class);
extension.registerConduitInitiator(
"http://cxf.apache.org/transports/local", localTransport);
extension.registerConduitInitiator(
"http://schemas.xmlsoap.org/wsdl/soap/http",
localTransport);
extension.registerConduitInitiator(
"http://schemas.xmlsoap.org/soap/http", localTransport);
extension.registerConduitInitiator(
"http://cxf.apache.org/bindings/xformat", localTransport);
// create a local endpoint
sf = new JAXRSServerFactoryBean();
sf.setBus(bus);
sf.setAddress(LOCAL_ADDRESS);
sf.setServiceBean(new SimpleRestServiceImpl());
sf.setServiceClass(SimpleRestServiceImpl.class);
}
@After
public void teardown() throws Exception {
if (null != jaxrsServer) {
// explicitly stop server
jaxrsServer.destroy();
}
if (null != bus) {
// shutdown the bus
bus.shutdown(false);
}
}
@Test
public void
testExceptionWhichOccursWithinAnOutboundFrameworkInterceptorReturnsAppropriateException()
throws Exception {
// register the DummyInterceptor which throws an exception
List<Interceptor<? extends Message>> outInterceptors = new
ArrayList<Interceptor<? extends Message>>(
1);
outInterceptors.add(new DummyInterceptor());
sf.setOutInterceptors(outInterceptors);
// start the server
jaxrsServer = sf.create();
WebClient client = WebClient.create(LOCAL_ADDRESS);
WebClient.getConfig(client).getRequestContext()
.put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);
try {
Response response = client
.path("v1/greetings/aveeeeename")
.type(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.get(Response.class);
assertEquals(500, response.getStatus());
} finally {
if (null != client) {
client.close();
}
}
}
I am using apache cxf version 2.7.4
Any help much appreciated
Thanks
Mandy
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com