Version 4

    Creating Custom EL Functions

     

    In the WebContent/META-INF/elfunctions.taglib.xml (JBDS) or view/META-INF/elfunctions.taglib.xml (seam-gen) create a file

     

    <?xml version="1.0"?>
    <!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "facelet-taglib_1_0.dtd">
    <facelet-taglib>
          <library-class>org.el.func.FnLibrary</library-class>
    </facelet-taglib>
    

     

    Create another src package src/facelets with the packagename: org.el.func and add

     

    import org.el.func.IsTextHandler;
    import com.sun.facelets.tag.AbstractTagLibrary;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    public class FnLibrary extends AbstractTagLibrary {
    
         public final static String Namespace = "http://org.el.func/SeamFunc";
    
         public static final FnLibrary INSTANCE = new FnLibrary();
    
         public FnLibrary() {
              super(Namespace);
              try {
                   Method[] methods = SeamFunc.class.getMethods();
                   for (int i = 0; i < methods.length; i++) {
                        if (Modifier.isStatic(methods+.getModifiers())) {
                             this.addFunction(methods+.getName(), methods+);
                        }
                   }
              } catch (Exception e) {
                   throw new RuntimeException(e);
              }
         }
    }
    

     

    The above will dynamically add any of the static methods in a class called SeamFunc.class to be available in the EL.  Now create SeamFunc.class:

     

    import org.jboss.seam.core.Expressions;
    
    public class SeamFunc {
    
         public static String concat(String... strings) {
              StringBuilder buff = new StringBuilder();
              if (strings != null) {
                   for (String str : strings) {
                        buff.append(str);
                   }
              }
              return buff.toString();
         }
    
         public static Object evalEl(String expression) {
              String framedExpr = "#{" + expression + "}";
              Object value = Expressions.instance().createValueExpression(framedExpr).getValue();
              return value;
         }
    
    }
    

     

     

    Now the last piece is to define the location of the elfunctions.taglib.xml in web.xml:

     

    <context-param>
        <param-name>facelets.LIBRARIES</param-name>
        <param-value>
            /META-INF/elfunctions.taglib.xml
        </param-value>
    </context-param>
    

     

     

     

    Create a test.xhtml page and add:

     

    xmlns:e="http://org.el.func/SeamFunc"
    

     

    and to the body:

     

    #{e:concat('Hello ', 'World!')} / #{e:evalEl('conversation')}
    

     

    These are just two examples of functions, you can create as many as you'd like.  The evalEL seems useless, until you realize you can do something like:

     

    #{e:evalEL(e:concat('person', 'Home'))}
    

     

    which correctly resolves the value of the Seam component named personHome.

     

    -


     

     

    Creating Custom UI Compositions

     

    Create another xml called META-INF/compositions.taglib.xml

     

    <?xml version="1.0"?>
    <!DOCTYPE facelet-taglib PUBLIC
    "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
    "facelet-taglib_1_0.dtd">
    <facelet-taglib>
        <namespace>http://enhancements.seam/jsf</namespace>
        <tag>
            <tag-name>print</tag-name>
            <source>../layout/enhancements/print.xhtml</source>
        </tag>
    </facelet-taglib>
    

     

    Add that to your web.xml

     

    <context-param>
        <param-name>facelets.LIBRARIES</param-name>
        <param-value>
            /META-INF/elfunctions.taglib.xml; compositions.taglib.xml
        </param-value>
    </context-param>
    

     

    Create the print.xhtml in WebContent/layout/enhancements/print.xhtml (JBDS) or view/layout/enhancements/print.xhtml (seam-gen) :

     

    <ui:composition  xmlns="http://www.w3.org/1999/xhtml"
               xmlns:ui="http://java.sun.com/jsf/facelets"
               xmlns:h="http://java.sun.com/jsf/html"
               xmlns:f="http://java.sun.com/jsf/core"
               xmlns:s="http://jboss.com/products/seam/taglib"
               xmlns:rich="http://richfaces.org/rich"
               xmlns:a="http://richfaces.org/a4j"
               xmlns:e="http://org.el.func/SeamFunc"
               xmlns:c="http://java.sun.com/jstl/core">
        
        <h:outputText value="#{e:concat('Hello ', name)}" ></h:outputText>
          
    </ui:composition>
    

     

    Now in your view or WebContent folder create test.xhtml

     

    <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <ui:composition xmlns="http://www.w3.org/1999/xhtml"
              xmlns:s="http://jboss.com/products/seam/taglib"
              xmlns:ui="http://java.sun.com/jsf/facelets"
              xmlns:f="http://java.sun.com/jsf/core"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:rich="http://richfaces.org/rich"
              xmlns:a="http://richfaces.org/a4j"
              xmlns:e="http://org.el.func/SeamFunc"
              xmlns:custom="http://enhancements.seam/jsf"
              template="/layout/template.xhtml">
              
        <ui:define name="body">
         
         <custom:print message="World" ></custom:print>
              
        </ui:define>
        
    </ui:composition>
    
    

     

    -


     

    Creating Custom Facelets Tag handlers

     

    Given you already have the elfunctions.taglib.xml from the custom EL functions, no need to add any more xml or configuration.

     

    Open and edit FnLibrary.java

     

    import org.el.func.IsTextHandler;
    import com.sun.facelets.tag.AbstractTagLibrary;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    public class FnLibrary extends AbstractTagLibrary {
    
         public final static String Namespace = "http://org.el.func/SeamFunc";
    
         public static final FnLibrary INSTANCE = new FnLibrary();
    
         public FnLibrary() {
              super(Namespace);
              try {
                   this.addTagHandler("doesFieldTypeClassHaveAnnotation", DoesFieldTypeClassHaveAnnotation.class);
                   Method[] methods = SeamFunc.class.getMethods();
                   for (int i = 0; i < methods.length; i++) {
                        if (Modifier.isStatic(methods+.getModifiers())) {
                             this.addFunction(methods+.getName(), methods+);
                        }
                   }
              } catch (Exception e) {
                   throw new RuntimeException(e);
              }
         }
    }
    

     

    Create DoesFieldTypeClassHaveAnnotation.class

     

    import java.io.IOException;
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    
    import javax.el.ValueExpression;
    import javax.faces.component.UIComponent;
    
    import com.sun.facelets.FaceletContext;
    import com.sun.facelets.tag.TagAttribute;
    import com.sun.facelets.tag.TagConfig;
    import com.sun.facelets.tag.TagHandler;
    
    public class DoesFieldTypeClassHaveAnnotation extends TagHandler {
         
         private final TagAttribute annotation;
         
         private final TagAttribute field;
    
    
        public DoesFieldTypeClassHaveAnnotation(final TagConfig config) {
            super(config);
            annotation = this.getRequiredAttribute("annotation");
            field = this.getRequiredAttribute("field");
        }
    
        
        public void apply(final FaceletContext faceletsContext, final UIComponent aParent) throws IOException {
             boolean apply = false;
             
             ValueExpression valueExpression = this.field.getValueExpression(faceletsContext, Object.class);
             Field f = (Field)valueExpression.getValue(faceletsContext.getFacesContext().getELContext());
             
              try {
                   Annotation[] asOnField = f.getType().getAnnotations();
                   for(Annotation t : asOnField) {
                        if (annotation.getValue().equals(t.annotationType().getName())) {
                             apply = true;
                             break;
                        }
                        
                   }
              } catch (SecurityException ex) {
                   System.err.println(ex.getMessage());
              }
              
              if (apply) {
                this.nextHandler.apply(faceletsContext, aParent);
            }
         }
    }
    

     

     

     

    In your test.xhtml

     

    <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <ui:composition xmlns="http://www.w3.org/1999/xhtml"
              xmlns:s="http://jboss.com/products/seam/taglib"
              xmlns:ui="http://java.sun.com/jsf/facelets"
              xmlns:f="http://java.sun.com/jsf/core"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:rich="http://richfaces.org/rich"
              xmlns:a="http://richfaces.org/a4j"
              xmlns:e="http://org.el.func/SeamFunc"
              xmlns:custom="http://enhancements.seam/jsf"
              template="/layout/template.xhtml">
              
        <ui:define name="body">
         
         <custom:print message="World" ></custom:print>
    
         <br />
    
         <e:doesFieldTypeClassHaveAnnotation field="#{person.dog}" annotation="javax.persistence.Entity">
              The dog field in the Person Entity is also an Entity
         </e:doesFieldTypeClassHaveAnnotation>
              
        </ui:define>
        
    </ui:composition>
    

     

    This would be the case where there is a @Entity public class Dog and

     

    @Entity
    public class Person {
    ...
    private Dog dog;
    ...
    }
    

     

     

     

     

    Referenced by: