April 24, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Using Managed Beans in a Facelet Page

  • October 30, 2013
  • By Manoj Debnath
  • Send Email »
  • More Articles »

Java Server Faces (JSF) uses Managed Beans to separate presentation from business logic. Program logic is contained in the bean implementation code and JSF simply refers to the bean properties or action using the Expression Language (EL). Managed Bean, thus is a specialized Java class that synchronizes values with components, processes business logic, and handles navigation between pages.

Where does the Managed Bean Fit?

JSF pages are standard web pages that intercept HTTP via the Faces servlet and produce HTML. Under the hood, JSF allows you to render the page with any PDL or VDL irrespective of devices (web browser or portable devices, etc.) and incorporate events, listeners and components.

JSF pages are standard web pages that intercept HTTP
JSF pages are standard web pages that intercept HTTP

Managed bean as a POJO has a no-argument constructor, a set of properties and methods that perform on the component. Each of the managed bean properties can be bound to a:

  • Component value: While binding a managed bean property to component's value there should be a corresponding match of property type to the component's value. For example - javax.faces.component.UIInput and javax.faces.component.UIOutput component classes are represented by the h:inputText and h:outputText. Similarly, javax.faces.component.UIData is represented by h:dataTable and so on.
  • Component instance
  • Converter instance
  • Listener instance
  • Validator instance

Most common functions performed by managed beans are:

  • Component data validation
  • Handle event fired by a component
  • Page navigation: determine the next page to which the application must navigate.

Expression Language (EL)

EL allows dynamic data access from the JavaBeans component through deferred evaluation or immediate evaluation. EL written as #{expr} are for deferred evaluation and ${expr} for immediate evaluation.

Deferred Evaluation: Deferred expressions are evaluated at other phases of the page life cycle by its controller depending on how the expression is being used in the page. In the following example, h:inputText tag's value attribute references a deferred evaluation expression that points to the name property of the employee bean. JSF evaluates #{employee.name} expression during the render-response phase of the lifecycle.

<h:inputText id="name" value="#{employee.name}" />

Immediate Evaluation: ${expr} expressions are evaluated immediately. These expressions are always read-only value expressions and used only as the value of a tag attribute that can accept runtime expressions. The following example shows a tag whose value attribute references an immediate evaluation.

<h:outputText value="${employee.name}" />

The JSF evaluates the expression ${employee.name}, converts it, and passes the returned value to the tag handler. The value is updated on the page.

Referencing a Managed Bean

Any component in JSF has a set of attributes for referencing the managed bean method. These methods perform the desired function for the component associated with a tag. However, there are certain components, which have some special or added features such as – the components that implement ActionSource can use the action and actionListener attributes or the components that implement EditableValueHolder can use the validator or valueChangeListener attributes. A component attribute referencing a managed bean method should follow a specific signature defined by the tag's attribute. For example – the method declaration of a validator attribute of the inputText is:

void validate(javax.faces.context.FacesContext,javax.faces.component.UIComponent, java.lang.Object)

Referencing a Navigation Method

Page navigation can be accomplished through components such as a button or a link. The tag used is action. This tag can be used to invoke a managed bean method that performs some processing and provides a logical outcome.

<h:commandButton value="Submit" action="#{userBean.submit}"/>
public String submit( ){
...
       if(userId.equals("administrator"){
             return "admin_dashboard";
       }else{
             return "common_dashboard";
       }
...
}

Referencing a Validation Method

The component's validator tag can be used to invoke the validation method declared in a managed bean. In the following code an email entered by the user is validated with the managed bean method, validateEmail.

<h:inputText value="#{userBean.email}" required="true" validator="#{userBean.validateEmail}"/>


public void validateEmail(FacesContext context, UIComponent toValidate, Object value){
        String emailPattern = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\."+
                    "[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9]"+
                    "(?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
        Pattern p = Pattern.compile(emailPattern);
        Matcher m = p.matcher((String)value);        
        if(!m.matches()){
            ((UIInput)toValidate).setValid(false);
            FacesMessage message = new FacesMessage("Invalid email!");
            context.addMessage(toValidate.getClientId(context), message);
        }
    }

Referencing a Value-change Event

A value-change event can be handled in a managed bean method in the following way:

<h:inputText value="#{userBean.name}" required="true" valueChangeListener="#{userBean.processValueChange}"/>
 
public void processValueChange(ValueChangeEvent event)
       throws AbortProcessingException    {
           if(event.getNewValue()!=null){
       FacesContext.getCurrentInstance().getExternalContext()
       .getSessionMap().put("name", event.getNewValue());
    }
}

Referencing an Action Event

A component generates an action event through the actionListener attribute. The managed bean method can handle the event as follows. The managed bean even handler must be a public method that accepts the action event and returns void.

<h:form>
    <h:panelGrid columns="2">     
       <h:outputLabel value="User Name :"/>
       <h:inputText value="#{userBean.name}"/>
       <h:outputLabel value="Password :"/>
       <h:inputSecret value="#{userBean.password}"/>-->
       <h:commandButton value="Login" action="#{userBean.login}"/>
    </h:panelGrid>
</h:form>
public void checkLogin(ComponentSystemEvent event){
  if(!loggedIn){
      FacesContext context = FacesContext.getCurrentInstance();
      ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler)context.
                                        getApplication().getNavigationHandler();
      handler.performNavigation("login");
  }
}

