Introduce JSF EL implicit variables by custom EL resolver 

Joined:
08/13/2009
Posts:
164

November 10, 2011 13:19:13    Last update: December 01, 2011 19:10:43
You can add custom implicit variables to JSF pages by using a custom EL resolver, in two simple steps:
  1. Write an ELResolver class to resolve the variable
  2. Add the ELResolver to faces-config.xml


Starting from the Maven Hello World example:
  1. Add faces API and EL dependencies to pom.xml:
    <dependencies>
    	<dependency>
    	    <groupId>org.apache.myfaces.core</groupId>
    	    <artifactId>myfaces-api</artifactId>
    	    <version>2.1.3</version>
    	    <scope>provided</scope>
    	</dependency>
    
    	<dependency>
    	    <groupId>javax.el</groupId>
    	    <artifactId>javax.el-api</artifactId>
    	    <version>2.2.3</version>
    	    <scope>provided</scope>
    	</dependency>
    
    	<dependency>
    	    <groupId>junit</groupId>
    	    <artifactId>junit</artifactId>
    	    <version>3.8.1</version>
    	    <scope>test</scope>
    	</dependency>
    </dependencies>
    

  2. Add a simple greeter class (src/main/java/com/example/Greeter.java):
    package com.example;
    
    public class Greeter {
        public String sayHi(String name) {
    	return "Hello " + name + "!";
        }
    }
    

  3. Add our custom EL resolver (src/main/java/com/example/ELResolver.java):
    package com.example;
    
    import java.util.Iterator;
    import java.beans.FeatureDescriptor;
    
    import javax.el.ELContext;
    import javax.el.PropertyNotWritableException;
    
    /**
     * This class introduces an implicit variable 'Greeter' into the EL space. 
     * It does variable resolution only, property resolution is left to the built-in 
     * resolvers. For variable resolution, base is always null, property is String.
     */
    public class ELResolver extends javax.el.ELResolver {
        private static final String GREETER = "Greeter";
    
        @Override
        public Class<?> getCommonPropertyType(ELContext ctx, Object base) {
    	return null;
        }
    
        @Override
        public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext ctx, Object base) {
    	return null;
        }
    
        @Override
        public Class<?> getType(ELContext ctx, Object base, Object property) {
    	if ((base == null) && property.equals(GREETER)) {
    	    ctx.setPropertyResolved(true);
    	    return Greeter.class;
    	}
    	return null;
        }
    
        @Override
        public Object getValue(ELContext ctx, Object base, Object property) {
    	if ((base == null) && property.equals(GREETER)) {
    	    ctx.setPropertyResolved(true);
    	    return new Greeter();
    	}
    	return null;
        }
    
        @Override
        public boolean isReadOnly(ELContext ctx, Object base, Object property) {
    	return true;
        }
    
        @Override
        public void setValue(ELContext ctx, Object base, Object property, Object value) {
    	ctx.setPropertyResolved(false);
        }
    }
    

  4. Add the custom EL resolver to src/main/resources/META-INF/faces-config.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <faces-config xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
        version="2.1">
        <application>
    	<el-resolver>com.example.ELResolver</el-resolver>
        </application>
    </faces-config>
    

  5. Build JAR with
    mvn package
    

  6. Drop the JAR into WEB-INF/lib of a webapp and test the new EL with:
    <h:outputText value="#{Greeter.sayHi('Mike')}"/>
    



Fixed: the setValue method used to throw an exception, which is wrong.
@Override
public void setValue(ELContext ctx, Object base, Object property, Object value) {
    // This is WRONG!
    throw new PropertyNotWritableException("I don't set value");
}

When values need to be set on a managed bean, throwing exception here stops further processing and causes the whole page to fail, even when the introduced variable is not used.
Share |
| Comment  | Tags