cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sergey Beryozkin <sberyoz...@gmail.com>
Subject Re: CXF 2.7.0 loosing original exception message after wrapping in WebApplicationException
Date Fri, 02 Nov 2012 15:28:38 GMT
Hi Duncan
On 02/11/12 12:13, Duncan Keysell (dkeysell) wrote:
> Hi Sergey,
>
> The temporary workaround is not working for me :-(. I am getting class
> cast exception. This is because in my application I also have an exception:
>
> public class XMPWebApplicationException extends WebApplicationException {
> Š.
> {
>
> And a mapper for it:
>
> public class XMPWebAppExceptionMapper implements
> ExceptionMapper<XMPWebApplicationException>  {
> Š.
> }
>
> So with the workaround in JAXRSUtils.convertFaultToResponse(T ex, Message
> inMessage) that is provided in 2.7.1-SNAPSHOT:
>
> Again the mapper and the exception satisfy the if statement and so the
> exception get changed to a javax.ws.rs.BadRequestException inside
> getWebApplicationExceptionClass method but the mapper is still expecting
> to receive a XMPWebApplicationException or a subclass. So this causes
> class cast exception.
>

I'm going to revert to the original code (the one that was there in 
2.6.x) asap. It appears I've misinterpreted what exactly we've agreed to 
awhile back on the spec list re mapping WebApplicationExceptions on the 
server side.

While I still think that there's a certain degree of ambiguity with 
application-thrown WebApplicationExceptions not being mapped to 
specialized WebApplicationException subclass mappers, example 
(WebApplicationException(404) -> NotFoundException mapper), I'm going to 
drop this code and revert to the old one.

Thanks for the patience
Sergey

>
>
> Thanks
> Duncan
>
>
>
>
>
>
>
>
> On 30/10/2012 13:47, "Sergey Beryozkin"<sberyozkin@gmail.com>  wrote:
>
>> Hi Duncan
>>
>> On 30/10/12 11:16, Duncan Keysell (dkeysell) wrote:
>>> Hi,
>>>
>>> Thanks for the update. I'm building my application against
>>> 2.7.1-SNAPSHOT
>>> now so I can try out a fix once you've had a time to look at this :-).
>>
>> I've just committed a temporarily fix. I'm looking for the final
>> confirmation on whether this mapping of base WebApplicationExceptions to
>> WebApplicationException subclass mappers will be actually supported, if
>> yes - then I will optimize the current solution, if not - I will revert
>> to the original code - I'll keep you up to date
>>
>> Thanks for reporting this issue,
>>
>> Sergey
>>
>>>
>>> Thanks
>>> Duncan
>>>
>>> On 25/10/2012 18:15, "Sergey Beryozkin"<sberyozkin@gmail.com>   wrote:
>>>
>>>> On 25/10/12 17:17, Sergey Beryozkin wrote:
>>>>> Hi Duncan
>>>>>
>>>>> Thanks for the analysis, comments inline
>>>>>
>>>>> On 25/10/12 14:18, Duncan Keysell (dkeysell) wrote:
>>>>>> Hi,
>>>>>>
>>>>>> In the application code for my REST service all the exceptions are
>>>>>> wrapped in WebApplicationException and then thrown. I have a test
>>>>>> case
>>>>>> to check this is working and below is the resource called in that
>>>>>> test
>>>>>> case:
>>>>>>
>>>>>>
>>>>>> @GET
>>>>>>
>>>>>> @Path("/plainBad")
>>>>>>
>>>>>> public MgmtResponse throwPlainException() throws Exception {
>>>>>>
>>>>>> throw new WebApplicationException(new Exception("Some lame
>>>>>> message"));
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>> I have an exception mapper (implementation of
>>>>>> ExceptionMapper<WebApplicationException>) that creates the
Response.
>>>>>> This Response contains the message from the original exception as
>>>>>> well
>>>>>> as the exception type, up until I have moved to use 2.7.0.
>>>>>>
>>>>>>
>>>>>> This is due to a change in the JAXRSUtils.convertFaultToResponse(T,
>>>>>> Message) message between 2.6.2 and 2.7.0.
>>>>>>
>>>>>>
>>>>>> Previously the method was (line 1217):
>>>>>>
>>>>>>
>>>>>> public static<T extends Throwable>   Response convertFaultToResponse(T
>>>>>> ex, Message inMessage) {
>>>>>>
>>>>>>
>>>>>>
>>>>>> ExceptionMapper<T>   mapper =
>>>>>>
>>>>>>
>>>>>>
>>>>>> ProviderFactory.getInstance(inMessage).createExceptionMapper(ex.getCla
>>>>>> ss
>>>>>> (),
>>>>>> inMessage);
>>>>>>
>>>>>> if (mapper != null) {
>>>>>>
>>>>>> try {
>>>>>>
>>>>>> return mapper.toResponse(ex);
>>>>>>
>>>>>> } catch (Exception mapperEx) {
>>>>>>
>>>>>> mapperEx.printStackTrace();
>>>>>>
>>>>>> return Response.serverError().build();
>>>>>>
>>>>>> }
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>>
>>>>>> return null;
>>>>>>
>>>>>>
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>> And now it is (line 1352):
>>>>>>
>>>>>>
>>>>>> @SuppressWarnings("unchecked")
>>>>>>
>>>>>> public static<T extends Throwable>   Response convertFaultToResponse(T
>>>>>> ex, Message inMessage) {
>>>>>>
>>>>>> ProviderFactory factory = ProviderFactory.getInstance(inMessage);
>>>>>>
>>>>>> ExceptionMapper<T>   mapper = factory.createExceptionMapper(ex,
>>>>>> inMessage);
>>>>>>
>>>>>> if (mapper != null) {
>>>>>>
>>>>>> if (ex.getClass() == WebApplicationException.class
>>>>>>
>>>>>> &&   mapper.getClass() != WebApplicationExceptionMapper.class)
{
>>>>>>
>>>>>> WebApplicationException webEx = (WebApplicationException)ex;
>>>>>>
>>>>>> Class<?>   exceptionClass =
>>>>>> getWebApplicationExceptionClass(webEx.getResponse(),
>>>>>>
>>>>>> WebApplicationException.class);
>>>>>>
>>>>>> if (exceptionClass != WebApplicationException.class) {
>>>>>>
>>>>>> try {
>>>>>>
>>>>>> Constructor<?>   ctr = exceptionClass.getConstructor(Response.class);
>>>>>>
>>>>>> ex = (T)ctr.newInstance(webEx.getResponse());
>>>>>>
>>>>>> } catch (Exception ex2) {
>>>>>>
>>>>>> ex2.printStackTrace();
>>>>>>
>>>>>> return Response.serverError().build();
>>>>>>
>>>>>> }
>>>>>>
>>>>>> }
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>>
>>>>>> try {
>>>>>>
>>>>>> return mapper.toResponse(ex);
>>>>>>
>>>>>> } catch (Exception mapperEx) {
>>>>>>
>>>>>> mapperEx.printStackTrace();
>>>>>>
>>>>>> return Response.serverError().build();
>>>>>>
>>>>>> } finally {
>>>>>>
>>>>>> factory.clearExceptionMapperProxies();
>>>>>>
>>>>>> }
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>>
>>>>>> return null;
>>>>>>
>>>>>>
>>>>>>
>>>>>> }
>>>>>>
>>>>>>
>>>>>>
>>>>>> So the problem is that the exception 'ex' and my 'mapper' pass the
if
>>>>>> statement (line 1356):
>>>>>>
>>>>>>
>>>>>> if (ex.getClass() == WebApplicationException.class
>>>>>>
>>>>>> &&   mapper.getClass() != WebApplicationExceptionMapper.class)
>>>>>>
>>>>>>
>>>>>> And then the ex gets over written and I loose all the details that
>>>>>> the
>>>>>> original WebApplicationException was holding. Shouldn't the if
>>>>>> statement be changed not to allow any mapping implementing
>>>>>> ExceptionMapper<WebApplicationException>? Is there some workaround
>>>>>> for
>>>>>> this?
>>>>>>
>>>>> I'm going to work on test case shortly. The actual change was needed
>>>>> to
>>>>> get new JAX-RS 2.0 exceptions such as NotFoundException (alternative
>>>>> to
>>>>> new WebApplicationException(404)), etc, captured by existing
>>>>> ExceptionMapper<WebApplicationException>   mappers if no a mapper
like
>>>>> ExceptionMapper<NotFoundException>   exists, but a regression has
been
>>>>> introduced.
>>>>>
>>>> It is the other way around, if we have
>>>> ExceptionMapper<NotFoundException>   but the code has thrown "new
>>>> WebApplicationException(404)" then NotFoundExceptionMapper should be
>>>> chosen given that NotFoundException extends WebApplicationException.
>>>>
>>>> I can see that the exception is lost in all the cases where the origin
>>>> ex is WebApplicationException and the mapper is not known to CXF, it is
>>>> really to do with a wrong constructor check, still looking, but will
>>>> likely fix early next week due to the long weekend coming in
>>>>
>>>> The tests  show that if you register say
>>>> ExceptionMapper<InternalServerErrorException>   and throw
>>>> InternalServerErrorException then no cause exception is lost, in
>>>> meantime I'll have a look at the other cases
>>>>
>>>> Cheers, Sergey
>>>>
>>>>> The possible workarounds: provide
>>>>> ExceptionMapper<ServerErrorException>
>>>>> or extend CXF WebApplicationExceptionMapper. Another one is CXF
>>>>> specific
>>>>> and it is to register a custom CXF invoker which will get a chance to
>>>>> capture the original WebApplicationException, I guess it should be the
>>>>> last resort option, I'll provide more info if doing other exception
>>>>> mappers won't help
>>>>>
>>>>> Thanks, Sergey
>>>>>
>>>>>
>>>>>
>>>>>>
>>>>>>
>>>>>> Thanks
>>>>>>
>>>>>> Duncan
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Sergey Beryozkin
>>>>
>>>> Talend Community Coders
>>>> http://coders.talend.com/
>>>>
>>>> Blog: http://sberyozkin.blogspot.com
>>>
>


-- 
Sergey Beryozkin

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

Blog: http://sberyozkin.blogspot.com

Mime
View raw message