You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Alex Porras <al...@twelve17.com> on 2011/09/06 22:12:24 UTC

ExceptionMapper choosing the wrong mapper

I am working on an app that has some custom exceptions in a class
hierarchy, rooted from RuntimeException.  For use in CXF, they contain
complementary ExceptionMapper classes. Basically, you are looking at a
parallel hierarchy:

(abstract)BaseRuntimeException
FooException
BarException


(abstract) BaseRuntimeExceptionMapper <T extends BaseRuntimeException>
FooExceptionMapper<FooException>
BarExceptionMapper <BarException>


What is happening is that when FooException is thrown in the
application, it is being handled by BarExceptionMapper.

I did some digging around and saw that
org.apache.cxf.jaxrs.provider.ProviderFactory.doCreateExceptionMapper()
calls sort() on the list of exceptionmappers, using
ExceptionMapperComparator, then returns the first mapper on the list.

I don't quite have my head wrapped around the mechanism behind it, but
what is happening is that the comparator is calling
"InjectionUtils.getActualType(types1[0]);", which returns
BaseRuntimeException for both classes, and thus, effectively, no
sorting is done.

Am I perhaps not using the ExceptionMapper mechanism in the way it was
intended?  Any help would be appreciated.

Alex

Re: ExceptionMapper choosing the wrong mapper

Posted by Alex Porras <al...@twelve17.com>.
On Tue, Sep 6, 2011 at 4:12 PM, Alex Porras <al...@twelve17.com> wrote:
> [snip]
>  Basically, you are looking at a
> parallel hierarchy:


Bleh, my mistake.  I wasn't clear enough in describing the hierarchy. It's:

(abstract)BaseRuntimeException
FooException extends BaseRuntimeException
BarException extends BaseRuntimeException

(In other words, FooException and BarException are both direct
children of BaseRuntimeException.)  The same applies to the exception
classes:

(abstract) BaseRuntimeExceptionMapper <T extends BaseRuntimeException>
FooExceptionMapper extends BaseRuntimeExceptionMapper<FooException>
BarExceptionMapper extends BaseRuntimeExceptionMapper<BarException>


HTH,

Alex

Re: ExceptionMapper choosing the wrong mapper

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 02/11/11 20:36, douglassparker wrote:
> On further reflection, this may or may not be a problem with the exception
> mappers.  I was trying to send back a Response.Status.BAD_REQUEST when the
> client sends malformed XML.  But I suppose the issue could be that the CXF
> interceptors are throwing the exception and the exception mappers never have
> a chance to handle it.  The specific exception is
> com.ctc.wstx.exc.WstxUnexpectedCharException.  This is a subclass of
> XMLStreamException, so I was hoping there was a way to map it the way I
> wanted.
>
Where is this exception originating from, from JAXBElementProvider ?
If so then it will be wrapped in the instance of 
WebApplicationException, so what you can do in that case is to register 
a custom WebApplicationException mapper

Sergey

> --
> View this message in context: http://cxf.547215.n5.nabble.com/ExceptionMapper-choosing-the-wrong-mapper-tp4775881p4959271.html
> Sent from the cxf-user mailing list archive at Nabble.com.


Re: ExceptionMapper choosing the wrong mapper

Posted by douglassparker <do...@me.com>.
On further reflection, this may or may not be a problem with the exception
mappers.  I was trying to send back a Response.Status.BAD_REQUEST when the
client sends malformed XML.  But I suppose the issue could be that the CXF
interceptors are throwing the exception and the exception mappers never have
a chance to handle it.  The specific exception is
com.ctc.wstx.exc.WstxUnexpectedCharException.  This is a subclass of
XMLStreamException, so I was hoping there was a way to map it the way I
wanted.   

--
View this message in context: http://cxf.547215.n5.nabble.com/ExceptionMapper-choosing-the-wrong-mapper-tp4775881p4959271.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: ExceptionMapper choosing the wrong mapper

Posted by douglassparker <do...@me.com>.
I have a similar, but different issue.  I have an Exception mapper for
javax.xml.stream.XMLStreamException.  I also have other mappers and a
fallback mapper for Throwable.  If an exception is thrown that is a SUBCLASS
of XmlStreamException, it is handled by the Throwable Mapper, and not by the
XmlStreamException mapper.  I don't want to create mappers for every
concrete exception type.  Exception mappers are supposed to respect
inheritance.  Any suggestions?  

--
View this message in context: http://cxf.547215.n5.nabble.com/ExceptionMapper-choosing-the-wrong-mapper-tp4775881p4959214.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: ExceptionMapper choosing the wrong mapper

Posted by Alex Porras <al...@twelve17.com>.
On Wed, Sep 7, 2011 at 6:21 AM, Sergey Beryozkin <sb...@gmail.com> wrote:
> Hi Alex
>
> I think that has to be improved on the CXF side - I'll try to get to it asap
>

Hi Sergey,

Thanks for your reply.  Note that the workaround is easy and not too
ugly, so rush! :)

Regards,

Alex

Re: ExceptionMapper choosing the wrong mapper

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Alex

On Tue, Sep 6, 2011 at 10:13 PM, Alex Porras <al...@twelve17.com> wrote:
> On Tue, Sep 6, 2011 at 4:12 PM, Alex Porras <al...@twelve17.com> wrote:
>
>> What is happening is that when FooException is thrown in the
>> application, it is being handled by BarExceptionMapper.
>
> I believe I have found the solution.  Despite the child exception
> mappers specifying a generic type required by the parent (abstract)
> exception mapper (which implements ExceptionMapper), each child class
> also needs to include a "implements ExceptionMapper<T>" declaration,
> to prevent CXF from bubbling up to the base interface implementation
> declaration and using that class's generic type.
>
> Thus, my exception mapper hierarchy is now:
>
> (abstract) BaseRuntimeExceptionMapper <T extends BaseRuntimeException>
> FooExceptionMapper extends BaseRuntimeExceptionMapper<FooException>
> implements ExceptionMapper<FooException>
> BarExceptionMapper extends
> BaseRuntimeExceptionMapper<BarException>implements
> ExceptionMapper<BarException>
>
> This seems a little repetitive, but I think it makes sense given the
> route that CXF seems to be using to determine the exception type.
>

I think that has to be improved on the CXF side - I'll try to get to it asap

thanks, Sergey


> Hope this helps someone else!
>
> Alex
>



-- 
Sergey Beryozkin

http://sberyozkin.blogspot.com
Talend - http://www.talend.com

Re: ExceptionMapper choosing the wrong mapper

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Alex,

Sorry for a delay, I've finally tried to get more optimized hierarchies 
supported but I'm not sure we can get a handle on this top-level 
parameter, here is the test code:

private static class RuntimeExceptionMapper1
         extends AbstractTestExceptionMapper<RuntimeException> {

     }

     private static class RuntimeExceptionMapper2
         extends AbstractTestExceptionMapper<WebApplicationException> {

     }

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

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

     }

ProviderFactory would get a list of generic interfaces and the bounds 
from then and the best we can get to is 'RuntimeException' which is 
obtained from "<T extends RuntimeException>".

Any idea on how to get to say "WebApplicationException" which is visible 
in the code at least in 
"AbstractTestExceptionMapper<WebApplicationException>".
I'm wondering if it is even available at the runtime,

Sergey



On 06/09/11 22:13, Alex Porras wrote:
> On Tue, Sep 6, 2011 at 4:12 PM, Alex Porras<al...@twelve17.com>  wrote:
>
>> What is happening is that when FooException is thrown in the
>> application, it is being handled by BarExceptionMapper.
>
> I believe I have found the solution.  Despite the child exception
> mappers specifying a generic type required by the parent (abstract)
> exception mapper (which implements ExceptionMapper), each child class
> also needs to include a "implements ExceptionMapper<T>" declaration,
> to prevent CXF from bubbling up to the base interface implementation
> declaration and using that class's generic type.
>
> Thus, my exception mapper hierarchy is now:
>
> (abstract) BaseRuntimeExceptionMapper<T extends BaseRuntimeException>
> FooExceptionMapper extends BaseRuntimeExceptionMapper<FooException>
> implements ExceptionMapper<FooException>
> BarExceptionMapper extends
> BaseRuntimeExceptionMapper<BarException>implements
> ExceptionMapper<BarException>
>
> This seems a little repetitive, but I think it makes sense given the
> route that CXF seems to be using to determine the exception type.
>
> Hope this helps someone else!
>
> Alex


-- 
Sergey Beryozkin

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

Blog: http://sberyozkin.blogspot.com

Re: ExceptionMapper choosing the wrong mapper

Posted by Alex Porras <al...@twelve17.com>.
On Tue, Sep 6, 2011 at 4:12 PM, Alex Porras <al...@twelve17.com> wrote:

> What is happening is that when FooException is thrown in the
> application, it is being handled by BarExceptionMapper.

I believe I have found the solution.  Despite the child exception
mappers specifying a generic type required by the parent (abstract)
exception mapper (which implements ExceptionMapper), each child class
also needs to include a "implements ExceptionMapper<T>" declaration,
to prevent CXF from bubbling up to the base interface implementation
declaration and using that class's generic type.

Thus, my exception mapper hierarchy is now:

(abstract) BaseRuntimeExceptionMapper <T extends BaseRuntimeException>
FooExceptionMapper extends BaseRuntimeExceptionMapper<FooException>
implements ExceptionMapper<FooException>
BarExceptionMapper extends
BaseRuntimeExceptionMapper<BarException>implements
ExceptionMapper<BarException>

This seems a little repetitive, but I think it makes sense given the
route that CXF seems to be using to determine the exception type.

Hope this helps someone else!

Alex