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

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

Comments:

[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

Posted by uberVU - social comments on February 16, 2010 at 06:55 AM PST #

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.

Posted by paul cunningham on February 17, 2010 at 10:57 PM PST #

Paul,

Let me know if:

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

serves your purpose ?

-Arun

Posted by Arun Gupta on February 18, 2010 at 03:56 AM PST #

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

-NBW

Posted by Noah White on February 23, 2010 at 10:32 AM PST #

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.

Posted by Arun Gupta on February 23, 2010 at 01:13 PM PST #

Is there a way when you click the button after fill inputtext feild, some other inputtext feilds from another page(xhtml) show in the same page or at the buttom. if any body know please help me. Thank you.

Posted by guest on May 15, 2011 at 03:01 PM PDT #

guest, If you know the backing bean for the other XHTML page then you may be able to show the data in this page. Just create a new outputText field and bind it to that value.

Posted by Arun Gupta on May 16, 2011 at 02:39 AM PDT #

I mean can I use xmlhttp in my xhtml or not? I know I can do with jsp but I want to used with jsf 2.0. like this code Can I used in my index.xhtml? <script type="text/javascript"> function showUser(str) { if (str=="") { document.getElementById("txtHint").innerHTML=""; return; } if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementById("txtHint").innerHTML=xmlhttp.responseText; } } xmlhttp.open("GET","getuser.xhtml?q="+str,true); xmlhttp.send(); } </script> </head>

Posted by leader on May 16, 2011 at 05:17 AM PDT #

I need to know how you click a buttom another form from onather page displays at the buttom of my main page. I know how to do this in php or jsp but I want to know how to with jsf 2.0 Thank you very much

Posted by leader on May 16, 2011 at 12:24 PM PDT #

leader, Please follow up with your questions on webtier@glassfish.java.net for the benefit of a broader audience.

Posted by Arun Gupta on May 17, 2011 at 09:05 AM PDT #

Post a Comment:
Comments are closed for this entry.
About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today