Phil Webb's Blog

Random thoughts from a software developer

Archive for the ‘Integrating Spring & JavaServer Faces’ Category

Integrating Spring & JavaServer Faces : Exception Handling

with one comment

Most JSF developers will be familiar the “An Error Occurred” page that gets displayed when an unexpected exception is thrown somewhere their code. This page is really useful when developing but is not something you usually want for a production application. You generally have a couple of options when it comes to replacing this page with stock JSF; you can use define some HTML <error-page> elements in your web.xml or you can write a custom ExceptionHandler.

Neither option is ideal for a Spring developer, <error-page> elements tend to be too simplistic and it is hard to use Spring concepts, such as dependency injection, with custom ExceptionHandlers. Luckily both JSF and Spring are very extensible frameworks so a project that I have been working on to integrate the technologies can offer some compelling alternatives.

The first option available allows ExceptionHandlers to be registered as Spring beans. Rather than use the existing javax.faces.context.ExceptionHandler class a new org.springframework.springfaces.exceptionhandler.ExceptionHandler interface is available. The interface is pretty straight forward, it defines a single handle method that should return true if the exception has been handled. The interface uses a generic to limit the types of exception considered.

public interface ExceptionHandler<E extends Throwable> {
  boolean handle(E exception, ExceptionQueuedEvent event) throws Exception;
}

All relevant beans beans that implement the ExceptionHandler interface will be consulted when an exception occurs from JSF. The first handler to return true will ‘win’ and subsequent handlers will not be called. You can use the org.springframework.core.Ordered interface or the @Ordered annotation if you need to sort your handlers. Of course, now that exception handlers are regular Spring beans, you can use all the standard Spring functionality such a dependency injection and AOP.

Now that we have basic exception handler hooks we can go on to offer a couple of useful implementations:

Sometimes the best way to handle certain exceptions is to simply show a message and remain on the current screen. For example, suppose a service throws TooManyResultsException when search queries are too broad. A simple message telling the user to ‘try again with more precise terms’ might be the only exception handling required. The org.springframework.springfaces.exceptionhandler.ObjectMessageExceptionHandler class builds on previous work that maps Objects to messages. Include an entry in your Spring MessageSource with the fully qualified name of the Exception as the key and a FacesMessage will be shown if the exception is thrown.

com.mycorp.search.TooManyResultsException=Too many results found, please try again with more precise search terms

You can easily map any number of exceptions to messages, you can even refer to properties of the exception using ‘{property}‘ placeholders in your message string. Messages can be displayed on the screen using standard JSF techniques (usually a <h:messages/> component).

Support for quickly mapping exceptions to messages is nice but it won’t be enough for a lot of applications and writing ExceptionHandler beans can quickly become tiresome. The final optional available is org.springframework.springfaces.mvc.exceptionhandler.DispatcherExceptionHandler. The DispatcherExceptionHandler provides a bridge between JSF and Spring MVC that allows you to use @ExceptionHandler annotations in your @Controllers as you would with any other Spring MVC application. Methods annotated with @ExceptionHandler are really versatile and can have very flexible signatures; you can deal with exceptions directly or return a view that should be rendered:

@ExceptionHandler
public String handle(ExampleException e) {
  return "redirect:errorpage";
}

Using @ExceptionHandler annotations with Spring MVC is a very natural fit and there have been numerous articles written on the subject. Hopefully existing JSF developers will find the Spring MVC programming style an attractive alternative to standard JSF.

Please take a look at the other articles in this series and if you want to examine the exception handing code the ‘org.springframework.springfaces.exceptionhandler’ and ‘org.springframework.springfaces.mvc.exceptionhandler’ packages are a good place to start.

Written by Phillip Webb

June 29, 2012 at 8:34 am

Integrating Spring & JavaServer Faces : Improved Templating

with 3 comments

With the release of version 2.0 Facelet templating became a core part of the JSF specification. Using <ui:composition> and <ui:decorate> tags it becomes pretty easy to build up complicated pages whilst still keeping your mark-up clean. Templates are particularly useful when creating HTML forms but, unfortunately, do tend to cause repetition in your xhtml files, breaking the DRY (Don’t Repeat Yourself) principal of good software design. As part of a project to provide deeper integration between JSF and Spring I have developed a couple of new components that aim to make templating easier. Before diving into the new components, lets look at how a typical form might be built up using standard JSF templates.

Often the initial starting point with form templates is to add some boiler plate surround to each input. Often you need extra <div> or <span> tags for your css to use. Here is a typical example:

<!-- /WEB-INF/pages/entername.xhtml -->
<ui:decorate template="/WEB-INF/layout/form.xhtml">
  <h:inputText id="firstName" label="First Name" value="#{bean.firstName}"/>
  <ui:param name="label" value="First Name"/>
  <ui:param name="for" value="firstName"/>
</ui:decorate>
<ui:decorate template="/WEB-INF/layout/form.xhtml">
  <h:inputText id="lastName" label="Last Name" value="#{bean.lastName}"/>
  <ui:param name="label" value="Last Name"/>
  <ui:param name="for" value="lastName"/>
</ui:decorate>
<!-- Many additional form elements -->
<!-- /WEB-INF/layout/form.xhtml -->
<ui:composition>
  <div class="formElement">
    <span class="formLabel">
      <h:outputLabel for="#{for}" label="#{label}">
    </span>
    <ui:insert/>
  </div>
</ui:composition>

Here we can see that each item on the form is contained within a <div> and form labels are wrapped in an additional <span>. There is already some repetition in the mark-up, with the “for” parameter mirroring the component ID. I have also given each <h:inputText> element a label attribute
for better validation error messages, this is repeated in the “label” <ui:param>. Things start getting worse if we want to mark required fields with an asterisk:

<!-- /WEB-INF/pages/entername.xhtml -->
<ui:decorate template="/WEB-INF/layout/form.xhtml">
  <h:inputText id="firstName" label="First Name" value="#{bean.firstName}" required="false"/>
  <ui:param name="label" value="First Name"/>
  <ui:param name="for" value="firstName"/>
  <ui:param name="showAsterisk" value="false"/>
</ui:decorate>
<ui:decorate template="/WEB-INF/layout/form.xhtml">
  <h:inputText id="lastName" label="Last Name" value="#{bean.lastName}" required="true"/>
  <ui:param name="label" value="Last Name"/>
  <ui:param name="for" value="lastName"/>
  <ui:param name="showAsterisk" value="true"/>
</ui:decorate>
<!-- Many additional form elements -->
<!-- /WEB-INF/layout/form.xhtml -->
<ui:composition>
  <div class="formElement">
    <span class="formLabel">
      <h:outputLabel for="#{for}" label="#{label}#{showAsterisk ? ' *' : ''}">
    </span>
    <ui:insert/>
  </div>
</ui:composition>

It’s pretty frustrating that we need to pass <ui:param> items that duplicate attributes already specified on the <h:inputText>. It is easy to see how, even for relatively small forms, we are going to end up with a lot of duplication in our mark-up. What we need is a way to get information about the inserted component inside the template, even though we don’t know what type of component it will be. What we need is <s:componentInfo>.

The <s:componentInfo> component exposes a variable containing information about the inserted component. This information includes the label, the component clientID and if the component is required. By inspecting the inserted item we can remove a lot of duplication:

<!-- /WEB-INF/pages/entername.xhtml -->
<ui:decorate template="/WEB-INF/layout/form.xhtml">
  <h:inputText id="firstName" label="First Name" value="#{bean.firstName}" required="false"/>
</ui:decorate>
<ui:decorate template="/WEB-INF/layout/form.xhtml">
  <h:inputText id="lastName" label="Last Name" value="#{bean.lastName}" required="true"/>
</ui:decorate>
<!-- Many additional form elements -->
<!-- /WEB-INF/layout/form.xhtml -->
<ui:composition>
  <s:componentInfo var="info">
    <div class="formElement">
      <span class="#{info.valid ? 'formLabel' : 'formErrorLabel'}">
        <h:outputLabel for="#{info.for}" label="#{info.label}#{info.required ? ' *' : ''}">
      </span>
      <ui:insert/>
    </div>
  </s:componentInfo>
</ui:composition>

Something else that we can now do is tell if the inserted component has failed validation. Notice that the example above will pick the “formErrorLabel” CSS class for components that are not valid.

One interesting feature of having the new <s:componentInfo> component is that all the <ui:decorate> tags become identical. We have removed all the repetition inside the tag, but the tag itself is still repeated many times. Here we have one more trick that can help by introducing a new <s:decorateAll> tag. Using <s:decorateAll> allows use to apply a template once for every child component. Here is the updated form mark-up:

<!-- /WEB-INF/pages/entername.xhtml -->
<s:decorateAll template="/WEB-INF/layout/form.xhtml">
  <h:inputText id="firstName" label="First Name" value="#{bean.firstName}" required="false"/>
  <h:inputText id="lastName" label="Last Name" value="#{bean.lastName}" required="true"/>
  <!-- Many additional form elements -->
</s:decorateAll>
<!-- /WEB-INF/layout/form.xhtml -->
<ui:composition>
  <s:componentInfo var="info">
    <div class="formElement">
      <span class="#{info.valid ? 'formLabel' : 'formErrorLabel'}">
        <h:outputLabel for="#{info.for}" label="#{info.label}#{info.required ? ' *' : ''}">
      </span>
      <ui:insert/>
    </div>
  </s:componentInfo>
