Skip to Main Content

Java EE (Java Enterprise Edition) General Discussion

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

How to add the ability to put EL expressions in Navigation Rules

843844Dec 19 2007 — edited Dec 19 2007
I had a need to dynamically determine what page to return to in a JSF application. There has to be an easier way, but here's how I wanted to do it. I wanted to put an EL expression in my <to-view-id> nav rules in the JSF config file (e.g. faces-config.xml). This isn't allowed. So I built my own custom ViewHandler to do it.

1) Define the ViewHandler in faces-config.xml:
	<application>
		...
		<view-handler>com.msd.tts.pluggable.MyDynamicViewHandler</view-handler>
	</application>
2) Create the class:
package com.msd.tts.pluggable;

import java.io.IOException;
import java.util.Locale;

import javax.faces.*;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.*;
import javax.faces.el.ValueBinding;

import com.sun.faces.util.Util;

/**
 * Adds ability to put EL expressions in the <to-view-id> Navigation Rules in JSF 
 * configuration file (faces-config.xml).
 * 
 * @author		Craig Peters
 * @version		1.0
 * 
 */

public class MyDynamicViewHandler extends ViewHandler {

    /**
     * The original handler we are customizing.
     */
    private ViewHandler prevHandler = null;
    
    /** Creates a new instance of MappingViewHandler. By including
     * a parameter of the same type, we encourage the JSF framework
     * to pass a reference of the previously used ViewHandler. This way
     * we can use all the previous functionality and override only the
     * method we are interested in (in this case, the getActionURL() method).
     */
	public MyDynamicViewHandler(ViewHandler prevHandler) {
		this.prevHandler = prevHandler;
	}
    
	@Override
	public String getActionURL(FacesContext context, String viewId) {
		return prevHandler.getActionURL(context, viewId);
	}
	
	@Override
	public Locale calculateLocale(FacesContext context) {
		return prevHandler.calculateLocale(context);
	}

	@Override
	public String calculateRenderKitId(FacesContext context) {
		return prevHandler.calculateRenderKitId(context);
	}

	@Override
	public UIViewRoot createView(FacesContext context, String viewId) {
		return prevHandler.createView(context, viewId);
	}

	@Override
	public String getResourceURL(FacesContext context, String path) {
		return prevHandler.getResourceURL(context, path);
	}

	@Override
	public void renderView(FacesContext context, UIViewRoot viewToRender)
			throws IOException, FacesException {
		
		String result = viewToRender.getViewId();
		
		if (Util.isVBExpression(viewToRender.getViewId())) {
			ValueBinding vb = context.getApplication().createValueBinding(viewToRender.getViewId());
			result = vb.getValue(context).toString();
		}
		
		if (result.charAt(0) != '/')
			throw new IllegalArgumentException("Illegal view ID " + result + ". The ID must begin with '/'");

		viewToRender.setViewId(result);
		
		prevHandler.renderView(context, viewToRender);
	}

	@Override
	public UIViewRoot restoreView(FacesContext context, String viewId) {
		return prevHandler.restoreView(context, viewId);
	}

	@Override
	public void writeState(FacesContext context) throws IOException {
		prevHandler.writeState(context);
	}
	
}
3) Use EL in navigation rules:
	<navigation-rule>
		<from-view-id>/CommonForm.jsp</from-view-id>
		<navigation-case>
			<to-view-id>#{bean.caller}</to-view-id>
		</navigation-case>
	</navigation-rule>
The "bean.caller" method will have saved the page to go back to.

Comments are welcome. I just didn't see any other way to dynamically go back to an arbitrary page.

Thanks.
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jan 16 2008
Added on Dec 19 2007
1 comment
161 views