Hi Sergey, Thanks everything is working fine with the latest 2.7.1-SNAPSHOT.
Thanks Duncan On 05/11/2012 10:39, "Sergey Beryozkin" <[email protected]> wrote: >Hi, > >I've reverted to the original code, but also updated the RS code to >throw WAE subclasses where possible as per the spec, example, >NotFoundException will be thrown instead of >WebApplicationException(404), etc > >Thanks, Sergey > > >On 02/11/12 15:28, Sergey Beryozkin wrote: >> 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"<[email protected]> 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"<[email protected]> 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.get >>>>>>>>Cla >>>>>>>> >>>>>>>> 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
