





















































This article by David Salter, author of the book, NetBeans IDE 8 Cookbook, explains how to create a JSF composite component in NetBeans.
(For more resources related to this topic, see here.)
JSF is a rich component-based framework, which provides many components that developers can use to enrich their applications.
JSF 2 also allows composite components to be easily created, which can then be inserted into other JSF pages in a similar way to any other JSF components such as buttons and labels.
In this article, we'll see how to create a custom component that displays an input label and asks for corresponding input. If the input is not validated by the JSF runtime, we'll show an error message. The component is going to look like this:
The custom component is built up from three different standard JSF components. On the left, we have a <h:outputText/> component that displays the label. Next, we have a <h:inputText /> component. Finally, we have a <h:message /> component. Putting these three components together like this is a very useful pattern when designing input forms within JSF.
To create a JSF composite component, you will need to have a working installation of WildFly that has been configured within NetBeans.
We will be using the Enterprise download bundle of NetBeans as this includes all of the tools we need without having to download any additional plugins.
First of all, we need to create a web application and then create a JSF composite component within it. Perform the following steps:
In JSF, custom components are created as Facelets files that are stored within the resources folder of the web application. Within the resources folder, multiple subfolders can exist, each representing a namespace of a custom component. Within each namespace folder, individual custom components are stored with filenames that match the composite component names.
We have just created a composite component within the cookbook namespace called inputWithLabel.
Within each composite component file, there are two sections: an interface and an implementation. The interface lists all of the attributes that are required by the composite component and the implementation provides the XHTML code to represent the component.
Let's now define our component by specifying the interface and the implementation. Perform the following steps:
<cc:attribute name="labelValue" />
<cc:attribute name="editValue" />
</cc:interface>
<cc:implementation>
<style>
.outputText{width: 100px; }
.inputText{width: 100px; }
.errorText{width: 200px; color: red; }
</style>
<h:panelGrid id="panel" columns="3" columnClasses="outputText, inputText, errorText">
<h:outputText value="#{cc.attrs.labelValue}" />
<h:inputText value="#{cc.attrs.editValue}" id="inputText" />
<h:message for="inputText" />
</h:panelGrid>
</cc:implementation>
<h:form id="inputForm">
<cookbook:inputWithLabel labelValue="Forename" editValue="#{personController.person.foreName}"/>
<cookbook:inputWithLabel labelValue="Last Name" editValue="#{personController.person.lastName}"/>
<h:commandButton type="submit" value="Submit" action="#{personController.submit}"/>
</h:form>
This code instantiates two instances of our inputWithLabel composite control and binds them to personController. We haven't got one of those yet, so let's create one and a class to represent a person. Perform the following steps:
private String foreName;
private String lastName;
@NotNull
@Size(min=1, max=25)
private String foreName;
@NotNull
@Size(min=1, max=50)
private String lastName;
@Named
@RequestScoped
public class PersonController {
private Person person = new Person();
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public String submit() {
return "results.xhtml";
}
<h:body>
You Entered:
<h:outputText value="#{personController.person.foreName}" />
<h:outputText value="#{personController.person.lastName}" />
</h:body>
The application is now complete. Deploy and run the application by right-clicking on the project within the Projects explorer and selecting Run.
Note that two instances of the composite component have been created and displayed within the browser.
Click on the Submit button without entering any information and note how the error messages are displayed:
Enter some valid information and click on Submit, and note how the information entered is echoed back on a second page.
Creating composite components was a new feature added to JSF 2. Creating JSF components was a very tedious job in JSF 1.x, and the designers of JSF 2 thought that the majority of custom components created in JSF could probably be built by adding different existing components together. As it is seen, we've added together three different existing JSF components and made a very useful composite component.
It's useful to distinguish between custom components and composite components. Custom components are entirely new components that did not exist before. They are created entirely in Java code and build into frameworks such as PrimeFaces and RichFaces. Composite components are built from existing components and their graphical view is designed in the .xhtml files.
When creating composite components, it may be necessary to specify attributes. The default option is that the attributes are not mandatory when creating a custom component. They can, however, be made mandatory by adding the required="true" attribute to their definition, as follows:
<cc:attribute name="labelValue" required="true" />
If an attribute is specified as required, but is not present, a JSF error will be produced, as follows:
/index.xhtml @11,88 <cookbook:inputWithLabel> The following attribute(s) are required, but no values have been supplied for them: labelValue.
Sometimes, it can be useful to specify a default value for an attribute. This is achieved by adding the default="…" attribute to their definition:
<cc:attribute name="labelValue" default="Please enter a value" />
In this article, we have learned to create a JSF composite component using NetBeans.
Further resources on this subject: