3
votes

I am trying to develop custom control in JSF 1.2 (using facelets).

I followed steps from different tutorials (defining .tld, taglib.xml, registered component in faces-config.xml and implementing UIComponent (component renders itself) and UIComponentELTag classes) and my component is rendered, I have value bound to it, but attributes I defined for that tag are ignored. I logged various methods in Tag class and noticed that none of the methods is ever called.

What am I missing? Is there a reason Tag handler class is never invoked?

Thanks in advance.

My taglib.xml file is:

<?xml version="1.0"?> 
<!DOCTYPE facelet-taglib PUBLIC 
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib> 
  <namespace>dynamissoft.com/entities/ui</namespace>
  <tag>
    <tag-name>legalEntityView</tag-name>
    <component>
      <component-type>rs.bozic.wastemanager.LegalEntityView</component-type>
    </component>
  </tag>
</facelet-taglib> 
2
Please post your xxx.taglib.xml file.lexicore
My taglib.xml file is: <?xml version="1.0"?> <!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "java.sun.com/dtd/facelet-taglib_1_0.dtd"> <facelet-taglib> <namespace>dynamissoft.com/entities/ui</namespace> <tag> <tag-name>legalEntityView</tag-name> <component> <component-type>rs.bozic.wastemanager.LegalEntityView</component-type> </component> </tag> </facelet-taglib>Vladimir

2 Answers

3
votes

Have you tried creating a custom component using facelets (xml only). That's the most easy way, using facelets, usually, the different java classes aren't needed anymore.

Very rough overview:

  • Create facelet xml file (like myComponent.xhtml)
  • Register in the facelet inside a taglib (which in turn should be defined in the web.xml)
  • Optionally, create some support beans in Java

You can pass values/beans to your component using normal tag paramets:

Using the component

Inside the component

Param1 is just printed: #{myParam2} Param2 used as value for table ...

There are excellent tutorials on Google, like the one from IBM.

If possible, consider using JSF 2.0. Facelets are integrated, and you have more flexibility to create your custom components. I created a blog posting a while ago on that: http://blog.whitehorses.nl/2010/02/08/jsf-2-0/ (or Google yourself)

2
votes

Just to expand Gerbrand's answer a bit, here's a procedure for a simple Facelets-compatible component. It renders a span tag that wraps a text specified via component's text attribute.

  1. First create the component class (in our case it's just a flavour of UIOutput):

      package sample.mytag;
    
      import java.io.IOException;
      import javax.faces.component.UIOutput;
      import javax.faces.context.FacesContext;
      import javax.faces.context.ResponseWriter;
    
      public class SpanComponent extends UIOutput{            
        private String text;
        @Override
        public Object saveState(FacesContext context) {
          Object values[] = new Object[2];
          values[0] = super.saveState(context);
          values[1] = target;
          return ((Object) (values));
        }
    
        @Override
        public void restoreState(FacesContext context, Object state) {
          Object values[] = (Object[])state;
          super.restoreState(context, values[0]);
          target = (String)values[1];
        }
    
        public String getText() {
          return text;
        }
    
        public void setText(String text) {
          this.text = text;
        }
    
        @Override
        public void encodeBegin(FacesContext context) throws IOException {
          ResponseWriter writer=context.getResponseWriter();
          writer.startElement("span", component);
          writer.writeAttribute("id", id, null);
          writer.writeText(text, null);
          writer.endElement("span");
          writer.flush();                
        }
    
        @Override
        public String getFamily(){
          return "myTag.component";
        }
    
        @Override
        public void encodeEnd(FacesContext context) throws IOException {
          return;
        }
    
        @Override
        public void decode(FacesContext context) {
          return;
        } 
      }
    
  2. Next, we need a taglib XML file, let's call it mytag.taglib.xml and put it inside WEB-INF dir.

      <!DOCTYPE facelet-taglib PUBLIC
        "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
        "WEB-INF/facelet-taglib_1_0.dtd"> 
      <facelet-taglib> 
      <namespace>http://sample.tag/mytags</namespace> 
      <tag>
        <tag-name>myspan</tag-name>
          <component>
            <component-type>myTag.component</component-type>    
          </component>
      </tag>
      </facelet-taglib> 
    

    Note that:

    • .taglib.xml suffix is mandatory
    • <component-type> should have the same value that is returned by component's getFamily() method
    • you can replace WEB-INF/facelet-taglib_1_0.dtd with http://java.sun.com/dtd/facelet-taglib_1_0.dtd
  3. It's time to modify web.xml and faces-config.xml.

    Former should be modified with

    <context-param> 
      <param-name>facelets.LIBRARIES</param-name> 
      <param-value>/WEB-INF/mytag.taglib.xml</param-value> 
    </context-param>     
    

    faces-config.xml should get

    <component> 
     <component-type>myTag.component</component-type> 
     <component-class>sample.mytag.LabelComponent</component-class> 
    </component>  
    
  4. We're good to go!

        <ui:composition
          xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"  
          xmlns:sample="http://sample.tag/mytag">  
    
          <sample:myspan text="I'm inside a span!"/>
    
        </ui:composition>