Creating a login composite component in JSF 2.0

In the previous recipe, you have seen the basic notions of developing a composite component in JSF 2.0. Our component just displayed a text suggesting that we are talking about a login operation, but that was all. Well, in this recipe, we will extend this composite component to make it look like a real login component.

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...

First we modify the component.xhtml page itself, as shown next:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:e="http://java.sun.com/jsf/composite/login">
<h:head>
<title>Creating a login composite component</title>
</h:head>
<h:body>
<h:form>
<div id="compositeComponent" style="border: 2px solid #000;">
<e:login>
<f:actionListener for="loginID"
type="listeners.LOGINActionListener" />
</e:login>
</div>
<h:commandButton value="Reload" />
<h:outputText value="#{LOGINActionMessage}" />
</h:form>
</h:body>
</html>

This time we have attached an action listener that will deal with the provided user and password credentials (it intercepts the login events), and will populate the response with a message displayed by an outputText component (a value is stored in request scope and then displayed).

This action listener is shown next:

package listeners;
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
public class LOGINActionListener implements ActionListener {
public void processAction(ActionEvent evt) throws
AbortProcessingException {
FacesContext ctx = FacesContext.getCurrentInstance();
UIComponent ui_comp = evt.getComponent();
ValueHolder user, pwd;
user = (ValueHolder) ui_comp.findComponent("usernameID");
pwd = (ValueHolder) ui_comp.findComponent("passwordID");
String msg = "Login fired!" + " User: " + user.getValue() +
" Password: " + pwd.getValue();
ctx.getExternalContext().getRequestMap().
put("LOGINActionMessage", msg);
}
}

Next, let's focus on the component page, login.xhtml. In the <composite:implementation> tag, we have provided the components that form a login page with two text fields and a button (these are the sub-components of the composite component):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:composite="http://java.sun.com/jsf/composite">
<h:head>
<title>Creating a login composite component
- not rendered on output
</title>
</h:head>
<h:body>
<composite:interface>
<composite:actionSource name="loginID" />
<composite:valueHolder name="username" />
<composite:valueHolder name="password" />
</composite:interface>
<composite:implementation>
login composite componentcreating, in JSF 2.0<table>
<tr>
<td>Username:<h:inputText id="usernameID" /> </td>
</tr>
<tr>
<td>Password:<h:inputSecret id="passwordID" /></td>
</tr>
<tr>
<td><h:commandButton value="Login" id="loginID" /></td>
</tr>
</table>
</composite:implementation>
</h:body>
</html>

The interesting part here is the <composite:interface> tag body. Here, we indicate that the composite component has two inner components that implement javax.faces.component.ValueHolder (any attached objects valid for ValueHolder may be attached to the composite component). The values of the name attribute must be the same as the id values in the <composite:implementation> tag.

How it works...

The component is rendered as a composite component made of two text fields and one submit button. The button event (login action) is captured by the action listener, which is responsible for extracting the submitted user and password using the findComponent method and preparing a response that is put in an outputText component. The key of this mechanism is the fact that in JSF 2.0 every composite component implements javax.faces.NamingContainer. By is nature, the findComponent method searches for any child components that match the argument, then searches the ancestor component that implements NamingContainer and asks it to find the component. In our case, an ActionListener is passed an ActionEvent whose source property is the component that fired the event, which means that component will be a child of our composite component.

See also

The code bundled with this book contains the complete code of our custom component under the recipe: Creating_a_login_composite_component.

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

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