Skip navigation

Ed has developed a 50 minute audio-visual presentation recounting his experience in writing the book. This presentation includes audio clips from the programmers themselves, including subtitles for those for whom English is not their native language, together with insight to tie it all together.

Ed has given this presentation at numerous international developer conferences and user groups around the world, including JAX in Germany, Jazoon in Switzerland, The Developer's Conference in São Paulo, Brazil and the Rich Web Experience in U.S.A..

See the presentation online now!

Audio and Video from Ed's presentation at Jazoon 2009 is available at Parleys.com, at the URL: <http://purl.oclc.org/NET/RidingTheCrest/Show>. Unfortunately, the subtitles did not come through on this presentation, but those viewing the presentation live do see them.

Technorati Tags: edburns

My previous entry dove under the covers for JSF 2.0 and examinedcomposite component metadata. This one is far less esoteric and shows how to handle the ViewExpiredException using a new JSF feature, the ExceptionHandler, contributed byPete Muir a JSF Expert Group representative from JBoss.

JSF throws a ViewExpiredException when a postback is made to a view and, for whatever reason, that view cannot be restored. Usually this is due to a session timeout, but a custom state management solution could also cause this exception to be thrown. The default behavior in JSF2 is to show the Facelets error page saying View Expired. The default page is illustrated at right.

The default ViewExpiredException error page 

One way to fix this is to declare an<error-page> element in your web.xml, as shown here.

  1.     <error-page>
  2.         <exception-type>javax.faces.application.ViewExpiredException</exception-type>
  3.         <location>/faces/viewExpired.xhtml</location>
  4.     </error-page>
  5.  

This works well enough. You can even put JSF components on the error page if you put the proper Faces Servlet mapping in the<location> element, as shown above. If you want to do some application level manipulation in response to the exception, you'll want something different, however. In this case, a custom ExceptionHandler is just the trick. I cover this in much more detial in my upcoming book, JavaServer Faces 2.0: The Complete Reference, and the example shown in this blog entry is neatly integrated into the chapter 10 sample app. Consider this blog entry an appetizer. So delete that old web.xml (it's not needed if you have JSF2 and Servlet 3, which you get in Glassfish V3) and let's go.

First, we need to install a customExceptionHandler. This is done using the tried and true JSF decorator pattern. In this case, we place the following into the faces-config.xml. There's no annotation for this because it's relatively uncommon, and we expect advanced users to use the feature. Therefore, the EG tradeoff was to not add yet another "scan for this annotation" clause to the spec.

  1.   <factory>
  2.       <exception-handler-factory>com.sun.faces.ViewExpiredExceptionExceptionHandlerFactory</exception-handler-factory>
  3.   </factory>
  4.  

Here's the code for the class.

  1. packagecom.sun.faces;
  2.  
  3. importjavax.faces.context.ExceptionHandler;
  4. importjavax.faces.context.ExceptionHandlerFactory;
  5.  
  6. publicclassViewExpiredExceptionExceptionHandlerFactory extendsExceptionHandlerFactory {
  7.  
  8.     privateExceptionHandlerFactory parent;
  9.  
  10.     publicViewExpiredExceptionExceptionHandlerFactory(ExceptionHandlerFactory parent) {
  11.         this.parent = parent;
  12.     }
  13.  
  14.     @Override
  15.     public ExceptionHandler getExceptionHandler() {
  16.         ExceptionHandler result = parent.getExceptionHandler();
  17.         result = newViewExpiredExceptionExceptionHandler(result);
  18.  
  19.         return result;
  20.     }
  21.  
  22.  
  23. }

The interesting things happen on lines 15 - 20. This method is called once per request must return a newExceptionHandler instance each time it's called. I know the method name should becreateExceptionHandler, but we stuck with "get" for consistence with other JSF methods. On line 17, we call the real ExceptionHandlerFactory and ask it to create the instance, which we then wrap in our customViewExpiredExceptionExceptionHandlerFactory class. This is where the real interesting stuff happens.

  1. packagecom.sun.faces;
  2.  
  3. importjava.util.Iterator;
  4. importjava.util.Map;
  5. importjavax.faces.FacesException;
  6. importjavax.faces.application.NavigationHandler;
  7. importjavax.faces.application.ViewExpiredException;
  8. importjavax.faces.component.UIViewRoot;
  9. importjavax.faces.context.ExceptionHandler;
  10. importjavax.faces.context.ExceptionHandlerWrapper;
  11. importjavax.faces.context.FacesContext;
  12. importjavax.faces.event.ExceptionQueuedEvent;
  13. importjavax.faces.event.ExceptionQueuedEventContext;
  14.  
  15. publicclassViewExpiredExceptionExceptionHandler extendsExceptionHandlerWrapper {
  16.  
  17.     privateExceptionHandler wrapped;
  18.  
  19.     publicViewExpiredExceptionExceptionHandler(ExceptionHandler wrapped) {
  20.         this.wrapped = wrapped;
  21.     }
  22.  
  23.     @Override
  24.     public ExceptionHandler getWrapped() {
  25.         return this.wrapped;
  26.     }
  27.  
  28.     @Override
  29.     public void handle()throwsFacesException {
  30.         for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();i.hasNext();){
  31.             ExceptionQueuedEvent event = i.next();
  32.             ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
  33.             Throwable t = context.getException();
  34.             if (t instanceofViewExpiredException) {
  35.                 ViewExpiredException vee =(ViewExpiredException) t;
  36.                 FacesContext fc =FacesContext.getCurrentInstance();
  37.                 Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
  38.                 NavigationHandler nav =
  39.                         fc.getApplication().getNavigationHandler();
  40.                 try {
  41.                     // Push some useful stuff to the request scope for
  42.                     // use in the page
  43.                     requestMap.put("currentViewId", vee.getViewId());
  44.  
  45.                     nav.handleNavigation(fc, null, "viewExpired");
  46.                     fc.renderResponse();
  47.  
  48.                 } finally {
  49.                     i.remove();
  50.                 }
  51.             }
  52.         }
  53.         // At this point, the queue will not contain any ViewExpiredEvents.
  54.         // Therefore, let the parent handle them.
  55.         getWrapped().handle();
  56.  
  57.     }
  58. }
  59.  
  60.    
  61.  

On line 15, you see we take advantage of thejavax.faces.context.ExceptionHandlerWrapperconvenience class. JSF has lots of these wrapper classes and when you use them, you need only override the getWrapped()method to return the instance of the class you're wrapping, which is often simply passed to the constructor, as shown on lines 19 - 21. Once you override getWrapped(), you need only override those methods you're interested in. In this case, we want to override only handle(), which we do on lines 29 - 57.

We iterate over the unhandler exceptions using the iterator returned fromgetUnhandledExceptionQueuedEvents().iterator(), as shown on line 30. The ExeceptionQueuedEvent is aSystemEvent (also described in detail in my book) from which we can get the actual ViewExpiredException, which I do on line 35. I know I'm going to be ultimately showing a JSF page so I want to extract some information from the exception and place it in request scope, so I can access it via EL in the page. I do this on line 37.

On lines 45 and 46, I leverage the JSF implicit navigation system and cause the server to navigate to the "viewExpired" page. This assumes, of course, that there is aviewExpired.xhtml page out there. 2015-08-19: This also assumes that the exception we are handling is not happening during the Render Response phase. If the exception is during the Render Response phase, it is not possible to use the NavigationHandler and you need to find another approach to convey the desired information. Naturally, you could parameterize this howevere you like, context-param, annotation, whatever. Line 46 causes the intervening lifecycle phases to be skipped.

Note that we have a try-finally block here, and in the finally block, on line 49, we call remove() on the iterator. This is an important part of the ExceptionHandlerusage contract. If you handle an exception, you have to remove it from the list of unhandled exceptions. That way, we know it's safe to call getWrapped().handle() on line 55.

Finally, let's see my cheesy viewExpired.xhtml page in action, shown at left.

The customized ViewExpiredException error page 

This page is not much more visually appealing than the default one, but that's not JSF's fault! The one in the JSF2 book will look nicer. Here's the source for this cheesy one.

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2.      xmlns:f="http://java.sun.com/jsf/core">
  3. <h:head>
  4.   <title>Nice View Expired Page</title>
  5. </h:head>
  6. <h:body>
  7. <h:form>
  8.  
  9.     <p>To protect your security, we have taken the liberty of logging you
  10.     out. Those who sacrifice liberty for security deserve to have
  11.     their views expired.</p>
  12.  
  13.     <p>You were on page #{currentViewId}.  Maybe that's useful.</p>
  14.  
  15.   </h:form>
  16. </h:body>
  17. </html>
  18.    
  19.  

Note that we show the data from the exception on line 15.

This entry showed you how to programmatically intercept theViewExpiredException and do something nice with it. If you have any other state that you can show in the page, it's easy to include it in the Facelets view.

Technorati Tags: edburns

This ultra-quick blog entry shows how to use the JSF runtime to access metadata for a composite component. Note that most of the metadata is optional when creating a composite component, therefore, this entry will be of interest to tool vendors and those wishing to write composite components that stand a chance of showing up nicely in tools.

The Using Page

When showing a composite component demo, I always like to start out with the using page.

Listing 1: the using page

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <h:head>
  3.   <title>A Simple JavaServer Faces 2.0 View</title>
  4. <style type="text/css">
  5. .grayBox { padding: 8px; margin: 10px 0; border: 1px solid #CCC; background-color: #f9f9f9;  }
  6.  
  7. </h:head>
  8. <h:body>
  9.   <h:form>
  10.  
  11.     <p>Composite Component usage:</p>
  12.  
  13. <div id="cc"class="grayBox" style="border: 1px solid #090;">
  14. <my:myComponent loginAction="#{userBean.loginAction}" />
  15. </div>
  16.  
  17. <h2>Metada for This Composite Component</h2>
  18.  
  19. <div id="foo" class="grayBox" style="border: 1px solid #090;">
  20.     <pre>
  21.     <meta:printMetadata viewName="main.xhtml" libraryName="cc"
  22.                        resourceName="myComponent.xhtml"/>
  23.     </pre>
  24. </div>
  25.  
  26.  
  27.     <p><h:commandButtonvalue="submit" /></p>
  28.   </h:form>
  29. </h:body>
  30. </html>
  31.  

Line 5 declares the namespace

Filter Blog

By date: