Good to know Sergey we will look at it again today. Definitely experiencing
the behavior I described so we will look for some delta between our code
and the test
On Oct 22, 2014 5:50 AM, "Sergey Beryozkin" <[email protected]> wrote:
> 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
>