</ui:composition>

If you want to look at the source code for these components check out the org.springframework.springfaces.template.ui package on springfaces GitHub project.

Written by Phillip Webb

April 13, 2012 at 6:21 pm

Integrating Spring & JavaServer Faces : Select Items

leave a comment »

With JSF, to use comboboxes, listboxes and checkboxes, you need to be aware of the javax.faces.model.SelectItem class. A SelectItem represents a single selectable option; it contains both the information needed for rendering, and the value that should be bound if the item is selected. Most of the time SelectItems are constructed with a value and a label:

new SelectItem(Title.MISS, "Miss");

Working with SelectItems before JSF 2.0 was often tedious as you needed to write code to adapt your domain objects into SelectItems. JSF 2.0 has improved things a lot and you can now dynamically construct SelectItems using EL expressions. For example:

<h:selectOneMenu>
  <f:selectItems value="#{customerRepository.all}" var="customer" label="#{customer.name}"/>
</h:selectOneMenu>

This certainly helps to reduce the amount of boiler-plate code, however, I still think that there are things that we can do make SelectItems even easier to use, especially when working with Spring. With that in mind, I have been developing a <s:selectItems> component, intended as a drop-in replacement for <f:selectItems>.

The first thing we can do, is help to reduce boiler-plate typing by removing the need to specify a var attribute. With <s:selectItems>, if the var attribute is not specified then it will default to item. So the code above can be written:

<h:selectOneMenu>
  <s:selectItems value="#{customerRepository.all}" label="#{item.name}"/>
</h:selectOneMenu>

In the above example, the value is being bound to a repository Interface that returns a Collection of Customer entities. As with the standard <f:selectItems> components you can also bind to an Array or DataModel. In addition the new component also supports any comma separated String value.

<h:selectOneMenu>
  <s:selectItems value="Java, Spring, JavaServer Faces"/>
</h:selectOneMenu>

The next thing that <s:selectItems> can help with is null values. It is quite common to need a “Please Select” option in drop downs to represent nulls. In vanilla JSF this can often mean additional mark-up for each component:

<h:selectOneMenu>
  <f:selectItem label="--- Please Select ---" noSelectionOption="true" itemValue=""/>
  <s:selectItems value="'{items}"/>
</h:selectOneMenu>

Instead of needing this additional mark-up for each element, our component will automatically insert a “Please Select” option whenever it is linked to a UISelectOne component. You can use the includeNoSelectionOption attribute to override this behavior. The label used for the “no selection option” will default to “— Please Select —” but you can customize and internationalize this text easily by adding a org.springframework.context.MessageSource to your ApplicationContext that can resolve the code "spring.faces.noselectionoption".

On the subject of MessageSource, the <s:selectItems> component will, whenever possible, try to create the label of the SelectItem using a org.springframework.springfaces.message.ObjectMessageSource. I have blogged in the past about how to convert Objects to messages and this component simply makes use of those ideas.

The new component has helped us when creating the SelectItems to display, but what about dealing with form submit? How do you convert the submitted String option back to a real Object? in the initial example above, we are binding to JPA Customer entities; The values will display just fine, but when you submit a form a “Conversion Error” is displayed because JSF does not know how to get from the submitted String back to the Customer object. The usual answer here is to develop your own javax.faces.convert.Converter implementation, but this is often problematic. Often you your select item value will be some complex object that is hard to represent in its entirety as a String.

There is an interesting technique that you can use when writing a Converter that will be used with a UISelectOne or UISelectMany component. You actually only need write code to convert from the Object to a String, conversion in the other direction can be accomplished by iterating the SelectItems and returning the single Object value that, when converted to a String, matches your submitted value. You can read more about the idea in this blog post by Arjan Tijms. Using this technique with the <s:selectItems> component is really easy, simply provide a itemConverterStringValue attribute that will be used to create the unique getAsString() value:

<h:selectOneMenu>
  <s:selectItems value="#{customerRepository.all}" label="#{item.name}" itemConverterStringValue="#{item.id}"/>
</h:selectOneMenu>

In actual fact the itemConverterStringValue is optional. If you don’t specify it, the toString() method of the object will be used or, in the case of a JPA @Entity, the @ID field will automatically be used. You are still free to write and attach your own Converter if you need to, in such cases the itemConverterStringValue is ignored.

Finally that is one more trick that the <s:selectItems> can perform. If you select component is bound to a Boolean or an Enum then the value attribute can be completely omitted. The select items will be built based on all possible options that the binding supports (“Yes”/”No” for Booleans or the complete set of Enum values). This also works with typed collections. For example, the following will display the options “Java”, “Spring” and “JavaServer Faces” (assuming you have an appropriate ObjectMessageSource) :

public enum Technology {
  JAVA, SPRING, JAVASERVER_FACES
}
public class Bean implements Serializable {
  private Set<Technology> technologies = new HashSet<Technology>();
  // ... getters and setters
}
<h:selectManyCheckbox value="#{bean.technologies}">
  <s:selectItems/>
</h:selectManyCheckbox>

If you want to check out any of this code take a look at the org.springframework.springfaces.selectitems package from the GitHub Project.

Written by Phillip Webb

January 12, 2012 at 5:31 pm

Integrating Spring & JavaServer Faces : Internationalization and Localization

with 10 comments

If you are working on a JSF application that is targeted to multiple languages, you may well be familiar with the <f:loadBundle> tag. Even if your application does not support internationalization using message bundles is still probably a good idea. Under the hood the <f:loadBundle> tag reads messages from a Java java.util.ResourceBundle and, whilst this will work, Spring developers often prefer the org.springframework.context.MessageSource interface.

As an alternative to <f:loadBundle> I have been developing a new <s:messageSource> component that can be used to expose messages from any Spring MessageSource, as well as offering a few other advantages.

The new component is a drop-in replacement for <f:loadBundle>.

<s:messageSource source="#{messageSource}" var="messages"/>
<p>
  <h:outputText value="#{messages.hello}"/>
</p>

The source attribute can be any EL expression that resolves to a MessageSource instance. If the source is not specified the Spring ApplicationContext will be used. The var attribute is the name of the variable that will be used to access the messages.

Unlike standard JSF, the key of the message to load will be built from the ID of the page being rendered. For example, assuming the page above is from the file WEB-INF/pages/messages/simple.xhtml, the key used to load the hello message will be pages.messages.simple.hello. Using these compound keys prevents message key clashes and keeps the page mark-up nice and concise. You can use the prefix attribute to override this behaviour if you need to.

If you make reference to message in your XHTML that you have forgotten to define you will either see a warning message (when in development) or an exception will be thrown (when in production).

As with standard JSF, your messages and include place-holders for use with <h:outputFormat>

pages.message.simple.welcome=Welcome to {1} with {0}
<h:outputFormat value="#{messages.welcome}">
  <f:param value="Spring"/>
  <f:param value="JSF"/>
</h:outputFormat>

The <h:outputFormat> tag is a little bit verbose, so for convenience, Spring messages can be used as Maps. This allows you to reference place-holders in a much more concise way:

<h:outputText value="#{messages.welcome['Spring']['JSF']}"/>

The same syntax allows you to map Java objects to messages. By default objects are mapped by building a message key from class name. For example, the following class:

package org.example;
public class ExampleObject {
}

Can be referenced in JSF:

<h:outputText value="#{messages[exampleInstance]}"/>

Resolving to the following message:

org.example.ExampleObject=example

For enum objects the message key includes the enum name as well as the class:

package org.example;
public enum ExampleObject {
  ONE, //mapped to message key org.example.ExampleObject.ONE
  TWO  //mapped to message key org.example.ExampleObject.TWO
}

Object messages can also make reference to properties that should form part of the message:

org.example.PersonName=Name is {first} {last}
...

package org.example;
public class PersonName {
  ...
  public String getFirst() {...}
  public String getLast() {...}
}

You can also define your own object message strategies by using a message source that implements the org.springframework.springfaces.message.ObjectMessageSource interface.

If you want to check out any of this code take a look at the org.springframework.springfaces.message and org.springframework.springfaces.message.ui packages from the GitHub Project.

Written by Phillip Webb

November 15, 2011 at 5:55 pm

Integrating Spring & JavaServer Faces : Converters

with 2 comments

When working with any web framework, you invariable run into the need to convert data input by the user from a String to some other type. Both Spring and JSF have converter strategies to deal with this, although they are really quite different in both their design and capabilities. Lets start by looking at Spring.

Spring 3 introduced a whole new conversion framework that allows objects of any type to be converted to any other type (as long as an appropriate converter is registered). Keith Donald has written about how the new conversion process works. Spring MVC was also updated at version 3 to make use of the converter service when dealing with request parameters, for example, passing a String parameter to the following controller method:

@RequestMapping
public void example(@RequestParam Integer value)

will result in the StringToNumber converter (via the StringToNumberConverterFactory) running to create the equivalent Integer.

Unlike Spring, converters in JSF only deal with converting objects to and from Strings. The javax.faces.convert.Converter interface defines two methods: getAsString (used when rendering) converts an object to a string and getAsObject (used when decoding postbacks) converts a previously rendered string back to an object.

By default, you can register converters with JSF either by adding an entries to your faces-config.xml or by using the @FacesConverter annotation. I have been working to allow you to also register JSF converters by simply declaring them as Spring beans. Using Spring beans gives you a number of advantages over vanilla JSF. For example, you easily can inject other collaborator beans and you can use Spring AOP. To use the converter bean simply refer to its ID from JSF:

@Component
public class MyConverter implements Converter {
    @Autowire
    private MyHelper helper;
    ...
}
<h:inputText value=”#{bean.value}”>
    <f:converter converterId=”myConverter”/>
</h:inputText>

In order to save referencing the same converter ID over and over again, JSF allows you to register a converter “for” a particular class. To support this with Spring a new @ForClass annotation has been introduced:

@Component
@ForClass(MyCustomType.class)
public class MyConverter implements Converter {
    ...
}

The example above will use MyConverter every time an object of MyCustomType needs converting.

For convenience I have also provided a variant of javax.faces.convert.Converter that supports generics. The org.springframework.springfaces.convert.Converter interface has an identical signature to the standard JSF version. When using this interface with @ForClass you can also omit the value on the annotation:

@Component
@ForClass
public class MyConverter implements Converter<MyCustomType> {
    ...
}

You can also implement more complex “for class” bindings using the ConditionalForClass interface (see the JavaDoc for details).

Finally, there is also support for using JSF converters (no matter how they are registered) from Spring MVC. The GenericFacesConverter is a Spring ConditionalGenericConverter that, when registered, automatically delegates to JSF.

For example, assuming that MyConverter is registered for MyCustomType the following MVC mapping will work:

@RequestMapping("/example")
public void example(@RequestParam MyCustomType value) {
    ....
}

You can also use the @FacesConverterId annotation if you need to reference a specific JSF converter:

@RequestMapping("/example")
public void example(@RequestParam @FacesConverterId("myOtherConverter") MyOtherCustomType value) {
    ....
}

If you want to see this in action take a look at ConverterExampleController from the showcase application.

Written by Phillip Webb

October 8, 2011 at 4:30 pm

Integrating Spring & JavaServer Faces : Pagination

with 2 comments

When working with large datasets you often need to present data in a paged format. Pagination is an interesting problem because it tends to cut across all layers of your application, from the view tier though application services down to the raw calls to your database.

When it comes to fetching paged data there are some pretty good solutions available. If you are using JPA then you are probably familiar with the setFirstResult() and setMaxResult() methods available on javax.persistence.Query. Even better is the Spring Data JPA project that provides org.springframework.data.domain.Pageable and org.springframework.data.domain.Page interfaces for use directly in your repositories.

With JSF there are also some well documented methods of displaying and fetching paged data. The exact solution will depend on the component suite that you are using but most of them are based around creating a custom javax.faces.model.DataModel implementation. For example MyFaces have suggestions on their wiki, RichFaces have blogged about the problem and PrimeFaces provide a Lazy Loading DataTable.

Recently I have been trying to develop something to ease the burden of the JSF developer and remove the need to create the custom DataModels and the backing beans that expose them. The basic idea is that a JSF component will create a lazy loading DataModel on your behalf using EL expressions to fetch the data as it is need.

Here is an example:

<s:pagedData 
  var="myDataModel" 
  value="#{userRepository.findByLastName(
    backingBean.lastName, pageRequest.offset, pageRequest.pageSize)}" 
  pageSize="20" />

This will create a myDataModel variable that will fetch 20 rows of data at a time by calling userRepository.findByLastName(). The EL expression will be called several time as the DataModel is scrolled.

(I am assuming that you are using EL 2.2, if you an older server such as Tomcat 6 you may need to install an updated el-impl.jar.)

Each time the EL expression is called a pageRequest variable is made available. This variable provides access the following context information that may be required when fetching a page of data:

pageNumber The page number to display
pageSize The page size requested
offset The offset (first result)
sortColumn The column used to sort data
sortAscending If the sort is in ascending or descending order
filters A map of filters to apply

 
One problem with the DataModel created in the above example is that the total number of rows is unknown. To get this information we need to provide an additional expression:

<s:pagedData 
  value="#{userRepository.findByLastName(
    backingBean.lastName,pageRequest.offset, pageRequest.pageSize)}"
  rowCount="#{userRepository.countByLastName(backingBean.lastName)}" />

The example above has also dropped the var and pageSize attributes, this will use a default page size of 10 and use a variable name of pagedData.

