Death to the back button in JSF


The browser back button is notorious for being the most hated browser feature by developers. It posses many design challenges and considerations. This article will cover a few approaches to handling the browser back button, as well as highlighting a way to create your own within a JSF application.

Stateful vs Stateless

When laying out your applications workflow, it is smart to consider how you want the application to flow and look to the end user. In a stateful application you attempt to store as much data in the backing beans, whereas with a stateless approach you load data as pages change. In JSF you have access to different kinds of managed beans. Some types work better for different implementations. Using view scoped and request scoped for a more stateless approach, whereas it would be smarter to use conversation scoped or session scoped for a more stateful approach. Each have there benefits and drawbacks.

Start by determining the applications purpose, this will help when selecting which type of bean to use. For example; when developing a search feature that spans multiple tables in various databases it may become inefficient to load the search results over again if the user presses the back button. Thus, a more stateful scoped bean (conversation scoped, or session scoped) would be smarter choice.

Consider the following workflow:

userSearch.xhtml -> finds a user and clicks -> userDetail.xhml

In a typical stateful workflow we could manage this entire page navigation using a conversation or session scoped bean in JSF. The data that is returned from the user search limits the users content to be shown on the user detail page. It only requires one backing bean to between both pages.

Benefits of a Stateful approach:
  • Additional security requirements are not needed since the user id is hidden.
  • No need to load data again in between views
  • Routes can easily be managed in backing beans using explicit routing
Drawbacks of a Stateful approach:
  • Backing beans can become cluttered
  • Stale data may become a issue
  • Pages are not bookmarkable (important in modern web applications)
  • Relies heavily on POST commands to navigate which is not search engine friendly
  • Memory usage can become an issue with larger / high traffic sites
A better stateless approach

Let’s continue to look at the following workflow, but with a different way to implement it. For this case I am going to assume that the userSearch is efficient.

userSearch.xhtml -> finds a user and clicks -> userDetail.xhml?id=123

Notice the “id?=123” has been added to the user detail page. This represents the id of the user that is expected be loaded. With a stateless implementation the user search page and the user detail page have no knowledge of each other. They would in fact be completely separate backing beans, most likely viewscoped. When the user is shown a list of search results, those links are generated using implicit routing and rendered to the DOM. Hovering over the link would show you the full url path. No need to hit a backing bean to determine routes like when using the stateful approach. The route is predetermined. This is one of the huge benefits to creating views that are stateless.

Benefits of a Stateless approach:
  • Pages are bookmarkable
  • Data is never stale
  • Links do not have to rely on backing beans, they can be generated on the page, SEO friendly
  • Less of a memory hog per session
Drawbacks of a Stateless approach:
  • Have to consider security implications when exposing id’s in the URL.
  • If performing heavy calculation, could hurt server performance.
Stateless with the back button

But how do we handle the back button in JSF applications? Designing your application to use stateless beans enables the ability to bring back the back button into your JSF application.

A typical enterprise application built in JSF will cripple if the back button is pressed. In fact a lot of developers have gone as far as building there own stateful back button to display on the page. This back button functions just like the browser back button, but has additional knowledge to control the stateful views. All of this is not necessary if your views are stateless.

It is my opinion that you should never give JSF too much control over the browser. If you have to implement your own back button within your application, do it so with stateless views. Stateless views by design should all have unique URL’s which you can track. Simply add a preRender event each JSF page which calls this BrowserHistoryController. This controller maintains a page stack of all url’s visited. It has a small amount of intelligence to handle users switching between pressing a on page back button, and the browser back button.

On any of your xhtml pages that you want tracked

   <f:event type="preRenderView" listener="#{browserHistoryController.addPageUrl()}"/>

Creating your own back link

<h:outputLink value="#{browserHistoryController.backUrl}" rendered="#{browserHistoryController.hasPageBack()}">Back</h:outputLink>

public class BrowserHistoryController extends BaseController implements Serializable {

    private static final long serialVersionUID = 1L;

    private Stack<String> pageStack = new Stack<>();
    private Integer maxHistoryStackSize = 20;

    public void addPageUrl() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (!facesContext.isPostback() && !facesContext.isValidationFailed()) {
            HttpServletRequest servletRequest = (HttpServletRequest) facesContext.getExternalContext().getRequest();
            String fullUrl = servletRequest.getRequestURL() + "?" + servletRequest.getQueryString();

    public String getBackUrl() {
        Integer stackSize = pageStack.size();
        if (stackSize > 1) {
            return pageStack.get(stackSize - 2);
        // Just in case hasPageBack was not implemented (be safe)
        return pageStack.get(stackSize - 1);

    public Stack<String> getPageStack() {
        return pageStack;

    public boolean hasPageBack() {
        return pageStack.size() > 1;

    public void setPageStack(Stack<String> pageStack) {
        this.pageStack = pageStack;

    private void updatePageStack(String navigationCase) {

        Integer stackSize = pageStack.size();

        // If stack is full, then make room by removing the oldest item
        if (stackSize >= maxHistoryStackSize) {
            stackSize = pageStack.size();

        // If the first page visiting, add to stack
        if (stackSize == 0) {

        // If it appears the back button has been pressed, in other words:
        // If the A -> B -> C, and user navigates from C -> B, then remove C
        if (stackSize > 1 && pageStack.get(stackSize - 2).equals(navigationCase)) {
            pageStack.remove(stackSize - 1);

        // If we are on the same page
        // If A == A then ignore
        if (pageStack.get(stackSize - 1).equals(navigationCase)) {

        // In a normal case, we add the item to the stack
        if (stackSize >= 1) {


Use this controller in combination with stateless views and the browser back button should no longer be a issue when coding for your application.