ProviderFactoryTest has the following:

private static class RuntimeExceptionMapper1
        extends AbstractTestExceptionMapper<RuntimeException> {

    }

    private static class RuntimeExceptionMapper2
        extends AbstractTestExceptionMapper<WebApplicationException> {

    }

private static class AbstractTestExceptionMapper<T extends RuntimeException>
        implements ExceptionMapper<T> {

        public Response toResponse(T arg0) {
            // TODO Auto-generated method stub
            return null;
        }

    }

This is identical to your example where you say the bug is expected, also note WebApplicationException is RuntimeException.

@Test
public void testExceptionMappersHierarchyWithGenerics() throws Exception {
        ServerProviderFactory pf = ServerProviderFactory.getInstance();
        RuntimeExceptionMapper1 exMapper1 = new RuntimeExceptionMapper1();
        pf.registerUserProvider(exMapper1);
        RuntimeExceptionMapper2 exMapper2 = new RuntimeExceptionMapper2();
        pf.registerUserProvider(exMapper2);
assertSame(exMapper1, pf.createExceptionMapper(RuntimeException.class, new MessageImpl())); Object webExMapper = pf.createExceptionMapper(WebApplicationException.class, new MessageImpl());
        assertSame(exMapper2, webExMapper);
    }

When RuntimeExceptionMapper2 is registered, RuntimeExceptionMapper1 is not picked for WebApplicationException. Updating the test not to register RuntimeExceptionMapper2 leads to RuntimeExceptionMapper1 being selected for WebApplicationException.

Looks like it is all correct to me, may be the issue is there in 2.7.11 but def not on the trunk/3.0.2

Cheers, Sergey

On 21/10/14 20:04, Lambert, Michael wrote:
To be clear:

This bug will only manifest itself if two exception mapper are both derived
from the same interface:

     public class AbstractMapper<T extends Throwable> implements
ExceptionMapper<T> {
         ...
     }

     public class FooMapper extends AbstractMapper<FooException> {
         ...
     }

     // ProviderFactory.ClassComparator.compare will return "0" when
BarMapper is compared to FooMapper
     public class BarMapper extends AbstractMapper<BarException> {
         ...
     }

If each exception mapper instance is derived from a DIFFERENT INTERFACE
everything works fine:

     public interface IFooMapper extends ExceptionMapper<FooException> {
         ...
     }

     public class FooMapper extends implements IFooMapper  {
         ...
     }

     public interface IBarMapper extends ExceptionMapper<BarException> {
         ...
     }

     // ProviderFactory.ClassComparator.compare will return "1" or -1 when
BarMapper is compared to FooMapper
     public class BarMapper extends implements IBarMapper {
         ...
     }



On Tue, Oct 21, 2014 at 2:34 PM, Lambert, Michael <
[email protected]> wrote:

Guys... it looks like there is a bug in ProviderFactory$ClassComparator.
Given two mappers it always ends up comparing them as if both mappers were
ExceptionMapper<Throwable>. There must be a problem in the way the
interfaces and "actual types" are derived (which is done in the
InjectionUtils class).

-Mike

On Tue, Oct 21, 2014 at 1:24 PM, Lambert, Michael <
[email protected]> wrote:

Hello gentleman!

My impression was that when implementing ExceptionMapper that the mapper
of the nearest superclass of an exception would be used if an exact
exceptionmapper match to the exception didnt exist.

For example if I created a FooException which extended BarException  I
would only have to create a BarExceptionMapper to catch and map both types
of exceptions; the BarExceptionMapper would be used when a FooException was
thrown.

The red hat docs seem to reinforce this opinion:


    -

    When any exception other than a WebApplicationException exception, or
    one of its subclasses, is thrown, the runtime will check for an appropriate
    exception mapper. An exception mapper is selected if it handles the
    specific exception thrown. If there is not an exception mapper for the
    specific exception that was thrown, the exception mapper for the nearest
    superclass of the exception is selected.



https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_Fuse/6.1/html/Apache_CXF_Development_Guide/files/RESTExceptionMapper.html

The reality is different for us however. In fact, if we create a custom
WebApplicationExceptionMapper ClientErrorExceptions are not caught by the
mapper. CXF seems to default to attempt to use whichever Mapper is the
first one we registered (e.g. if we defined a FooExceptionMapper and
registered it, CXF would attempt to use that and throw an error rather than
try to use the WebApplicationExceptionMapper).

Can someone tell me what the expected behavior is? Is my question clear?

We are using CXF version 2.7.11.

Thanks!

Mike






--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Reply via email to