JSF 2 Custom Input FacesComponent Example

In this tutorial we will create a custom input FacesComponent. Since JSF 2 we can create a custom component using only annotations. prior to JSF 2 we had to create a taglib.xml file and register it in the servlet descriptor. We’ll show both the new and old ways how to create a custom component.

Creating the Custom Component

We are creating a custom input component which extends from UIInput. We are overriding the decode and encode methods for respectively get the values from the request and encoding the necessary fields to display on the UI. The @FacesComponent annotation creates the tag file and automatically registers it in the servlet descriptor.

package com.memorynotfound.jsf;

import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import java.io.IOException;
import java.util.Map;

@FacesComponent(createTag = true, namespace = "http://memorynotfound.com/example",
        tagName = "custom-input", value = "com.memorynotfound.jsf.CustomInput")
public class CustomInput extends UIInput {

    @Override
    public void decode(FacesContext context) {
        Map requestMap = context.getExternalContext().getRequestParameterMap();
        String clientId = getClientId(context);
        char sep = UINamingContainer.getSeparatorChar(context);
        String submitted_hello_msg = ((String) requestMap.get(clientId + sep + "inputfield"));
        setSubmittedValue(submitted_hello_msg);
    }

    @Override
    public void encodeEnd(FacesContext context) throws IOException {
        String clientId = getClientId(context);
        char sep = UINamingContainer.getSeparatorChar(context);
        encodeInputField(context, clientId + sep + "inputfield");
        encodeSubmitButton(context, clientId + sep + "submit");
        encodeOutputField(context);
    }

    private void encodeInputField(FacesContext context, String clientId) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("input", this);
        writer.writeAttribute("type", "text", null);
        writer.writeAttribute("name", clientId, "clientId");
        writer.writeAttribute("size", "30", null);
        Object value = getValue();
        if (value != null) {
            writer.writeAttribute("value", value.toString(), "value");
        }
        writer.writeAttribute("size", "6", null);
        writer.endElement("input");
    }

    private void encodeSubmitButton(FacesContext context, String clientId) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("input", this);
        writer.writeAttribute("type", "Submit", null);
        writer.writeAttribute("name", clientId, "clientId");
        writer.writeAttribute("value", "Click Me!", null);
        writer.endElement("input");
    }

    private void encodeOutputField(FacesContext context) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String hellomsg = (String) getAttributes().get("value");
        writer.startElement("p", this);
        writer.writeText("You entered: " + hellomsg, null);
        writer.endElement("p");
    }

}

Prior JSF 2: Creating the taglib file

If you don’t use the @FacesComponent annotation, you must manually create a tag file and register it in the servlet descriptor. Here is an example of the tag lib file.

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
        "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
        "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib version="2.0"
                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-facelettaglibrary_2_0.xsd">

    <namespace>http://memorynotfound.com/example</namespace>
    <tag>
        <tag-name>custom-input</tag-name>
        <component>
            <component-type>com.memorynotfound.jsf.CustomInput</component-type>
        </component>
    </tag>

</facelet-taglib>

Prior JSF 2: registering the file in web.xml

Again, If you don’t use the @FacesComponent annotation, you must manually create a tag file and register it in the servlet descriptor. Here is how you can register the custom taglib file in the servlet descriptor.

<!-- register custom tag -->
<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/custom.taglib.xml</param-value>
</context-param>

Using the custom input component

Finally we can use our custom component. It’s as simple as adding the namespace in the html element and using the custom component as defined in wether via the annotation or the custom tablib file.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:custom="http://memorynotfound.com/example">
<h:body>

    <h2>JSF Custom Input FacesComponent Example</h2>
    <h:form>
        <custom:custom-input/>
    </h:form>

</h:body>
</html>

Demo

URL: http://localhost:8081/jsf-custom-input-component/index.xhtml

JSF Custom Input FacesComponent Example

After submitting the value.

JSF Custom Input FacesComponent Example

References

Download

You may also like...

  • asd

    Hi, is faces-config.xml necessary?