If you have used Spring Data you may have noticed how similar the pageRequest variable is to the org.springframework.data.domain.Pageable interface. In fact, as long as Spring Data is on your classpath, pageRequest can be cast to Pageable. Furthermore the component understands the org.springframework.data.domain.Page object so you no longer need the rowCount expression.

Here is an example that calls a spring data repository and presents data using MyFaces Tomahawk components. This example also allows you to sort the data by clicking on a column header:

<s:pagedData value="#{userRepository.findByLastName(backingBean.lastName, pageRequest)}" />
<t:dataTable value="#{pagedData}" rows="#{pagedData.pageSize}" 
    sortColumn="#{pagedData.sortColumn}" sortAscending="#{pagedData.sortAscending}" var="user">
  <t:column>
    <f:facet name="header">
      <t:commandSortHeader columnName="name">
        <h:outputText value="User Name" />
      </t:commandSortHeader>
    </f:facet>
    <h:outputText value="#{user.name}" />
  </t:column>
  <f:facet name="footer">
    <t:dataScroller paginator="true" paginatorMaxPages="9" />
  </f:facet>
</t:dataTable>

One final trick up our sleeves is to ensure that when using PrimeFaces the created DataModel is compatible with org.primefaces.model.LazyDataModel. Here the same example as above but using PrimeFaces components:

<s:pagedData value="#{userRepository.findByLastName(backingBean.lastName, pageRequest)}" />
<p:dataTable value="#{pagedData}" rows="#{pagedData.pageSize}" 
    paginator="true" lazy="true" var="user">
  <p:column headerText="User Name" sortBy="#{user.name}">
    <h:outputText value="#{user.name}" />
  </p:column>
</p:dataTable>

If you want to take a look at any of the code for this it is available on GitHub (look at the org.springframework.springfaces.page.ui and org.springframework.springfaces.model packages). I also have a basic sample application showing page mark-up. As always this code is a moving target so you might encounter some problems running the demos.

Written by Phillip Webb

August 7, 2011 at 3:28 pm

Integrating Spring & JavaServer Faces : Dynamic Navigation

leave a comment »

Often your JSF application will need to move beyond basic static navigation and start to make dynamic navigation decisions.  For example, you may want to redirect users based on their age.  Most JSF tutorials recommend that dynamic navigation is implemented by binding the action attribute of a command to a backing bean:

<h:commandButton action="#{bean.actionBasedOnAge}"/>
public String actionBasedOnAge() {
  if(age &lt; 12) {
    return "fetchadult";
  } else {
    return "ok"
  }
}

The example above shows how anyone under twelve is directed to 'fetchadult' instead of the usual 'ok'. Both the 'fetchadult' and 'ok' outcomes will need to have navigation rules defined in the faces-config.xml so that JSF knows what actual page to display.

When working with Spring MVC it is often more natural to have navigation logic contained in the @Controller bean. To help with this, implicit 'controller' and 'handler' variables are available when rendering JSF from MVC. The 'controller' variable provides access to the controller bean that was mapped to the original request, and the 'handler' variable to the underling MVC handler.  In Spring 3.0 'controller' and 'handler' are generally the same object. In Spring 3.1 however, the underlying MVC architecture is changing and 'handler' will generally be a org.springframework.web.method.HandlerMethod instance.

Here is a submit button that references the someNavigation() method of the the @Controller:

<h:commandButton action="#{controller.someNavigation"/>

Whilst accessing the controller bean is useful, it is not the ideal solution.  I prefer to use logical names in my JSF pages and map those the Java methods.  I also want an easy way to get back to data from the underlying model.

The @NavigationMapping annotation provides another, more flexible approach to handling navigation.  It works in a very similar way to @RequestMappings.  The annotation can be placed on any public method in your @Controller to map navigation outcomes to destinations.

<h:commandButton action="submit"/>
@NavigationMapping
public String onSubmit() {
  return "redirect:http://www.springsource.org";
}

If you need access to a backing bean the standard Spring @Value annotation can be used.  Any EL expression that the page can resolve can also be used on a navigation method parameter.

@NavigationMapping
public String onSubmit(@Value("#{person.age}") int age) {
...
}

Accessing model elements is even easier.  As long as you only have a single object of the type you want to access in your model, and it is not a simple type (int, String, etc), you don’t need any annotations:

@NavigationMapping
public String onSubmit(Person p) {
...
}

Other argument types can also be used (see the JavaDoc for a complete list).  For example, here is a navigation mapping that handles 'submit', 'cancel' and 'save' outcomes.  The injected arguments tell us the which of the three outcomes was clicked and provides access to the source UIComponent.

@NavigationMapping('submit','cancel','save')
public String handleNavigation(String outcome, UIComponent source) {
...
}

Return types are also equally flexible.  You can return view names as Strings, you can also use the same "@hotelsController.show" notation that I have previously blogged about.  You can also return View objects directly or you can use NavigationOutcome if you want to include implicit model items.

Finally, if you just want to render an immediate response you can use the @ResponseBody annotation or return a HttpEntity.  This works in exactly the same way as Spring.

Written by Phillip Webb

July 1, 2011 at 7:56 pm

Integrating Spring & JavaServer Faces : MVC Nuts and Bolts

with 3 comments

I have attempted to integrate JSF with Spring MVC in the past, and whilst my first attempt worked, it was far from ideal.  This time around I decided to take a few key decisions to help focus my efforts:

  • Drop backwards compatibility.  There is just too much work involved with supporting JSF 1.2 and too much good stuff coming up in Spring 3.1 to ignore.
  • MVC annotations are king.  @RequestMapping seems to be the preferred approach for most people; lets only support this and keep any custom annotations to a minimum.
  • Reduce dependencies.  It’s nice to reuse stuff but this is an integration project so the less there is to integrate the better.

With this in mind I decided to take the org.springframework.faces.mvc.JsfView class from Web Flow as my inspiration.  This class works really well because it only deals with the View in MVC, the Model and Controller remain entirely in the realm of Spring.   The only problem with JsfView is the lack of postback support.  We need to somehow detect the difference between the initial request for a view and any subsequent JSF postback.

Thanks to Spring MVC having a very flexible architecture this is entirely possible.  We can have multiple HandlerMapping and HandlerAdapter beans registered with the DispatcherServlet.  To support JSF we need something high up in this chain that can detect and deal with  postbacks, leaving anything that is not a postback to be dealt with in the usual way.  Here is the general sequence of events:

user               dispatcher    @controller
 |  /some/request      |              |
 |-------------------->|   maps to    |
 |                     |------------->|  creates
 |                     |              |------------> FacesView
 |                     |                             (/pages/file.xhtml)
 |                     |   render                        |
 |                     |-------------------------------->|
 |                     |                           [Delegate to JSF]
 |  response           |<--------------------------------|
 |<--------------------|
 |                     |
 |                     |
 | /some/request       |
 | (postback)          |
 |-------------------->|      postback handler
 |                     |--------->|
 |                     |    [Delegate to JSF]
 |  response           |<---------|
 |<--------------------|          |
 |                     |          |

 
The postback handler has a couple of interesting problems to deal with.  1) How do we know we are a postback.  2) How do we know what view to restore.  Obviously a postback will be a HTTP POST operation, but we cannot blindly assume that all POSTs are JSF postbacks.  We also need to know what XHTML file to restore, but this file is based on a decision taken by the @Controller of the last request.

The answer to both these problems is to write our own JSF ResponseStateManager.  The ResponseStateManager is part of JSFs state management infrastructure and is responsible for reading and writing component state.  Usually JSF will save the state data in the HTTP session and write a hidden form field within the page so it can be restored later.  Hooking into this mechanism we can write an additional field for MVC, the presence of the field lets us know that we have a postback and furthermore the value will let us know what XHTML file to restore.

With the postback handler in place we now have the best of both the Spring and JSF worlds.  We can use @RequestMapping annotations to build expressive URLs and JSF components to render complex web pages.  If want to we can even return different Views for the same URL based on entirely different technologies (for example by inspecting the HTTP header we might decide to return a JSF page or a XML document).

If you want to look at postback handler code it is available here.  The usual caveats of this being a moving codebase apply.

Written by Phillip Webb

June 20, 2011 at 7:15 pm

Integrating Spring & JavaServer Faces : Navigation

with 2 comments

This is the first in what I hope will be a series of blogs about my efforts to provide deep integration between Spring and JavaServer Faces.  Everything mentioned here is a “work in progress” so if you checkout the code please be aware that it is a moving target; expect some rough edges and don’t be surprised if it’s sometimes broken.

You can already use Spring with JSF pretty happily out of the box, with Spring managing your beans and JSF handling your screens.  There is also some really great support for JSF in Spring Web Flow, if you are doing any flow based application you really should be using Web Flow.  Web Flow also provides the org.springframework.faces.mvc.JsfView class that will let you render a JSF page from Spring MVC.  Unfortunately JsfView only renders transient (stateless) views, if you want to handle postbacks you are out of luck.

Allowing Spring MVC to render JSF views that can handle postback has been my primary driver for starting this project.  Thanks to the flexibility of both MVC and JSF it is entirely possible to integrate these technologies (although the exact details of how are probably best saved for another post).  I want to spend the rest of this post talking about how we can create really nice JSF navigation.

If you have used standard JSF navigation you are probably used to the following type of thing in your faces-config.xml:

