5 Replies Latest reply on Jul 27, 2006 11:48 AM by Chris Hane

    @Redirect

    Chris Hane Novice

      I am trying to display an error page when an exception is thrown, specifically during a business method. I have tried the Redirect and HttpError.

      The Redirect is the closest; but if I'm not mistaken this is a browser redirect. I am wondering if it is possible to have the redirected to error page display a dynamic error message?

      Ideally I would be able to display FacesMessages on the error.xhtml page, which I don't think I can do in the @Redirect case. Any thoughts?

      The latest thread I found didn't really have a resolution: http://www.jboss.com/index.html?module=bb&op=viewtopic&t=82710

      Thanks,
      Chris....

        • 1. Re: @Redirect
          Jim Hazen Expert

          I can think of a few things you might want to try.

          1. Use @Redirect, the redirect filter and the facesMessages component combinded with a <h:messages globalOnly="true"/> in your error.xhtml.

          2. If that doesn't work (ask Gavin why not, as I'm pretty sure it should), you can outject an error message string and then use it in your error.xhtml.

          3. You can have a couple generic error pages. data_error.xhtml, security_error.xhtml, etc based on common exception types. In this scenario you wouldn't get truely dynamic content, but would be able to but up a nice message telling the user that a data error has occurred, the error has been logged and to try again in a few minutes. Which is just about all you can do when something like this happens anyway.

          • 2. Re: @Redirect
            Chris Hane Novice

            Thanks!

            I'll give your 1st option a shot tomorrow to see what I can come up with. I have not used the redirect filter explicetly before, so it'll be something new to learn about.

            In the meantime below is something that I have been playing with. Basically I am adding a new interceptor. I believe I have acheived what I want for handling the exception and returning a navigation rule that is an error page. I have yet to use a FacesMessage on it; but I don't see why it shouldn't work.

            I have not tested this extensively yet and would appreciate thoughts/concerns that anyone might see with my approach.

            Thanks,
            Chris....

            The annotation I use on the BusinessException and as a marker on the SFSB:

            @Target(TYPE)
            @Retention(RUNTIME)
            @Interceptors(ExceptionInterceptor.class)
            public @interface Redisplay {
             String viewId() default "";
            }
            


            The Interceptor I am using (for now I have named it the same as the Seam Interceptor - except it is in a different package). In fact I do most of the same stuff, except I had to add the rollback stuff which I grabbed from the SeamExceptionFilter.

            I'm not sure if I need to add the SeamExceptionFilter.endWebRequestAfterException(request) functionality.
            @Around( { ConversationalInterceptor.class, RemoveInterceptor.class, BijectionInterceptor.class })
            public class ExceptionInterceptor{
            
             private static final Log log = LogFactory.getLog(ExceptionInterceptor.class);
            
             @AroundInvoke
             public Object handleExceptions(InvocationContext invocation) throws Exception{
             boolean outermost = invocation.getContextData().get("custom.outermost.ExceptionInterceptor") == null;
             invocation.getContextData().put("custom.outermost.ExceptionInterceptor", true);
             try {
             log.fatal("===== Execute Exception Handler ==========");
             return invocation.proceed();
             } catch(Exception e) {
             log.fatal("====== Process Exception =======");
            
             if(outermost && FacesContext.getCurrentInstance() != null) {
             if(e.getClass().isAnnotationPresent(Redisplay.class)) {
             rollbackTransactionIfNecessary();
             handled(e);
             return e.getClass().getAnnotation(Redisplay.class).viewId();
             }
             }
             throw e;
             }
             }
            
             private void rollbackTransactionIfNecessary(){
             try {
             if(Transactions.isTransactionActiveOrMarkedRollback()) {
             log.info("killing transaction");
             Transactions.getUserTransaction().rollback();
             }
             } catch(Exception te) {
             log.error("could not roll back transaction", te);
             }
             }
            
             private static void handled(Exception e){
             getRequest().put("org.jboss.seam.exceptionHandled", e);
             }
            
             private static Map getRequest(){
             return FacesContext.getCurrentInstance().getExternalContext()
             .getRequestMap();
             }
            
            }
            
            


            Usage would be:
            @Name("editor")
            @Stateful
            @Redisplay
            public class Editor implements IEditor{
            
             public Fulfillment fulfill;
            
             @Begin
             public String save(){
             //persist logic //throws BusinessException
             return "save";
             }
            }
            


            Simple exception class
            @Redisplay(viewId="exceptionErrorMessage")
            public class BusinessException extends RuntimeException{
             private static final long serialVersionUID = -4422447214761623238L;
            
             public BusinessException(){
             super("Generic Business Exception");
             }
            
             public BusinessException(String msg){
             super(msg);
             }
            
            }
            


            simple navigation rule
             <navigation-rule>
             <navigation-case>
             <from-outcome>exceptionErrorMessage</from-outcome>
             <to-view-id>/error.xhtml</to-view-id>
             </navigation-case>
             </navigation-rule>
            


            • 3. Re: @Redirect
              Gavin King Master

              If you use Seam's built-in FacesMessages component, the messages will be propagated across a browser redirect.

              • 4. Re: @Redirect
                Gavin King Master

                You should also check out the functionality now available in CVS for @Redirect and @HttpError exceptions.

                • 5. Re: @Redirect
                  Chris Hane Novice


                  Gavin/CptnKirk

                  Thanks...for some reason I could not get @Redirect to work last night.

                  Now that I've sleep, it works like a charm this morning. But at least I learned more about the internals of Seam...

                  Have a good day,
                  Chris....