Miles to go …

February 11, 2010

TOTD #123: f:ajax, Bean Validation for JSF, CDI for JSF and JPA 2.0 Criteria API – all in one Java EE 6 sample application

Filed under: General — arungupta @ 11:23 pm

Taking TOTD #120 forward, we’ll add the following features to our application:

  • Add database access using Java Persistence API 2.0
  • Show type-safe Criteria API from JPA 2.0
  • Use Context & Dependency Injection for JSF managed beans
  • Add Ajax effects from Java Server Faces 2.0
  • Add Bean Validation to the JSF managed bean

Lets get started!

  1. Use the Maven project created in TOTD #120 and update the directory such that it looks like:
    src
    src/main
    src/main/java
    src/main/java/org
    src/main/java/org/glassfish
    src/main/java/org/glassfish/samples
    src/main/java/org/glassfish/samples/SakilaBean.java
    src/main/java/org/glassfish/samples/SimpleBean.java
    src/main/java/org/glassfish/samples/SimpleEJB.java
    src/main/java/org/glassfish/samples/SimpleServlet.java
    src/main/webapp
    src/main/webapp/index.jsp
    src/main/webapp/index.xhtml
    src/main/webapp/sakila.xhtml
    src/main/webapp/show.xhtml
    src/main/webapp/WEB-INF
    src/main/webapp/WEB-INF/beans.xml
    src/main/webapp/WEB-INF/web.xml
    

    The key differences are:

    1. "beans.xml" is an empty file to enable Context & Dependency Injection bean discovery.
    2. The JPA Persistence Unit is copied and installed in local Maven repository as explained in TOTD #122.
    3. "web.xml" is added to bootstrap the Java Server Faces runtime. This is required because "@ManagedBean" annotation on "SimpleBean" class is now changed to "@javax.inject.Named". The JSF runtime is automatically registered and booted if any bean in the webapp is annotated with "@ManagedBean" or one of the JSF common classes (such as Converter, Validator, or Renderer) is implemented or extended. If none of these "hints" are available in the application, and it’s required, then it needs to enabled explicitly.

Here are the updated files, changes are highlighted in bold and explained after each fragment:

index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtm
l1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Enter Name &amp; Age</title>
</h:head>
<h:body>
<h1>Enter Name &amp; Age</h1>
<h:form>
<h:panelGrid columns="3">
<h:outputText value="Name:"/>
<h:inputText value="#{simplebean.name}" title="name" id="name" required="true"/>
<h:message for="name" style="color: red"/>
<h:outputText value="Age:"/>
<h:inputText value="#{simplebean.age}" title="age" id="age" required="true"/>
<h:message for="age" style="color: red"/>
</h:panelGrid>
<h:commandButton action="show" value="submit"/>
</h:form>
</h:body>
</html>

Changed the panelGrid from "2" columns to "3". This allows for any validation messages to be displayed right next to the source. Also added "<h:message …/>" to display the validation messages.

SimpleBean.java

package org.glassfish.samples;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraints.Min;

@Named("simplebean")
@RequestScoped
public class SimpleBean {
@NotNull
@Size(min=2, message="Name must be at least 2 characters")
 private String name;
@NotNull
@Min(5)
 private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}

The changes to the above code are listed below:

  • Replaced "@ManagedBean" with "@Named" annotation defined in JSR 330 and used by CDI.
  • Using constraints defined by Bean Validation APIs (JSR 303) to check for
    • Both bean properties to be non-null
    • Name to be at least 2 characters
    • A minimum age of 5
    • There are several other pre-defined constraints in "javax.validation.constraints" package and new constraints can be easily defined as well.

SakilaBean.java

package org.glassfish.samples;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.faces.event.ActionEvent;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceUnit;
import javax.persistence.EntityManagerFactory;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import sakila.Actor;
@Named("sakilabean")
@RequestScoped
public class SakilaBean {
@PersistenceUnit(unitName="SakilaPU")
EntityManagerFactory emf;
private List<Actor> actors;
private int length;
private int totalActors;
// getters & setters
public List<Actor> getActors() { return actors; }
public void setActors(List<Actor> actors) { this.actors = actors; }
public int getLength() { return length; }
public void setLength(int length) { this.length = length; }
public int getTotalActors() { return totalActors; }
public void setTotalActors(int totalActors) { this.totalActors = totalActors; }
public void findActors(ActionEvent evt) {
EntityManager em = emf.createEntityManager();
CriteriaBuilder cb = emf.getCriteriaBuilder();
CriteriaQuery<Actor> criteria = cb.createQuery(Actor.class);
// FROM clause
Root<Actor> actor = criteria.from(Actor.class);
// SELECT clause
criteria.select(actor);
// WHERE clause
criteria.where(cb.greaterThan(
cb.length(actor.get("firstName").as(String.class)), length));
// FIRE
actors = em.createQuery(criteria).getResultList();
totalActors = actors.size();
}
}

The key points:

  • This is a CDI bean marked by @Named and used in the JSF view (shown next), with the name "sakilabean"
  • EntityManagerFactory is injected using @PersistenceUnit
  • "findActors" method builds the query using Criteria API. Returns actors’ names limited by the number of characters in their first name.
  • Queries "Actor" table from the database and set bean properties "actors" and "totalActors".
  • Uses "length" bean property (set from the JSF view) to restrict the number of characters in the name.

sakila.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtm
l1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Sakila - Actors Listing</title>
</h:head>
<h:body>
<h1>Sakila - Actors Listing</h1>
<h:form>
<h:outputText value="Show actors with first name's length &lt;"/>
<h:inputText value="#{sakilabean.length}" id="length" required="true" size="5"/>
<h:commandButton actionListener="#{sakilabean.findActors}" value="submit">
<f:ajax execute="length" render="actorTable totalActors"/>
</h:commandButton><br/>
Total actors found: <h:outputText value="#{sakilabean.totalActors}" id="totalActors"/><p/>
<h:dataTable var="actor" value="#{sakilabean.actors}" border="1" id="actorTable">
<h:column><h:outputText value="#{actor.firstName}"/>, <h:outputText value="#{actor.lastName}"/></h:column>
</h:dataTable>
</h:form>
</h:body>
</html>

Key points:

  • This JSF view shows a form that accepts a number used for restricting the length of actors’ first name. The value of this attribute is bound to "length" property of the underlying bean.
  • Command Button is tied to a JSF Action Listener which is then bound to "findActors" method in the bean. This method executes the JPA query explained above.
  • "f:ajax" is a newly introduced tag in JSF 2.0 and means an Ajax request is performed on the "onClick" event of the rendered button, "findActors" method in the bean in this case. The tag also specifies other tags in the page, "actorTable" and "totalActors" in this case, that needs to be rendered after the request is completed. The input parameter to the Ajax request is specified using "execute" attribute. Read more about this tag here or section 10.4.1.1 of the JSF 2 specification.

Package and deploy the application as:

mvn clean package
./bin/asadmin deploy --force=true ~/samples/javaee6/simplewebapp/target/simplewebapp-1.0-SNAPSHOT.war

The application is now accessible at "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/sakila.jsf" and looks like:

Enter a value of "4" in the text box and hit "Submit":

Only the HTML table of names and the total count of actors is refreshed showcasing partial page refresh.

Now enter a value of "8" and hit "Submit":

Enjoy!

More Java EE 6 features to be shown in subsequent blogs.

Technorati: totd javaee glassfish v3 javaserverfaces ajax jpa cdi beanvalidation

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
Related posts:
  1. TOTD #120: Deployment Descriptor-free Java EE 6 application using JSF 2.0 + EJB 3.1 + Servlets 3.0
  2. TOTD #124: Using CDI + JPA with JAX-RS and JAX-WS
  3. TOTD #158: Java EE 7 JSRs: JPA 2.1, JAX-RS 2.0, Servlets 3.1, EL 3.0, JMS 2.0, JSF 2.2, CDI 1.1, Bean Validation 1.1
  4. TOTD #148: JPA2 Metamodel Classes in NetBeans 7.0 – Writing type-safe Criteria API
  5. TOTD #94: A simple Java Server Faces 2.0 + JPA 2.0 application – Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3

5 Comments »

  1. [Trackback] This post was mentioned on Twitter by arungupta: New Blog: TOTD #123: f:ajax, Bean Validation for JSF, CDI for JSF and JPA 2.0 Criteria API – all in one Java EE 6 … http://bit.ly/coXe5r

    Comment by uberVU - social comments — February 16, 2010 @ 2:55 pm

  2. Hi Arun,

    Is there anyway I could use f:ajax
    to refresh a datatable automatically
    at set intervals.

    just like a4f:poll did in rich faces.

    cheers,
    paul.

    Comment by paul cunningham — February 18, 2010 @ 6:57 am

  3. Paul,

    Let me know if:

    http://weblogs.java.net/blog/2009/07/03/tale-two-components-jsf2

    serves your purpose ?

    -Arun

    Comment by Arun Gupta — February 18, 2010 @ 11:56 am

  4. Is there a particular reason you chose to go with a PersistenceUnit/Resource_Local approach vs. PersistenceContext/JTA approach? Thnx,

    -NBW

    Comment by Noah White — February 23, 2010 @ 6:32 pm

  5. Noah,

    The PU was created for a Java SE application and that’s why Resource_Local was used. For a Java EE application, it should be JTA unless the transactions are explicitly managed by the application.

    Comment by Arun Gupta — February 23, 2010 @ 9:13 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.
Powered by WordPress