<navigation-rule>
    <from-view-id>/pages/list.xhtml</from-view-id>
    <navigation-case>
        <from-outcome>select</from-outcome>
        <to-view-id>/pages/details.xhtml</to-view-id>
        <redirect/>
    </navigation-case>
</navigation-rule>

Whilst it is pretty easy to understand, there are some obvious drawbacks of the standard approach, for starters its pretty verbose.  Most of the time I want to redirect my users rather than leaving them confused as to why the URL shows something different to their current page.  Needing that <redirect/> on virtually every element is really annoying.  The amount of XML obviously upset the developers of JSF themselves, and luckily JSF 2.0 has introduced the concept of implicit navigation. This is something we will make use of later.  If you want to read a really good article about JSF navigation checkout Fluent Navigation in JSF 2 by Dan Allen.

Navigation is really all about destinations, there is not much point in redirecting someone to a 404 page not found error.  Creating nice readable URL destinations has always been a bit of a struggle for JSF.  Right now, without developing your own code, the best option for creating readable URLs is probably to use PrettyFaces.  Of course, with JSF and Spring integrated nicely you don’t need to use anything other than the @RequestMapping annotation to create readable URLs. The example below shows a how you can map a nice readable URL to show hotel details from an ID.

@Controller
public class HotelsController {
  @RequestMapping(value = "/hotels/{id}", method = RequestMethod.GET)
  public String show(@PathVariable Long id, Model model) {
    model.addAttribute(bookingService.findHotelById(id));
    return "hotels/show";
  }
}

With @RequestMapping annotations in place we can think again about the navigation.  Usually the <h:commandButton>, <h:button>, <h:commandLink> or <h:link> components will be used to trigger navigation, for example:

<h:commandButton value="Go" action="select">

Here when the user clicks on the "Go" button the "select" action kicks in and the navigation rules are used to find a destination.  As we want to move away from defining navigation XML we need an alternative approach to find MVC destinations.  Slightly subverting JSFs support for implicit navigation gives us quite a nice way to do this.  With a bit of integration code we can support a special "spring:" prefix that tells JSF to resolve destinations using Spring MVC.

<h:commandButton value="Go" action="spring:redirect:/spring/hotels/123"/>

The example above will resolve "redirect:/spring/hotel/123" using the ViewResolvers registered with Spring MVC.  In this case UrlBasedViewResolver will pick up "redirect:" and a RedirectView will be used.

That’s quite nice, but hard-coding the hotel ID "123" into the view name is not all that practical.  Luckily there is an answer:

<h:commandButton value="Go" action="spring:redirect:/spring/hotels/{id}">
    <f:param name="id" value="#{resultItem.id}/>
</h:commandButton>

All <f:param> child tags of the commandButton will be used to construct a model for the MVC view.  In this case we get a model containing “id=#{resultItem.id}“.  The EL value expression #{resultItem.id} will be resolved before the view is rendered.  The RedirectView class in Spring 3.1 will deal with URL template variables, so “/spring/hotels/{id}” will pick up “id” to render the complete URL.

One slight irritation with the above method is that you need to define your URLs inside your XHTML files as well as in your @RequestMapping annotations.  As an alternative to this you can use a special “@bean.method” notation to indicate that you want to navigate to the value of the @RequestMapping on the specified controller bean method:

<h:commandButton value="Go" action="spring:@hotelsController.show">
    <f:param name="id" value="#{resultItem.id}/>
</h:commandButton>

If you have more than one @RequestMapping method on your controller bean you can navigate between them using the even shorter syntax “@method” (here the bean is assumed to be the current handler).  Of course not every type of @RequestMapping can be reversed into a URL, for example if you use wildcards then this will not work.  The advice is to keep your mappings as simple as possible.

One final benefit of this method is that we can also reverse the DataBinder process.  For example:

public class SearchCriteria implements Serializable {
  private String searchString;
  private int page;
  // ... getters / setters
}
@RequestMapping(value = "/hotels")
public String list(SearchCriteria criteria, Model model) {
  // ...
}
<h:link outcome="spring:@list">
    <f:param name="sc" value="#{searchCriteria}"/>
</h:link>

Assuming the #{searchCriteria} EL expression resolves to a SearchCriteria object containing the string "California" and the integer 10 the URL built would be "/spring/hotels?searchString=California&page=10".

If you would like to have a look at code for this project it is currently available at http://github.com/philwebb/springfaces.  As mentioned at the top of the post this code is a work in progress so please expect some problems.  My next task on the roadmap is to support a @NavigationMapping annotation that will allow programmatic navigation.

Written by Phillip Webb

June 18, 2011 at 11:48 pm

Follow

Get every new post delivered to your Inbox.