You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@cxf.apache.org by "Sergey Beryozkin (JIRA)" <ji...@apache.org> on 2013/03/26 13:33:15 UTC
[jira] [Resolved] (CXF-4912) cxf rest client always picks the first
ResponseExceptionMapper for a method with different exception throws
[ https://issues.apache.org/jira/browse/CXF-4912?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Sergey Beryozkin resolved CXF-4912.
-----------------------------------
Resolution: Fixed
Fix Version/s: 2.5.10
2.6.7
2.7.4
2.8.0
Assignee: Sergey Beryozkin
> cxf rest client always picks the first ResponseExceptionMapper for a method with different exception throws
> -----------------------------------------------------------------------------------------------------------
>
> Key: CXF-4912
> URL: https://issues.apache.org/jira/browse/CXF-4912
> Project: CXF
> Issue Type: Bug
> Components: JAX-RS
> Affects Versions: 2.7.3
> Environment: apache-tomcat-6.0.33, jdk1.6.0_34, spring 3.2.1.RELEASE, jackson 2.1.4
> Reporter: Parwiz Rezai
> Assignee: Sergey Beryozkin
> Fix For: 2.8.0, 2.7.4, 2.6.7, 2.5.10
>
> Attachments: ClientProxyImpl.java.patch, cxftest.zip
>
>
> The selection for response mapper on client side will always pick the first
> exception listed and invoke the mapper for that guy.. it will never
> invoke Exception1ResponseMapper even though our exception is of type
> Exception1..
> throws Exception2, Exception1 <-- this will always find a mapper for Exception2
> first and use that even if our actual eexception is Exception1 in this case.
> I think the code needs to lookup the mapper based on type as well
> instead of generic first mapper found for that service.
> I have two differnt exceptions:
> {code:borderStyle=solid}
> public class Exception1 extends Exception {
> public Exception1() { }
> public Exception1(String msg) {
> super(msg);
> }
> }
> public class Exception2 extends Exception {
> public Exception2() {}
> public Exception2(String msg) {
> super(msg);
> }
> }
> {code}
> {code:title=Exception1ResponseMapper.java|borderStyle=solid}
> import com.fasterxml.jackson.core.JsonParser;
> import com.fasterxml.jackson.databind.MappingJsonFactory;
> import java.io.InputStream;
> import javax.ws.rs.core.Response;
> import org.apache.cxf.jaxrs.client.ResponseExceptionMapper;
> public class Exception1ResponseMapper implements ResponseExceptionMapper<Exception1> {
> @Override
> public Exception1 fromResponse(Response response) {
> try {
> MappingJsonFactory factory = new MappingJsonFactory();
> JsonParser parser = factory.createJsonParser((InputStream) response.getEntity());
> Exception1 exception = parser.readValueAs(Exception1.class);
> return exception;
> } catch (Exception ex) {
> return new Exception1("Could not deserialize server side exception: " + ex.getMessage());
> }
> }
> }
> {code}
> {code:title=Exception2ResponseMapper.java|borderStyle=solid}
> import com.fasterxml.jackson.core.JsonParser;
> import com.fasterxml.jackson.databind.MappingJsonFactory;
> import java.io.InputStream;
> import javax.ws.rs.core.Response;
> import org.apache.cxf.jaxrs.client.ResponseExceptionMapper;
> public class Exception2ResponseMapper implements ResponseExceptionMapper<Exception2> {
> @Override
> public Exception2 fromResponse(Response response) {
> try {
> MappingJsonFactory factory = new MappingJsonFactory();
> JsonParser parser = factory.createJsonParser((InputStream) response.getEntity());
> Exception2 exception = parser.readValueAs(Exception2.class);
> // do some specific work for exception 2 only
> return exception;
> } catch (Exception ex) {
> return new Exception2("Could not deserialize server side exception: " + ex.getMessage());
> }
> }
> }
> {code}
> so suppose one mapper does something different than the other one.
> now my service method:
> {code:borderStyle=solid}
> @Path("/cool")
> @Consumes(MediaType.APPLICATION_JSON)
> @Produces(MediaType.APPLICATION_JSON)
> public interface MyService {
> @GET
> SomeCoolObject myMethod() throws Exception2, Exception1;
> }
> @Service("myService")
> public class MyServiceImpl implements MyService {
> public SomeCoolObject myMethod() throws Exception2, Exception1 {
> throw new Exception1("hey this exception will still go exception 2 mapper.. why?");
> }
> }
> {code}
> {code:title=creating client proxy|borderStyle=solid}
> List providers = new ArrayList<Object>();
> providers.add(new com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider());
> providers.add(new Exception1ResponseMapper());
> providers.add(new Exception2ResponseMapper());
> MyService serviceProxy = JAXRSClientFactory.create("http://localhost:8080/", MyService.class, providers);
> try {
> serviceProxy.myMethod();
> } catch(Exception e) {
> // should get back Exception1 but no go
> }
> {code}
> following is exception to response mappers on service side
> {code:title=Exception mapping on server side|borderStyle=solid}
> @Provider
> public class Exception1AsResponseMapper implements ExceptionMapper<Exception1> {
> @Override
> public Response toResponse(Exception1 exception) {
> return Response.ok(exception, MediaType.APPLICATION_JSON).status(Response.Status.BAD_REQUEST).build();
> }
> }
> @Provider
> public class Exception2AsResponseMapper implements ExceptionMapper<Exception2> {
> @Override
> public Response toResponse(Exception2 exception) {
> return Response.ok(exception, MediaType.APPLICATION_JSON).status(Response.Status.BAD_REQUEST).build();
> }
> }
> {code}
> {code:xml|title=spring configs for cxf servlet}
> <import resource="classpath:META-INF/cxf/cxf.xml" />
> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
> <context:annotation-config/>
>
> <context:component-scan base-package="com.test"/>
> <jaxrs:server id="services" address="/">
> <jaxrs:serviceBeans>
> <ref bean="myService"/>
> </jaxrs:serviceBeans>
> <jaxrs:providers>
> <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/>
> <bean class="com.test.server.Exception1AsResponseMapper"/>
> <bean class="com.test.server.Exception2AsResponseMapper"/>
> </jaxrs:providers>
> <jaxrs:extensionMappings>
> <entry key="json" value="application/json" />
> </jaxrs:extensionMappings>
> </jaxrs:server>
> {code}
> on the server side the right response mapper is invoked correctly based on type of Exception thrown.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira