users@jersey.java.net

RE: [Jersey] Doh! Re: [Jersey] ExceptionMapper and Viewable

From: Jordi Domingo <noseya_at_hotmail.com>
Date: Fri, 16 Oct 2009 12:10:52 +0200

Thanks Paul :)

Jordi

Date: Fri, 16 Oct 2009 11:38:08 +0200
From: Paul.Sandoz_at_Sun.COM
To: users_at_jersey.dev.java.net
Subject: Re: [Jersey] Doh! Re: [Jersey] ExceptionMapper and Viewable

Hi Jordi,
Well done! Thanks for your patience and persistence. I have logged a number of issues which should hopefully resolve all the inconsistencies you have found.
I am glad i made it possible to allow Viewable instances to be declared in this manner (another developer wanted to do that, reported an issue and I fixed it) :-)
In 1.1.2 i added an EJB exception mapper. The reason i had to do this was because of the way runtime exceptions thrown from EJBs are wrapped by the EJB runtime in an EJBException:
public class EJBExceptionMapper implements ExceptionMapper<EJBException> {
    private final Providers providers;
    public EJBExceptionMapper(@Context Providers providers) { this.providers = providers; }
    public Response toResponse(EJBException exception) { final Exception cause = exception.getCausedByException(); if (cause != null) { final ExceptionMapper mapper = providers.getExceptionMapper(cause.getClass()); if (mapper != null) { return mapper.toResponse(cause); } else if (cause instanceof WebApplicationException) { return ((WebApplicationException)cause).getResponse(); } }
        return Response.serverError().build(); }}
I think there is an issue with JAX-RS that it is not possible to re-throw exceptions from an ExceptionMapper to be propagated to the container. I think i need to add a Jersey-specific feature to allow this. Issue logged:
  https://jersey.dev.java.net/issues/show_bug.cgi?id=390
I have also logged an issue with MappableContainerException to re-throw the cause instead:
  https://jersey.dev.java.net/issues/show_bug.cgi?id=391 BTW i have also dug further into result 3) and i think it may be possible to fix. Issue logged:
  https://jersey.dev.java.net/issues/show_bug.cgi?id=389


Sorry for the delay, i got a bit crazy with maven and failures deploying the app with an EJB (your web.xml was 2.4 version and I didnt noticed :)) )
I created the project from a maven archetype. Issue has been logged:
  https://jersey.dev.java.net/issues/show_bug.cgi?id=388
Paul.

On Oct 16, 2009, at 11:12 AM, Jordi Domingo wrote:Hi there :)

I made i little hack (following your example for the 500 :) ) to solve the 404 error:

public class HackDumpFilter implements ContainerResponseFilter{

    private final static Logger logger = LoggerFactory.getLogger(HackDumpFilter.class);
    
    public ContainerResponse filter(ContainerRequest request,ContainerResponse response){
        
        if(response.getStatus() == 500){
            response.setEntity(null);
            response.getHttpHeaders().put("Content-Type",null);
        }else if(response.getStatus() == 404){
            response.setEntity(new Viewable("/jsp/notFound.jsp",null));
        }
        return response;
    }
}

Hope it helps somebody else :)

Jordi

From: noseya_at_hotmail.com
To: users_at_jersey.dev.java.net
Date: Fri, 16 Oct 2009 11:02:05 +0200
Subject: RE: [Jersey] Doh! Re: [Jersey] ExceptionMapper and Viewable

Great test Paul!

But, did you try to turn your resource into an EJB ? :)

Results change:

1) Now Fails with a complete dump, escaping the servlet container
2) Same like not ejb
3) Same like not ejb

My resource's are Stateless beans :(

Sorry for the delay, i got a bit crazy with maven and failures deploying the app with an EJB (your web.xml was 2.4 version and I didnt noticed :)) )

Thanks,

Jordi

Date: Thu, 15 Oct 2009 12:50:44 +0200
From: Paul.Sandoz_at_Sun.COM
To: users_at_jersey.dev.java.net
Subject: Re: [Jersey] Doh! Re: [Jersey] ExceptionMapper and Viewable