A Simple Validation Example

The example given below is a very simple application to demonstrate an email validation through a managed bean. This application includes an entity class Contact, an EJB class named ContactEJB, a managed bean class named ContactMBean and two JSF web pages.

Entity: Contact.java
@Entity
@NamedQuery(name="findAllContacts", query = "SELECT c FROM Contact c")
public class Contact implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String email;
    private String phone;
//… getters and setters
}
package org.contactapp.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.contactapp.entity.Contact;
EJB: ContactEJB.java
@Stateless
public class ContactEJB{
    @PersistenceContext(unitName = "ContactAppPU")
    private EntityManager em;
    public List<Contact> findContacts(){
        
        TypedQuery<Contact> query = em.createNamedQuery("findAllContacts", Contact.class);
        return query.getResultList();
    }
    
    public Contact createContact(Contact contact){
        em.persist(contact);
        return contact;
    }
}
Managed Bean: ContactMBean.java
@Named(value = "contactMBean")
@RequestScoped
public class ContactMBean {
    @EJB
    private ContactEJB contactEJB;
    private Contact contact = new Contact();
    private List<Contact> contacts = new ArrayList<>();
    public String doCreateContact() {
        contact = contactEJB.createContact(contact);
        contacts = contactEJB.findContacts();
        return "contactList.xhtml";
    }
    public void validateEmail(FacesContext context, UIComponent toValidate, Object value) {
        String emailPattern = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
        Pattern p = Pattern.compile(emailPattern);
        Matcher m = p.matcher((String) value);
        if (!m.matches()) {
            ((UIInput) toValidate).setValid(false);
            FacesMessage message = new FacesMessage("Invalid email! Please enter a valid email.");
            context.addMessage(toValidate.getClientId(context), message);
        }
    }
//...getters and setters
}
index.xhtml
    <h:head>
        <title>Create new Contact</title>
    </h:head>
    <h:body>
        <h:form>
            <h:panelGrid columns="2">
                <h:outputLabel value="Name : "/>
                <h:inputText value="#{contactMBean.contact.name}" required="true"/>
                <h:outputLabel value="Email : "/>
<h:inputText value="#{contactMBean.contact.email}" required="true" validator="#{contactMBean.validateEmail}">
                    
                </h:inputText>
                <h:outputLabel value="Phone : "/>
                <h:inputText value="#{contactMBean.contact.phone}"/>                
                
            </h:panelGrid>
            <h:commandButton value="Create New Contact" action="#{contactMBean.doCreateContact}"/>
        </h:form>
    </h:body>
 
contactList.xhtml
    <h:body>
        <h:dataTable value="#{contactMBean.contacts}" var="c" border="1" width="50%">
            <h:column>
                <f:facet name="header">
                    <h:outputText value="ID"/>
                </f:facet>
                <h:outputText value="#{c.id}"/>
            </h:column>
            
            <h:column>
                <f:facet name="header">
                    <h:outputText value="Name"/>
                </f:facet>
                <h:outputText value="#{c.name}"/>
            </h:column>
            
            <h:column>
                <f:facet name="header">
                    <h:outputText value="Email"/>
                </f:facet>
                <h:outputText value="#{c.email}"/>
            </h:column>
            
            <h:column>
                <f:facet name="header">
                    <h:outputText value="Phone"/>
                </f:facet>
                <h:outputText value="#{c.phone}"/>
            </h:column>
                      
        </h:dataTable>
        <h:form>
            <h:link outcome="index.xhtml" value="Create new Contact"/>
        </h:form>
            
    </h:body>

Conclusion

Managed beans can perform several similar functions and their implementation varies according to the need and business logic of the UI. Java EE7 rejuvenated managed bean usage through Context Dependency Injection (CDI). JSF has no components for date input or other complex inputs, however these can be created as composite JSF components. If one is really interested in some ready-made rich UI in JSF, look for PrimeFaces, Icefaces, etc.


Tags: JSF, Facelets




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel