Spring & JSF integration: Dynamic Navigation

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.

Reference: Integrating Spring & JavaServer Faces : Dynamic Navigation from our JCG partner Phillip Webb at the Phil Webb’s Blog blog.

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

Leave a Reply


nine × 9 =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close