H Jordi,
I have attached a very simple project that exercises many of the possible ways of mapping exceptions.
Hopefully it should be fairly intuitive to understand. The main index.jsp provides links to click on that results in various forms of error pages.
Results of investigation:
1) Jersey will propagate runtime exceptions to the servlet layer if those exceptions are not mapped by an ExceptionMapper. Those exceptions can then be mapped using an error page. See the error page SecurityExceptionErrorPage.jsp and the link: http://localhost:8080/exceptions/webresources/myresource/runtime?ex=java.lang.SecurityException
     supported by the following resource method:
      @Path("runtime") @GET @Produces("text/plain") public String runtimeException(@QueryParam("ex") String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class c = Class.forName(className, true, this.getClass().getClassLoader()); RuntimeException re = (RuntimeException)c.newInstance(); if (true) throw re; return "Hi there!"; }
2) Jersey will propagate checked exceptions wrapped in a MappableContainerException to the servlet layer. That exception can then be mapped using an error page and the cause can be extracted. See the error page MappableContainerException.jsp and the links:
       http://localhost:8080/exceptions/webresources/myresource/checked/ioexception http://localhost:8080/exceptions/webresources/myresource/checked/myexception
     supported by the following resource methods: @Path("checked/ioexception") @GET @Produces("text/plain") public String checkedIOException() throws IOException { if (true) throw new IOException(); return "Hi there!"; }
      public static class MyException extends Exception { }
      @Path("checked/myexception") @GET @Produces("text/plain") public String checkedMyException() throws MyException { if (true) throw new MyException(); return "Hi there!"; }

3) If Jersey sets the status code in the servlet response it is not possible for error pages to be mapped to the status code. See the links:
       http://localhost:8080/exceptions/404 http://localhost:8080/exceptions/webresources/404
    The first link is mapped to the 404 bound error page, NotFound.jsp. The the second link returns the default GF 404 error page. The first works because the Jersey servlet is not invoked.
    I verified i get the same behavior with a simple servlet if one only sets the status code to 404. However, i could get this to work if instead of calling HttpServletResponse.setStatus i call HttpServletResponse.sendError.
  Conclusions:
Result 1 is working correctly.
Result 2 could be improved by unwrapping the cause in the MappableContainerException and re-throwing the cause wrapped in ServletException.
Result 3 might be a bug in the servlet container. I am not quite sure how to work around it. For example if using sendError then any headers that have been added are ignored. It seems to me the correct behavior would be to map status codes if no entity is present (nor no bytes have been written to the response output stream).
Paul.



En tu material escolar no puede faltar el nuevo Pack de Emoticonos Vuelta al Cole ¡Descárgatelo gratis! Es muy divertido
En tu material escolar no puede faltar el nuevo Pack de Emoticonos Vuelta al Cole ¡Descárgatelo gratis! Es muy divertido
                                                _________________________________________________________________ ¿Sabías que ahora puedes hablar por Messenger desde Hotmail con todos tus contactos? Revisa tu correo mientras conversas con tus amigos. http://www.hotmail.com
--_5446345e-f6dd-4032-8653-9c0bc5b6e714_
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Verdana
}
--></style>
</head>
<body class='hmmessage'>
Thanks Paul :)<br><br>Jordi<br><br><hr id="stopSpelling">Date: Fri, 16 Oct 2009 11:38:08 +0200<br>From: Paul.Sandoz@Sun.COM<br>To: users@jersey.dev.java.net<br>Subject: Re: [Jersey] Doh! Re: [Jersey] ExceptionMapper and Viewable<br><br>Hi Jordi,<div><br></div><div>Well done! Thanks for your patience and persistence. I have logged a number of issues which should hopefully resolve all the inconsistencies you have found.</div><div><br></div><div>I am glad i made it possible to allow Viewable instances to be declared in this manner (another developer wanted to do that, reported an issue and I fixed it) :-)</div><div><br></div><div><div>In 1.1.2 i added an EJB exception mapper. The reason i had to do this was because of the way runtime exceptions thrown from EJBs are wrapped by the EJB runtime in an&nbsp;EJBException:</div><div><br></div><div><div>public class EJBExceptionMapper implements ExceptionMapper&lt;EJBException&gt; {</div><div><br></div><div>&nbsp;&nbsp; &nbsp;private final Providers providers;</div><div><br></div><div>&nbsp;&nbsp; &nbsp;public EJBExceptionMapper(@Context Providers providers) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;this.providers = providers;</div><div>&nbsp;&nbsp; &nbsp;}</div><div><br></div><div>&nbsp;&nbsp; &nbsp;public Response toResponse(EJBException exception) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;final Exception cause = exception.getCausedByException();</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (cause != null) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;final ExceptionMapper mapper = providers.getExceptionMapper(cause.getClass());</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (mapper != null) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return mapper.toResponse(cause);</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} else if (cause instanceof WebApplicationException) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return ((WebApplicationException)cause).getResponse();</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div><br></div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return Response.serverError().build();</div><div>&nbsp;&nbsp; &nbsp;}</div><div>}</div><div><br></div><div>I think there is an issue with JAX-RS that it is not possible to re-throw exceptions from an ExceptionMapper to be propagated to the container. I think i need to add a Jersey-specific feature to allow this. Issue logged:</div><div><br></div><div>&nbsp;&nbsp;<a href="https://jersey.dev.java.net/issues/show_bug.cgi?id=390">https://jersey.dev.java.net/issues/show_bug.cgi?id=390</a></div><div><br></div><div>I have also logged an issue with MappableContainerException to re-throw the cause instead:</div><div><br></div><div>&nbsp;&nbsp;<a href="https://jersey.dev.java.net/issues/show_bug.cgi?id=391">https://jersey.dev.java.net/issues/show_bug.cgi?id=391</a></div><div>&nbsp;&nbsp;</div></div></div><div>BTW i have also dug further into result 3) and i think it may be possible to fix. Issue logged:</div><div><br></div><div>&nbsp;&nbsp;<a href="https://jersey.dev.java.net/issues/show_bug.cgi?id=389">https://jersey.dev.java.net/issues/show_bug.cgi?id=389</a></div><div><br></div><div><br></div><div><br></div><div><blockquote><div class="ecxhmmessage" style="font-size: 10pt; font-family: Verdana;">Sorry for the delay, i got a bit crazy with maven and failures deploying the app with an EJB (your web.xml was 2.4 version and I didnt noticed :)) )</div></blockquote></div><div><br></div><div>I created the project from a maven archetype. Issue has been logged:</div><div><br></div><div>&nbsp;&nbsp;<a href="https://jersey.dev.java.net/issues/show_bug.cgi?id=388">https://jersey.dev.java.net/issues/show_bug.cgi?id=388</a></div><div><br></div><div>Paul.</div><div><br></div><div><br><div><div>On Oct 16, 2009, at 11:12 AM, Jordi Domingo wrote:</div><br class="ecxApple-interchange-newline"><blockquote><div class="ecxhmmessage" style="font-size: 10pt; font-family: Verdana;">Hi there :)<br><br>I made i little hack (following your example for the 500 :) ) to solve the 404 error:<br><br>public class HackDumpFilter implements ContainerResponseFilter{<br><br>&nbsp;&nbsp;&nbsp; private final static Logger logger = LoggerFactory.getLogger(HackDumpFilter.class);<br>&nbsp;&nbsp;&nbsp;<span class="ecxApple-converted-space">&nbsp;</span><br>&nbsp;&nbsp;&nbsp; public ContainerResponse filter(ContainerRequest request,ContainerResponse response){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<span class="ecxApple-converted-space">&nbsp;</span><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(response.getStatus() == 500){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; response.setEntity(null);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; response.getHttpHeaders().put("Content-Type",null);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }else if(response.getStatus() == 404){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; response.setEntity(new Viewable("/jsp/notFound.jsp",null));<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return response;<br>&nbsp;&nbsp;&nbsp; }<br>}<br><br>Hope it helps somebody else :)<br><br>Jordi<br><br><hr id="ecxstopSpelling">From:<span class="ecxApple-converted-space">&nbsp;</span><a href="mailto:noseya@hotmail.com">noseya@hotmail.com</a><br>To:<span class="ecxApple-converted-space">&nbsp;</span><a href="mailto:users@jersey.dev.java.net">users@jersey.dev.java.net</a><br>Date: Fri, 16 Oct 2009 11:02:05 +0200<br>Subject: RE: [Jersey] Doh! Re: [Jersey] ExceptionMapper and Viewable<br><br>Great test Paul!<br><br>But, did you try to turn your resource into an EJB ? :)<br><br>Results change:<br><br>1) Now Fails with a complete dump, escaping the servlet container<br>2) Same like not ejb<br>3) Same like not ejb<br><br>My resource's are Stateless beans :(<br><br>Sorry for the delay, i got a bit crazy with maven and failures deploying the app with an EJB (your web.xml was 2.4 version and I didnt noticed :)) )<br><br>Thanks,<br><br>Jordi<br><br><hr id="ecxecxstopSpelling">Date: Thu, 15 Oct 2009 12:50:44 +0200<br>From:<span class="ecxApple-converted-space">&nbsp;</span><a href="mailto:Paul.Sandoz@Sun.COM">Paul.Sandoz@Sun.COM</a><br>To:<span class="ecxApple-converted-space">&nbsp;</span><a href="mailto:users@jersey.dev.java.net">users@jersey.dev.java.net</a><br>Subject: Re: [Jersey] Doh! Re: [Jersey] ExceptionMapper and Viewable<br><br><div>H Jordi,</div><div><br></div><div>I have attached a very simple project that exercises many of the possible ways of mapping exceptions.</div><div><br></div><div>Hopefully it should be fairly intuitive to understand. The main index.jsp provides links to click on that results in various forms of error pages.</div><div><br></div><div>Results of investigation:</div><div><br></div><div>1) Jersey will propagate runtime exceptions to the servlet layer if those exceptions are not mapped by</div><div>&nbsp;&nbsp; &nbsp; an ExceptionMapper. Those exceptions can then be mapped using an&nbsp;error page.&nbsp;</div><div>&nbsp;&nbsp; &nbsp; See the error page SecurityExceptionErrorPage.jsp and the link:</div><div>&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp;<span class="ecxApple-converted-space">&nbsp;</span><a href="http://localhost:8080/exceptions/webresources/myresource/runtime?ex=java.lang.SecurityException">http://localhost:8080/exceptions/webresources/myresource/runtime?ex=java.lang.SecurityException</a></div><div><br></div><div>&nbsp;&nbsp; &nbsp; supported by the following resource method:</div><div><br></div><div>&nbsp;&nbsp; &nbsp; &nbsp;@Path("runtime")</div><div>&nbsp;&nbsp; &nbsp; &nbsp;@GET</div><div>&nbsp;&nbsp; &nbsp; &nbsp;@Produces("text/plain")</div><div>&nbsp;&nbsp; &nbsp; &nbsp;public String runtimeException(@QueryParam("ex") String className)&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throws ClassNotFoundException, InstantiationException, IllegalAccessException {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Class c = Class.forName(className, true, this.getClass().getClassLoader());</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;RuntimeException re = (RuntimeException)c.newInstance();</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (true) throw re;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return "Hi there!";</div><div>&nbsp;&nbsp; &nbsp; &nbsp;}</div><div>&nbsp;</div><div><br></div><div><div>2)&nbsp;Jersey will propagate checked exceptions wrapped in a MappableContainerException to the servlet layer.</div><div>&nbsp;&nbsp; &nbsp; That exception can then be mapped using an error page and the cause can be extracted.</div><div>&nbsp;&nbsp; &nbsp; See the error page MappableContainerException.jsp and the links:</div><div><br></div><div>&nbsp;&nbsp; &nbsp; &nbsp;<span class="ecxApple-converted-space">&nbsp;</span><a href="http://localhost:8080/exceptions/webresources/myresource/checked/ioexception">http://localhost:8080/exceptions/webresources/myresource/checked/ioexception</a></div><div>&nbsp;&nbsp; &nbsp; &nbsp;<span class="ecxApple-converted-space">&nbsp;</span><a href="http://localhost:8080/exceptions/webresources/myresource/checked/myexception">http://localhost:8080/exceptions/webresources/myresource/checked/myexception</a>&nbsp;</div><div><br></div><div>&nbsp;&nbsp; &nbsp; supported by the following resource methods:</div></div><div>&nbsp;</div><div><div>&nbsp;&nbsp; &nbsp; &nbsp;@Path("checked/ioexception")</div><div>&nbsp;&nbsp; &nbsp; &nbsp;@GET</div><div>&nbsp;&nbsp; &nbsp; &nbsp;@Produces("text/plain")</div><div>&nbsp;&nbsp; &nbsp; &nbsp;public String checkedIOException() throws IOException {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (true) throw new IOException();</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return "Hi there!";</div><div>&nbsp;&nbsp; &nbsp; &nbsp;}</div><div><br></div><div>&nbsp;&nbsp; &nbsp; &nbsp;public static class MyException extends Exception {</div><div>&nbsp;&nbsp; &nbsp; &nbsp;}</div><div><br></div><div>&nbsp;&nbsp; &nbsp; &nbsp;@Path("checked/myexception")</div><div>&nbsp;&nbsp; &nbsp; &nbsp;@GET</div><div>&nbsp;&nbsp; &nbsp; &nbsp;@Produces("text/plain")</div><div>&nbsp;&nbsp; &nbsp; &nbsp;public String checkedMyException() throws MyException {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (true) throw new MyException();</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return "Hi there!";</div><div>&nbsp;&nbsp; &nbsp; &nbsp;}</div><div><br></div><div><br></div><div>3) If Jersey sets the status code in the servlet response it is not possible for error pages to be mapped to the&nbsp;</div><div>&nbsp;&nbsp; &nbsp; status code.</div><div>&nbsp;&nbsp; &nbsp; See the links:</div><div><br></div><div>&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;<a href="http://localhost:8080/exceptions/404">http://localhost:8080/exceptions/404</a></div><div>&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;<a href="http://localhost:8080/exceptions/webresources/404">http://localhost:8080/exceptions/webresources/404</a></div><div><br></div><div>&nbsp;&nbsp; &nbsp;The first link is mapped to the 404 bound error page, NotFound.jsp. The the second link returns the default&nbsp;</div><div>&nbsp;&nbsp; &nbsp;GF 404 error page. The first works because the Jersey servlet is not invoked.</div><div><br></div><div>&nbsp;&nbsp; &nbsp;I verified i get the same behavior with a simple servlet if one only&nbsp;sets&nbsp;the&nbsp;status&nbsp;code&nbsp;to&nbsp;404.</div><div>&nbsp;&nbsp; &nbsp;However, i could get this to work if instead of calling HttpServletResponse.setStatus i call&nbsp;</div><div>&nbsp;&nbsp; &nbsp;HttpServletResponse.sendError.</div><div><br></div><div>&nbsp;&nbsp;</div><div>Conclusions:</div><div><br></div><div>Result 1 is working correctly.</div><div><br></div><div>Result 2 could be improved by unwrapping the cause in the&nbsp;MappableContainerException and re-throwing the cause wrapped in ServletException.</div><div><br></div><div>Result 3 might be a bug in the servlet container. I am not quite sure how to work around it. For example if using sendError then any headers that have been added are ignored. It seems to me the correct behavior would be to map status codes if no entity is present (nor no bytes have been written to the response output stream).</div><div><br></div><div>Paul.</div><div><br></div><div><br></div></div><div><br></div><br><hr>En tu material escolar no puede faltar el nuevo Pack de Emoticonos Vuelta al Cole<span class="ecxApple-converted-space">&nbsp;</span><a href="http://www.vivelive.com/emoticonosvueltaalcole%20%20">¡Descárgatelo gratis! Es muy divertido</a><span class="ecxApple-converted-space">&nbsp;</span><br><hr>En tu material escolar no puede faltar el nuevo Pack de Emoticonos Vuelta al Cole<span class="ecxApple-converted-space">&nbsp;</span><a href="http://www.vivelive.com/emoticonosvueltaalcole%20%20">¡Descárgatelo gratis! Es muy divertido</a></div></blockquote></div><br></div> <br /><hr />¿Para qué descargarte juegos, si tienes los más divertidos online? <a href='http://juegosonline.es.msn.com/' target='_new'>Entra ya en Juegos y prepárate para muchas horas de diversión</a></body>
</html>
--_5446345e-f6dd-4032-8653-9c0bc5b6e714_--