Building a "HelloWorld" JSF custom component

Now that we are done with the basics of what a JSF component is, let's see the simplest example of a JSF custom component, the HelloWorld component. The idea of this recipe is to get you familiar with the skeletons of the JSF custom component classes.

Getting ready

We have developed this recipe with NetBeans 6.8, JSF 2.0, and GlassFish v3. The JSF 2.0 classes were obtained from the NetBeans JSF 2.0 bundled library.

How to do it...

We will proceed step by step, and implement each class described earlier in the introduction of the chapter. To begin with, we will write the UI Component class, and for this we keep in mind that the effect of our component is to render a simple message on the client. Knowing that, we can extend the concrete UIOutput class or, as we did, the UIComponentBase class (we prefer this class, because we don't need the value attribute, which is specific for UIOutput components). Therefore, our component may look as shown next:

package custom.component;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import java.io.IOException;
import javax.faces.context.ResponseWriter;
public class HelloWorldComponent extends UIComponentBase {
public String getFamily() {
return "HELLO_WORLD_FAMILY";
}
@Override
public void encodeBegin(FacesContext ctx) throws IOException {
ResponseWriter responseWriter = ctx.getResponseWriter();
String helloworld = (String) getAttributes().get("helloworld");
responseWriter.startElement("b", this);
if (helloworld != null) {
responseWriter.writeText(helloworld, "helloworld");
} else {
responseWriter.writeText("This is a simple
Hello World JSF custom component!", null);
}
responseWriter.endElement("b");
}
}

As you can see, we have two methods in HelloWorldComponent. The getFamily method, associates a string, representing the component family, with this component. This family is significant, because this value is used to look up the renderer when it is time to make an HTML document.

Since our component only displays a message, and the tag doesn't contain any children, we only need to override the encodeBegin method, which renders the tag. For advanced components, which have a body, we should have three overridden methods:

  • encodeBegin: This starts the element for the root component
  • encodeChildren: This would cause all of the children to be encoded
  • encodeEnd: This closes the element

Next, we will build the tag handler. This class is responsible for creating the component, attaching the renderer to the component, and setting the fields on the component based on the values supplied in JSP. In this case, the tag handler is:

package custom.component;
import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.webapp.UIComponentELTag;
public class HelloWorldComponentTag extends UIComponentELTag {
// Mapping helloworld attribute to a bean property
public ValueExpression helloworld = null;
public String getComponentType() {
return "HELLO_WORLD";
}
public String getRendererType() {
return null;
}
public ValueExpression getHelloworld() {
return helloworld;
}
public void setHelloworld(ValueExpression helloworld) {
this.helloworld = helloworld;
}
@Override protected void setProperties(UIComponent ui_comp) {
super.setProperties(ui_comp);
if (!(ui_comp instanceof HelloWorldComponent)) {
throw new IllegalStateException("Component " +
ui_comp.toString() + " is of wrong type!!!");
}
HelloWorldComponent helloWorldComponent =
HelloWorldComponent)ui_comp;
if (helloworld != null) {
helloWorldComponent.setValueExpression("helloworld",
helloworld);
}
}
}

Notice that since we don't have a separate renderer class (we don't need one), we return a null value. The setProperties method sets the incoming values from the JSP tag by first calling the same method of the parent class along with the custom code to set the value from the helloworld tag attribute.

Next, we build the TLD document. This file allows us to use our custom JSP tag handler class. The helloworld.tld file is stored in the WEB-INF folder of the application (standard J2EE architecture) and it is responsible for associating the tag name to its attributes:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>0.03</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>Hello World Component Tag Library</short-name>
<uri>http://packt.net/cookbook/components</uri>
<description>
Custom components tag library.
</description>
<tag>
<name>helloWorldUI</name>
<tag-class>custom.component.HelloWorldComponentTag</tag-class>
<body-content>empty</body-content>
<description>
This custom component says hello.
</description>
<attribute>
<name>helloworld</name>
<required>false</required>
<deferred-value>
<type>java.lang.Object</type>
</deferred-value>
<description>
The attribute that will contain the hello message.
</description>
</attribute>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
The component identifier for this component.
</description>
</attribute>
<attribute>
<name>immediate</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
Immediate conversion and validation.
</description>
</attribute>
<attribute>
<name>rendered</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
Indicates if the component should be
rendered or processed on any subsequent form submit.
</description>
</attribute>
<attribute>
HelloWorld componentbuilding<name>required</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
Flag indicating that the user is required to
provide a submitted value for this input component.
</description>
</attribute>
<attribute>
<name>validator</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
A validator method that will be called
to perform validation.
</description>
</attribute>
<attribute>
<name>binding</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<description>
A value binding that points to a bean property.
</description>
</attribute>
</tag>
</taglib>

Now, the HelloWorld custom component is done! The last thing that has to be done is to add the corresponding lines in the faces-config.xml descriptor (this is necessary even if we are using JSF 2.0). These lines will configure the component as follows:

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="1.2"
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_1_2.xsd">
<component>
<component-type>HELLO_WORLD</component-type>
<component-class>
custom.component.HelloWorldComponent
</component-class>
</component>
</faces-config>

Time to see what we have done! For this you can call our component from a JSP page as shown next:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<%@taglib prefix="e" uri="http://packt.net/cookbook/components"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<f:view>
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8"/>
<title>Writing a simple JSF custom component
an hello world component</title>
</head>
<body>
<e:helloWorldUI helloworld="Hello from Packt!"/>
</body>
</html>
</f:view>

Notice that we have added the component taglib element right after the JSF/HTML taglib element.

The output will be the following message:

Hello from Packt

How it works...

If you read the introduction of this chapter, then it becomes easier for you to understand how our custom component works.

See also

The code bundled with this book contains a complete example of this recipe. The project can be opened with NetBeans 6.8 and it is named: Create_a_HelloWorld_custom_component

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset