Friday Feb 08, 2013

Resource Library Contracts in JSF2.2 (TOTD #202)


JavaServer Faces 2 introduced Facelets as the default View Declaration Language. Facelets allows to create templates using XHTML and CSS that can be then used to provide a consistent look-and-feel across different pages of an application. JSF 2.2 defines Resource Library Contracts that allow facelet templates to be applied to an entire application in a reusable and interchangeable manner.

This Tip Of The Day (TOTD) will explain how you can leverage them in your web application.

The complete source code for this sample can be downloaded here. This will run on GlassFish build 72 + latest JSF 2.2.0 SNAPSHOT copied over "glassfish3/glassfish/modules/javax.faces.jar" file.

Consider the following WAR file:
index.xhtml
user/index.xhtml
contracts/blue/layout.css
contracts/blue/template.xhtml
contracts/red
contracts/red/layout.css
contracts/red/template.xhtml
WEB-INF/faces-config.xml

The application also has two pages - "index.xhtml" and "user/index.xhtml". All contracts reside in the "contracts" directory of the WAR. All templates and resources for a contract are in their own directory. For example, the structure above has two defined contracts "blue" and "red". Each contract has a "template.xhtml" and a CSS. Each template is called as "declared template". The "template.xhtml" has <ui:insert> tags called as "declared insertion points". CSS and other resources bundled in the directory are "declared resources". The "declared template", "declared insertion points", and "declared resources" together make the definition of the resource library contract. A template client needs to know the value of all three in order to use the contract.

In our case, templates have similar "ui:insert" sections and template clients will accordingly have "ui:define" sections. The difference will primarily be in the CSS. "index.xhtml" will refer to the template as:

<ui:composition template="/template.xhtml">
<ui:define name="content">
. . .
</ui:define>
</ui:composition>

The usage of the contracts is defined in "faces-config.xml" as:

<application>
<resource-library-contracts>
<contract-mapping>
<url-pattern>/user/*</url-pattern>
<contracts>blue</contracts>
</contract-mapping>
<contract-mapping>
<url-pattern>*</url-pattern>
<contracts>red</contracts>
</contract-mapping>
</resource-library-contracts>
</application>
A contract is applied based upon the URL pattern invoked. Based upon the configuration specified here, "red" contract will be applied to "faces/index.xhtml" and "red" contract will be applied to "faces/user/index.xhtml".

The template of the page can be changed dynamically as well. For example consider "index.xhtml" is updated as:

<f:view contracts="#{contractsBean.contract}">
<ui:composition template="/template.xhtml">

<ui:define name="content">
<a href="#{facesContext.externalContext.requestContextPath}/faces/user/index.xhtml">Go to</a> other contract
<p/>
Look at WEB-INF/faces-config.xml for contract configuration.
<p/><p/>
Choose a template:<br/>
<h:form>
<h:selectOneRadio value="#{contractsBean.contract}" layout="pageDirection" required="true">
<f:selectItem itemValue="red" itemLabel="red"/>
<f:selectItem itemValue="blue" itemLabel="blue"/>
</h:selectOneRadio>
<h:commandButton value="Apply" action="index" />
</h:form>
</ui:define>

</ui:composition>
</f:view>
The "ui:composition" is included in "f:view". An additional "contracts" attribute can bind to an EL. The value of this EL is populated from the radio button in the newly added form. Now you can choose a radio button, click on the "Apply" button and the new template will be applied to the page. The bean is very trivial:

@Named
@SessionScoped
public class ContractsBean implements Serializable {

String contract = "red";

public String getContract() {
return contract;
}

public void setContract(String contract) {
this.contract = contract;
}
}

This is a very powerful feature. Imagine providing different look-and-feel for your website and letting the user choose them, fun eh ?

Contracts may be packaged as a JAR file. Such a JAR file maybe bundled in "WEB-INF/lib" directory. Read section 2.7 for more details about the packaging requirement and a marker file that identifies the JAR to contain a contract.

In the specification ...
  • Section 10.1.3 provide background on the feature.
  • Section 2.7 provide formal definition of the feature.
  • Section 11.4.2.1 defines how the contracts are identified during application startup.
Create templates as JAR files and reuse them across different applications, enjoy!

Thursday Feb 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

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

Friday Feb 05, 2010

TOTD #120: Deployment Descriptor-free Java EE 6 application using JSF 2.0 + EJB 3.1 + Servlets 3.0

Here is trivial Java EE 6 application that is keeping you away from any deployment descriptors. It uses Java Server Faces 2.0, Enterprise Java Beans 3.1, and Servlet 3.0. This application shows the following Java EE 6 features:

  1. No-interface view for EJB
  2. EJBs packaged in a WAR file
  3. Optional "faces-config.xml" for Java Server Faces
  4. FacesServlet registered using Servlet 3.0 programmatic registration APIs
  5. Java Server Faces navigation rules using convention-over-configuration
  6. Optional "web.xml" for Servlets 3.0

The WAR file structure is:

./index.jsp
./index.xhtml
./META-INF
./show.xhtml
./WEB-INF
./WEB-INF/classes
./WEB-INF/classes/org
./WEB-INF/classes/org/glassfish
./WEB-INF/classes/org/glassfish/samples
./WEB-INF/classes/org/glassfish/samples/SimpleBean.class
./WEB-INF/classes/org/glassfish/samples/SimpleEJB.class
./WEB-INF/classes/org/glassfish/samples/SimpleServlet.class

Look ma, no deployment descriptors!

So how do you create this application:

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=org.glassfish.samples -DartifactId=simplewebapp

This application is purposely not generated as a web application (missing "-DarchetypeArtifactId=maven-archetype-webapp"). If you specify this property then it will generate "WEB-INF/web.xml" which we don't intend to use.

Change "pom.xml" to:

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.glassfish.samples</groupId>
   <artifactId>simplewebapp</artifactId>
   <packaging>war</packaging>
   <version>1.0-SNAPSHOT</version>
   <name>simplewebapp</name>
   <url>http://maven.apache.org</url>
   <repositories>
     <repository>
       <id>glassfish-repository</id>
       <name>Java.net Repository for Glassfish</name>
       <url>http://download.java.net/maven/glassfish</url>
     </repository>
   </repositories>
   <build>
     <plugins>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>2.0.2</version>
         <configuration>
           <source>1.5</source>
           <target>1.5</target>
         </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-war-plugin</artifactId>
         <version>2.1-beta-1</version>
         <configuration>
           <failOnMissingWebXml>false</failOnMissingWebXml>
         </configuration>
       </plugin>
     </plugins>
   </build>
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>3.8.1</version>
       <scope>test</scope>
     </dependency>
    <dependency>
       <groupId>javax</groupId>
       <artifactId>javaee-api</artifactId>
       <version>6.0</version>
       <scope>provided</scope>
    </dependency>
   </dependencies>
</project>

In the above code:
  • "maven-compiler-plugin" needs to be specified as the default source level for Maven compile plugin is JDK 1.3. It's been over 9 years JDK 1.3 was released, not even listed on Java SE standard downloads page, EOLed many years ago. Vote/Comment for the issue MCOMPILER-80 if you'd like this bug to be fixed.
  • Adding "failOnMissingWebXml" ensures that Maven packages the WAR file even though no "web.xml" is present.
  • The complete list of Maven coordinates for GlassFish are available here.

Create the directory structure as:

./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/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/show.xhtml

Once again, there are no deployment descriptors, just plain Java files and XHTML/JSP pages.

Here are the different source files with explanation after each one of them:

SimpleBean.java
package org.glassfish.samples;

import javax.faces.bean.ManagedBean;

@ManagedBean(name="simplebean")
public class SimpleBean {
    private String name;
    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; }
}

This is currently a simple JSF managed bean. TOTD #109 explains how to convert a JSF managed bean to use CDI. A future blog will show how to convert this sample to use CDI.

SimpleEJB.java

package org.glassfish.samples;

import javax.ejb.Stateless;

@Stateless
public class SimpleEJB {
    public String sayHello(String name) {
        return "Hello " + name + "!!!";
    }
}

The session bean has no interface, just the @Stateless annotation.

SimpleServlet.java

package org.glassfish.samples;

import javax.ejb.EJB;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;
import java.io.PrintWriter;
import java.io.IOException;

/\*\*
 \* Hello world!
 \*/
@WebServlet(urlPatterns={"/SimpleServlet"})
public class SimpleServlet extends HttpServlet {
    @EJB SimpleEJB bean;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h2>Serving at: " + request.getContextPath() + "</h2>");
        out.println("<h2>Invoking EJB: " + bean.sayHello("Duke") + "</h2>");
        out.println("</body></html>");
    }
}

The servlet injects the EJB in the application, display the servlet context and the result of invoking the business operation of the EJB.


index.jsp

<html>
<body>
<h2>Hello World!</h2>
Invoke the Servlet by clicking <a href="SimpleServlet">here</a>.
</body>
</html>

This is just a placeholder for invoking the servlet.

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="2">
 <h:outputText value="Name:"/>
 <h:inputText value="#{simplebean.name}" title="name" id="name" required="true"/>
 <h:outputText value="Age:"/>
 <h:inputText value="#{simplebean.age}" title="age" id="age" required="true"/>
 </h:panelGrid>
 <h:commandButton action="show" value="submit"/>
 </h:form>
 </h:body>
</html>


JSF 2 uses Facelets as viewing technology and so an ".xhtml" file is used for all the JSF tags. This page is intentionally kept simple and not using any templating, composition, or any other features of Facelets. This page renders an HTML form with two text boxes and a command button, binds the value of text box to the managed bean, and displays the page "show.xhtml" when the command button is clicked. The default JSF 2 navigation handler try to match a view on the disk ("show.xhtml" in this case) based upon the "action" attribute.

show.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:h="http://java.sun.com/jsf/html">
 <h:head>
 <title>Show Name &amp; Age</title>
 </h:head>
 <h:body>
 <h1>Show Name &amp; Age</h1>
<h:form action="show">
 <h:panelGrid columns="2">
 <h:outputText value="Name:"/>
 <h:outputText value="#{simplebean.name}" />
 <h:outputText value="Age:"/>
 <h:outputText value="#{simplebean.age}" />
 </h:panelGrid>
 </h:form>
 </h:body>
</html>

This page reads the bean properties (stored from previous page) and displays them on the page.

How do you build this entire application ?

mvn clean package

Lets deploy the application on a Java EE 6 compliant application server, GlassFish v3 (download here):

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

And now your application is accessible at "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/index.jsp" and looks like:

Clicking on "here" looks like:

The JSF page is accessible at "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/index.jsf" and looks like (after entering the values):

Notice that even though the page is named "index.xhtml", it's accessed as "index.jsf". This is because the JSF specification provides recommended mapping for FacesServlet to "\*.faces" and "/faces/\*". In addition, Mojarra (Reference Implementation of JSF2 in GlassFish) also adds a mapping to "\*.jsf". Any views using these URL pattersn are routed through FacesServlet. So alternative URLs for our page are "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/index.faces" and "http://localhost:8080/simplewebapp-1.0-SNAPSHOT/faces/index.xhtml".

Clicking on "Submit" shows the following page:



That's it!

Here are several other useful entries:

  • TOTD #109 : How to convert a JSF managed bean to JSR 299 bean (Web Beans) ?
  • TOTD #108 : Java EE 6 web application (JSF 2.0 + JPA 2.0 + EJB 3.1) using Oracle, NetBeans, and GlassFish
  • TOTD #102 : Java EE 6 (Servlet 3.0 and EJB 3.1) wizards in Eclipse
  • TOTD #99 : Creating a Java EE 6 application using MySQL, JPA 2.0 and Servlet 3.0 with GlassFish Tools Bundle for Eclipse
  • TOTD #98 : Create a Metro JAX-WS Web service using GlassFish Tools Bundle for Eclipse
  • TOTD #95 : EJB 3.1 + Java Server Faces 2.0 + JPA 2.0 web application - Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3
  • 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
  • TOTD #93 : Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3 - A simple Servlet 3.0 + JPA 2.0 app

The next follow up blog will show "Hello World"s of Context & Dependency Injection, Bean Validation, Java API for Restful Web services, Java Persistence API, Interceptors, and other Java EE 6 specifications in this application.

Technorati: totd javaee glassfish v3 javaserverfaces servlet3 ejb maven

Friday Oct 02, 2009

TOTD #109: How to convert a JSF managed bean to JSR 299 bean (Web Beans) ?

This entry is a follow up to TOTD #95 and shows how to use the recent integrations of JSR 299 in GlassFish v3 to convert a JSF managed bean to a JSR 299 bean (aka Web Beans). The TOTD #95 describes a simple Java EE 6 web application that uses Java Server Faces 2.0 components for displaying the results of a database query conducted by EJB 3.1 and JPA 2.0 classes.

The EJB class, which also acts as the JSF managed bean, looks like:

@javax.ejb.Stateless
@ManagedBean
public class StateList {
  @PersistenceUnit
  EntityManagerFactory emf;

  public List getStates() {
    return    emf.createEntityManager().createNamedQuery(”States.findAll”).getResultList();
  }
}

Three changes are required to convert this class into a JSR 299 compliant bean (Web Bean) as listed below:

  1. Add an empty "beans.xml" to the WEB-INF directory.
  2. Replace "@ManagedBean" with "@javax.inject.Named annotation". "@javax.inject" annotations are defined by JSR 330.
  3. Resource injection does not work with JPA classes, yet, so populate EntityManager explicitly as explained below:
    1. Replace EntityManagerFactory resource injection:

      @PersistenceUnit
      EntityManagerFactory emf;
      

      with:
      EntityManager emf = Persistence.createEntityManagerFactory("HelloEclipseLinkPU");
      
    2. Add the required entity classes explicitly to "persistence.xml". If the persistence unit is injected then the container automatically scans the web application root for any entity classes.
      1. Expand "Configuration Files" and edit "persistence.xml".
      2. Uncheck "Include All Entity Classes in ..." check box.
      3. Click on "Add Class...", select "state.States", and click on "OK".

That's it, re-deploy your application and now you are using the Web Beans integration in GlassFish v3 instead of JSF managed bean. The output is available at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" as shown:



This is the exact same output as shown in TOTD #95.

Now, one-by-one, JPA, EJB, Transactions and other components will start working. Read Roger's blog for another example of Web Beans in GlassFish.

A complete archive of all the tips is available here.

Technorati: totd glassfish v3 mysql javaee6 javaserverfaces webbeans jsr299 netbeans

Thursday Oct 01, 2009

TOTD #108: Java EE 6 web application (JSF 2.0 + JPA 2.0 + EJB 3.1) using Oracle, NetBeans, and GlassFish

TOTD #106 explained how to install Oracle database 10g R2 on Mac OS X. TOTD #107 explained how to connect this Oracle database using NetBeans. This Tip Of The Day will explain how to use the sample HR database (that comes with Oracle database server) to write a simple Java EE 6 application.

This application will use Java Server Faces 2.0 for displaying the results, Enterprise Java Beans 3.1 + Java Persistence API 2.0 for middle tier, and Oracle database server + GlassFish v3 as the backend. The latest promoted build (65 of this writing) will not work because of the issue #9885 so this blog will use build 63 instead.

Several improvements have been made over NetBeans 6.8 M1 build and this blog is using the nightly build of 9/27. The environment used in this blog is:

  • NetBeans 9/27 nightly
  • GlassFish v3 build 63
  • Oracle database server 10.2.0.4.0 R2 on Mac OS X
  • Oracle JDBC Driver type 4 (ojdbc6.jar)

Lets get started!

  1. Configure GlassFish v3 with JDBC connection
    1. Download and unzip build 63.
    2. Download ojdbc6.jar and copy to "glassfishv3/glassfish/domains/domain1/lib/ext" directory.
    3. Start the Application Server as:
      ./bin/asadmin start-domain --verbose &
      
    4. Create a JDBC connection pool as:
      ./bin/asadmin create-jdbc-connection-pool --datasourceclassname oracle.jdbc.pool.OracleDataSource --restype javax.sql.DataSource --property "User=hr:Password=hr:URL=jdbc\\:oracle\\:thin\\:@localhost\\:1521\\:orcl" jdbc/hr
      

      and verify the connection pool as:
      ./bin/asadmin ping-connection-pool jdbc/hr
      
    5. Create a JDBC resource as:
      ./bin/asadmin create-jdbc-resource --connectionpoolid jdbc/hr jdbc/hr
      
  2. Configure GlassFish v3 build 63 in NetBeans
    1. In NetBeans IDE "Services" panel, right-click on "Servers" and click on "Add Server...". Choose "GlassFish v3" and provide a name as shown below:


    2. Click on "Next >" and specify the unzipped GlassFish location as:



      and click on "Finish".
  3. Create the Java EE 6 application
    1. In "Projects" pane, right-click and select "New Project...".
    2. Choose "Java Web" and "Web Application" and click on "Next". Choose the project name as "HelloOracle":



      and click on "Next >".
    3. Select the recently added GlassFish v3 server and choose "Java EE 6 Web" profile:



      and click on "Next >". Notice "Java EE 6 Web" profile is chosen as the Java EE version.
    4. Select "JavaServer Faces" on the frameworks page:



      and click on "Finish". Notice the JSF libraries bundled with the App Server are used.
  4. Create the Java Persistence Unit
    1. Right-click on the project, select "New", "Entity Classes from Database...":


    2. From the Data Source, select "jdbc/hr" as shown:



      This is the same JDBC resource created earlier. Select "EMPLOYEES" from the Available Table, click on "Add >" to see the output as:



      The related tables are automatically included. Click on "Next >".
    3. Click on "Create Persistence Unit ..." and take all the defaults and click on "Create".
    4. Specify the package name as "model":



      and click on "Finish". This generates a JPA-compliant POJO class that provide access to tables in the underlying Oracle database. The class name corresponding to each table is shown in the wizard.
  5. Create Enterprise Java Beans
    1. Right-click on the project and select "New Class...".
    2. Specify the class name as "EmployeesBean" and package as "controller", click on "Finish".
    3. Annotate the class to make it an Enterprise Java Bean and a JSF Managed Bean as:
      @javax.ejb.Stateless
      @javax.faces.bean.ManagedBean
      


      Notice, the EJB is bundled in the WAR file and no special type of modules are required. Java EE 6 provides simplified packaging of EJB which makes it really ease to use.

      Also this application is currently using JSF managed bean but will use JSR 299 (aka Web Beans) in a future blog.
    4. Inject the Persistence Unit by adding the following variable:
      @PersistenceUnit
      EntityManagerFactory emf;
      
    5. Add a new method to retrieve the list of all employees as:
      public List getEmployees() {
       return em.createNamedQuery("Employees.findAll").getResultList();
      }
      

      "Employees.findAll" is a default NamedQuery generated by NetBeans and makes it easy to query the database. Several other queries are generated for each mapped JPA class, such as "Employees.findByEmployeeId" and "Employees.findByFirstName". Custom queries can also be created and specified on the POJO class.

      The completed class looks like:
      @Stateless
      @ManagedBean
      public class EmployeesBean {
      
       public List getEmployees() {
       return emf.createEntityManager().createNamedQuery("Employees.findAll").getResultList();
       }
      }
      
  6. Use EJB in the generated JSF page
    1. JSF 2 uses Facelets as the templating mechanism and NetBeans generate a simple "index.xhtml" file to start with. Expand "Web Pages" and open "index.xhtml".
    2. Replace the body template with:
      <h1>First Java EE 6 app using Oracle database</>
      <h:dataTable var="emp" value="#{employeesBean.employees}" border="1">
       <h:column><h:outputText value="#{emp.lastName}"/>, <h:outputText value="#{emp.firstName}"/></h:column>
       <h:column><h:outputText value="#{emp.email}"/></h:column>
       <h:column><h:outputText value="#{emp.hireDate}"/></h:column>
       </h:dataTable>
      

      It uses JSF value expressions to bind the Enterprise Java Bean and dumps the HTML formatted name, email, and hire date of each employee in the database.
  7. Run the project: Right-click on the project and select "Run" to see the output at "http://localhost:8080/HelloOracle/" as:

So we can easily create a Java EE 6 application using NetBeans, Oracle, and GlassFish.

A complete archive of all the TOTDs is available here.

This and other similar applications will be demonstrated at the upcoming Oracle Open World.

Technorati: totd oracle database glassfish v3 javaee javaserverfaces ejb jpa netbeans oow

Sunday Aug 16, 2009

TOTD #95: EJB 3.1 + Java Server Faces 2.0 + JPA 2.0 web application - Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3


TOTD #93 showed how to get started with Java EE 6 using NetBeans 6.8 M1 and GlassFish v3 by building a simple Servlet 3.0 + JPA 2.0 web application. TOTD #94 built upon it by using Java Server Faces 2 instead of Servlet 3.0 for displaying the results. However we are still using a POJO for all the database interactions. This works fine if we are only reading values from the database but that's not how a typical web application behaves. The web application would typically perform all CRUD operations. More typically they like to perform one or more CRUD operations within the context of a transaction. And how do you do transactions in the context of a web application ? Java EE 6 comes to your rescue.

The EJB 3.1 specification (another new specification in Java EE 6) allow POJO classes to be annotated with @EJB and bundled within WEB-INF/classes of a WAR file. And so you get all transactional capabilities in your web application very easily.

This Tip Of The Day (TOTD) shows how to enhance the application created in TOTD #94 and use EJB 3.1 instead of the JSF managed bean for performing the business logic. There are two ways to achieve this pattern as described below.

Lets call this TOTD #95.1
  1. The easiest way to back a JSF page with an EJB is to convert the managed bean into an EJB by adding @javax.ejb.Stateless annotation. So change the  "StateList" class from TOTD #94 as shown below:

    @javax.ejb.Stateless
    @ManagedBean
    public class StateList {
        @PersistenceUnit
        EntityManagerFactory emf;

        public List<States> getStates() {
            return emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
        }
    }

    The change is highlighted in bold, and that's it!
Because of "Deploy-on-save" feature in NetBeans and GlassFish v3, the application is autodeployed. Otherwise right-click on the project and select Run (default shortcut "F6"). As earlier, the results can be seen at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or "http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml" and looks like:



The big difference this time is that the business logic is executed by an EJB in a fully transactional manner. Even though the logic in this case is a single read-only operation to the database, but you get the idea :)

Alternatively, you can use the delegate pattern in the managed bean as described below. Lets call this #95.2.
  1. Right-click on the project, select "New", "Session Bean ..." and create a stateless session bean by selecting the options as shown below:



    This creates a stateless session with the name "StateBeanBean" (bug #170392 for redundant "Bean" in the name).
  2. Simplify your managed bean by refactoring all the business logic to the EJB as shown below:

    @Stateless
    public class StateBeanBean {
        @PersistenceUnit
        EntityManagerFactory emf;
        
        public List<States> getStates() {
            return emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
        }
    }

    and

    @ManagedBean
    public class StateList {
        @EJB StateBeanBean bean;

        public List<States> getStates() {
            return bean.getStates();
        }
    }

    In fact the EJB code can be further simplified to:

    @Stateless
    public class StateBeanBean {
        @PersistenceContext
        EntityManager em;
       
        public List<States> getStates() {
            return em.createNamedQuery("States.findAll").getResultList();
        }
    }

    The changes are highlighted in bold.
If the application is already running then Deploy-on-Save would have automatically deployed the entire application. Otherwise right-click on the project and select Run (default shortcut "F6"). Again, the results can be seen at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or "http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml" and are displayed as shown in the screenshot above.

The updated directory structure looks like:



The important point to note is that our EJB is bundled in the WAR file and no additional deployment descriptors were added or existing ones modified to achieve that. Now, that's really clean :)

The next blog in this series will show how managed beans can be replaced with WebBeans, err JCDI.

Also refer to other Java EE 6 blog entries.

Please leave suggestions on other TOTD that you'd like to see. A complete archive of all the tips is available here.

Technorati: totd glassfish v3 mysql javaee6 javaserverfaces jpa2 ejb netbeans

Thursday Aug 13, 2009

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


TOTD #93 showed how to get started with Java EE 6 using NetBeans 6.8 M1 and GlassFish v3 by building a simple Servlet 3.0 + JPA 2.0 web application. JPA 2.0 + Eclipselink was used for the database connectivity and Servlet 3.0 was used for displaying the results to the user. The sample demonstrated how the two technologies can be mixed to create a simple web application. But Servlets are meant for server-side processing rather than displaying the results to end user. JavaServer Faces 2 (another new specification in Java EE 6) is designed to fulfill that purpose.

This Tip Of The Day (TOTD) shows how to enhance the application created in TOTD #93 and use JSF 2 for displaying the results.
  1. Right-click on the project, select "Properties", select "Frameworks", click on "Add ..." as shown below:



    Select "JavaServer Faces" and click on "OK". The following configuration screen is shown:



    Click on "OK" to complete the dialog. This generates a whole bunch of files (7 to be accurate) in your project. Most of these files are leftover from previous version of NetBeans and will be cleaned up. For example, "faces-config.xml" is now optional and "forwardToJSF.jsp" is redundant.
  2. Anyway, lets add a POJO class that will be our managed bean. Right-click on "server" package and select "New", "Java Class ...", give the name as "StateList". Change the class such that it looks like:

    package server;

    import java.util.List;
    import javax.faces.bean.ManagedBean;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.PersistenceUnit;
    import states.States;

    /\*\*
     \* @author arungupta
     \*/
    @ManagedBean
    public class StateList {
        @PersistenceUnit
        EntityManagerFactory emf;

        public List<States> getStates() {
            return emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
        }
    }

    Here are the main characterisitcs of this class:
    1. This is a POJO class with @ManagedBean annotation. This annotation makes this class a managed bean that can be used in the JSF pages. As no other annotations or parameters are specified, this is a request-scoped managed bean with the name "stateList" and lazily initialized. More details about this annotation are available in the javadocs.
    2. The persistence unit created in TOTD #93 is injected using @PersistenceUnit annotation.
    3. The POJO has one getter method that queries the database and return the list of all the states.
  3. In the generated file "template-client.xhtml", change the "head" template to:

    Show States

    and "body" template to:

                    <h:dataTable var="state" value="#{stateList.states}" border="1">
                        <h:column><h:outputText value="#{state.abbrev}"/></h:column>
                        <h:column><h:outputText value="#{state.name}"/></h:column>
                    </h:dataTable>

  4. This uses the standard JSF "dataTable", "column", and "outputText" tags and uses the value expression to fetch the values from the managed bean.

If the application is already running from TOTD #93, then Deploy-on-Save would have automatically deployed the entire application. Otherwise right-click on the project and select Run (default shortcut "F6"). The results can be seen at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or "http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml" and looks like:



The updated directory structure looks like:



There were multiple files added by the JSF framework support in NetBeans. But as I said earlier, they will be cleaned up before the final release.

Also refer to other Java EE 6 blog entries.

Please leave suggestions on other TOTD that you'd like to see. A complete archive of all the tips is available here.

Technorati: totd glassfish v3 mysql javaee6 javaserverfaces jpa2 netbeans

Thursday Apr 02, 2009

TOTD # 77: Running Seam examples with GlassFish

Seam is a full-stack solution to assemble complex web applications using simple annotated classes, a rich set of UI components, and very little XML. It integrates Ajax and Business Process Modeling with several Java EE technologies such as Java Server Faces (JSF), Java Persistence API (JPA), and Enterprise Java Beans (EJB 3.0).

GlassFish is a Java EE compliant application server so it's natural to pick GlassFish as your deployment platform for Seam applications :)

This blog is going to show how Seam samples can be easily run on GlassFish.
  1. Download Seam 2.1.1 GA from here and unzip.
  2. Build "examples/jpa" sample as:

    ~/tools/jboss-seam-2.1.1.GA/examples/jpa >ant glassfish
    Buildfile: build.xml

    glassfish:

    initcopy:

    initpoms:
         [echo] Setting up dependencies
        [mkdir] Created dir: /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms
         [copy] Copying 1 file to /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms
    [artifact:install] [INFO] Installing /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms/root.pom to . . .

    . . .

    init.war:

    war:
         [copy] Copying 27 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war
         [copy] Copying 7 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war/WEB-INF/lib

    noejb.war:
         [copy] Copying 18 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war/WEB-INF/lib
         [copy] Copying 2 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war
         [copy] Copying 4 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war

    distributable.war:

    noejb.archive:
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/dist-glassfish/jboss-seam-jpa.war

    BUILD SUCCESSFUL
    Total time: 5 seconds
  3. Deploy the sample as:

    ~/tools/jboss-seam-2.1.1.GA/examples/jpa >~/tools/glassfish/v2.1/glassfish/bin/asadmin deploy dist-glassfish/jboss-seam-jpa.war
    Command deploy executed successfully.

    The app is now accessible at "http://localhost:8080/jboss-seam-jpa" and here are some of the captured screenshots:







    Simple and easy!
  4. Build "examples/hibernate" as:

    ~/tools/jboss-seam-2.1.1.GA/examples/hibernate >ant glassfish
    Buildfile: build.xml

    glassfish:

    initcopy:

    initpoms:
         [echo] Setting up dependencies
         [copy] Copying 1 file to /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms
    [artifact:install] [INFO] Installing /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms/root.pom to /Users/arungupta/.m2/repository/org/jboss/seam/root/2.1.1.GA/root-2.1.1.GA.pom

     . . .

    distributable.war:

    noejb.archive:
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/hibernate/dist-glassfish/jboss-seam-hibernate.war

    BUILD SUCCESSFUL
    Total time: 6 seconds

  5. Deploy the sample as:

    ~/tools/jboss-seam-2.1.1.GA/examples/hibernate >~/tools/glassfish/v2.1/glassfish/bin/asadmin deploy dist-glassfish/jboss-seam-hibernate.war
    Command deploy executed successfully.

    The app is now accessible at "http://localhost:8080/jboss-seam-hibernate" and has exactly similar snapshots as shown in "jboss-seam-jpa" sample. Simple and easy, yet again!
  6. Build "examples/jee5/booking" and deploy as:

    ~/tools/jboss-seam-2.1.1.GA/examples/jee5/booking >ant
    Buildfile: build.xml

    initcopy:

    initpoms:
         [echo] Setting up dependencies
         [copy] Copying 1 file to /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms
    [artifact:install] [INFO] Installing /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms/root.pom to /Users/arungupta/.m2/repository/org/jboss/seam/root/2.1.1.GA/root-2.1.1.GA.pom
         [copy] Copying 1 file to /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms

    . . .

    archive:
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jee5/booking/dist/jboss-seam-jee5-booking.jar
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jee5/booking/dist/jboss-seam-jee5-booking.war
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jee5/booking/dist/jboss-seam-jee5-booking.ear

    BUILD SUCCESSFUL
    Total time: 5 seconds
    ~/tools/jboss-seam-2.1.1.GA/examples/jee5/booking >~/tools/glassfish/v2.1/glassfish/bin/asadmin deploy dist/jboss-seam-jee5-booking.ear
    Command deploy executed successfully.

    The application is now accessible at "http://localhost:8080/seam-jee5-booking". Wow, that's simple and easy as well!
So we have deployed multiple Seam samples on GlassFish v2.1 - simple and easy!

Here are some more useful pointers realted to Seam and GlassFish:
  • Chapter 39 of the Seam Community Documentation even describes how to deploy an application created using seam-gen on GlassFish.
  • Dan Allen, the author of Manning's Seam in Action, presented a webinar at TheAquarium Online.
  • Several other Seam entries @ TA.
  • Deploying a seam-gen project to GlassFish (blog entry) - Here is a quote from the blog:

    GlassFish has a very sexy administrative console, but it also has a very sexy commandline tool known as asadmin. The asadmin tool gives you virtually unbounded control over the application server, including core tasks such as starting and stopping the application server, deploying and undeploying applications, and setting up database connection pools, amidst a plethora of other controls. You'll see that my modified seam-gen tool takes advantage of a handful of these commands.

    And another one ...

    GlassFish gives you efficiency through automation, which is undoubtedly the most effective way to become efficient. ... GlassFish volunteers itself to participate in a script and is the reason why I choose it as my preferred application server.
  • GlassFish support added to seam-gen: It is certainly exciting to know that there are targets like "gf-deploy-datasource", "gf-deploy-hibernate", and "gf-prepare" available to Seam developers out-of-the-box.
  • Sample Application using JSF, Seam, and Java Persistence APIs on GlassFish - detailed step-by-step blog explaining how to run Seam applications on GlassFish
The other samples in the bundle (that I tried) rely upon non-Java EE jars in the App Server's classpath. A slight build file tweaking can bundle those jars in the application itself and will allow to run them as well.

Are you deploying your Seam applications on GlassFish ?

Happy Seaming on GlassFish!

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all the tips is available here.

Technorati: totd seam glassfish javaee javaserverfaces ejb jpa

Thursday Dec 11, 2008

TOTD # 59: Alternative JSF implementations on GlassFish - MyFaces and Tomahawk


GlassFish comes bundled with an industry grade implementation of Java Server Faces codenamed Mojarra. It is the most complete, up-to-date and well-tested JSF implementation and used pretty extensively. GlassFish v2 and v3 Prelude ships with JSF 1.2.x-compliant implementation that is defined as part of Java EE 5. GlassFish v3 trunk contains JSF 2.0-compliant implementation that is getting defined as part of Java EE 6. The latest version of Mojarra can be installed from the Update Center.

But GlassFish does not restrict you to Mojarra and instead it embraces other JSF implementations easily. This blog uses MyFaces, an alternate JavaServer Faces implementation from Apache, to demonstrate that. If you are interested in a brief summary of what it takes to use these alternate implementations on GlassFish then scroll to the end of this entry.

MyFaces also provides several component libraries such as Tomahawk, Trinidad, and Tobago for building web applications. This blog shows how MyFaces Tomahawk samples can be deployed on GlassFish v2 and v3. The basic integration hooks between GlassFish and other JSF implementations remain the same and are independent of the component library.

Lets get started and understand all the glory!

Download MyFaces Tomahawk samples from here. The download consists of 4 WAR files and they are unzipeed in the current directory. So create a new directory and then unzip the bundle if you want to organize it slightly better. The getting Started instructions require you to copy "simple.war" where as the actual WAR filename is "myfaces-example-simple-1.1.8.war". Anyway, we are going to deploy this sample on GlassFish v2, v3 Prelude, and v3 trunk and what needs to be done to use the MyFaces implementation bundled within the WAR.
  1. Deploy using Mojarra on GlassFish v2
    1. Deploying "myfaces-example-simple-1.1.8.war" on GlassFish v2 using "asadmin deploy myfaces-example-simple-1.1.8.war" and it shows the following message:

      [#|2008-12-05T11:00:43.710-0800|INFO|sun-appserver9.1|javax.enterprise.system.tools.deployment|_ThreadID=22;_ThreadName=Thread-43;|
      deployed with moduleid = myfaces-example-simple-1.1.8|#]

      [#|2008-12-05T11:00:44.296-0800|INFO|sun-appserver9.1|javax.enterprise.resource.webcontainer.jsf.config|_ThreadID=21;
      _ThreadName=httpWorkerThread-4848-1;/myfaces-example-simple-1.1.8;|Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03) for context '/myfaces-example-simple-1.1.8'|#]

      The bold text indicates that Mojarra 1.2 bundled with GlassFish v2 is used as the JSF runtime, the exact version is shown in the bold text. The deployed web application is accessible at "http://localhost:8080/myfaces-example-simple-1.1.8/home.jsf" and looks like:



      The following error message is shown as you click through the samples:

      [#|2008-12-03T16:27:43.935-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=24;_ThreadName=httpSSLWorkerThread-8080-1;|
      2008-12-03 16:27:43,935 [httpSSLWorkerThread-8080-1] INFO  org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation
      |#]

      [#|2008-12-03T16:27:43.935-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=24;_ThreadName=httpSSLWorkerThread-8080-1;|
      2008-12-03 16:27:43,935 [httpSSLWorkerThread-8080-1] ERROR org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.

      This error message is generated by MyFaces and may be ignored. I think the message should be a WARNING instead of an ERROR.
  2. Deploy using MyFaces on GlassFish v2
    1. Create a directory "simple" and unjar "myfaces-example-simple-1.1.8.war" in there.
    2. Add "WEB-INF/sun-web.xml" and specify the contents as:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
      <sun-web-app>
      <class-loader delegate="false"/>
      <property name="useMyFaces" value="true"/>
      </sun-web-app>

      The key point to notice is the property name "useMyFaces". The name is slightly mis-leading because the switch essentially tells GlassFish runtime to use the bundled Java Server Faces runtime and is not restricted to MyFaces only. This is fixed in GlassFish v3 and is discussed later.
    3. Create a WAR file in "simple" directory as "jar cvf myfaces-simple-v2.war \*".
    4. Deploy the generated WAR on GlassFish v2 as "asadmin deploy myfaces-simple-v2.war". It shows the following message:

      . . .

      [#|2008-12-05T11:11:25.615-0800|INFO|sun-appserver9.1|javax.enterprise.system.tools.deployment|_ThreadID=24;_ThreadName=Thread-257;|
      deployed with moduleid = myfaces-simple-v2|#]

      [#|2008-12-05T11:11:26.266-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|
      2008-12-05 11:11:26,266 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading standard config org/apache/myfaces/resource/standard-faces-config.xml
      |#]

      [#|2008-12-05T11:11:26.290-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|
      2008-12-05 11:11:26,290 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config jar:file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/tomahawk-1.1.8.jar!/
      META-INF/faces-config.xml
      |#]

      [#|2008-12-05T11:11:26.309-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,308 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/examples-config.xml
      |#]

      [#|2008-12-05T11:11:26.337-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,337 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/testSuite-config.xml
      |#]

      [#|2008-12-05T11:11:26.349-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,349 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-api in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/myfaces-api-1.1.6.jar
      |#]

      [#|2008-12-05T11:11:26.350-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,350 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-impl in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/myfaces-impl-1.1.6.jar
      |#]

      [#|2008-12-05T11:11:26.350-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,350 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - MyFaces-package : tomahawk-sandbox not found.
      |#]

      [#|2008-12-05T11:11:26.350-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,350 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : tomahawk in version : 1.1.8 from path : file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/tomahawk-1.1.8.jar
      |#]

      . . .

      [#|2008-12-05T11:11:27.069-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,069 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the RI-JSF-Implementation.
      |#]

      [#|2008-12-05T11:11:27.069-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,069 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation
      |#]

      [#|2008-12-05T11:11:27.070-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,070 [httpWorkerThread-4848-1] ERROR org.apache.myfaces.shared_impl.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.
      |#]

      [#|2008-12-05T11:11:27.070-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,070 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.webapp.StartupServletContextListener - ServletContext '/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/' initialized.
      |#]

      The first thing to note is that the message "Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03)" is not shown. That indicates Mojarra is not used as the JSF runtime. Then you can see how MyFaces 1.1.6 API and Implementation are loaded, Tomahaw 1.1.8 is loaded and finally started using MyFaces JSF implementation.

      The main page from this deployed application at "http://localhost:8080/myfaces-simple-v2" is very similar as shown below:

  3. Deploy using Mojarra on GlassFish v3 Prelude - This is very similar experience as with GlassFish v2.
    1. Deploying "myfaces-example-simple-1.1.8.war" on GlassFish v3 shows the following message:

      Dec 5, 2008 11:27:17 AM com.sun.faces.config.ConfigureListener contextInitialized
      INFO: Initializing Mojarra (1.2_10-b01-FCS) for context '/myfaces-example-simple-1.1.8'
      Dec 5, 2008 11:27:18 AM com.sun.enterprise.web.WebApplication start
      INFO: Loading application myfaces-example-simple-1.1.8 at /myfaces-example-simple-1.1.8
      Dec 5, 2008 11:27:18 AM org.glassfish.deployment.admin.DeployCommand execute
      INFO: Deployment of myfaces-example-simple-1.1.8 done is 3470 ms

      The bold text clearly indicates that Mojarra 1.2 bundled, exact version shown in the bold text, with GlassFish v3 is used as the JSF runtime. The deployed web application is accessible at "http://localhost:8080/myfaces-example-simple-1.1.8/home.jsf". Viewing the sample in browser shows:

      Dec 5, 2008 11:54:54 AM  
      INFO: 2008-12-05 11:54:54,083 [httpWorkerThread-8080-0] INFO  org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Starting up Tomahawk on the RI-JSF-Implementation.

      Dec 5, 2008 11:54:54 AM  
      INFO: 2008-12-05 11:54:54,083 [httpWorkerThread-8080-0] INFO  org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation

      Dec 5, 2008 11:54:54 AM  
      INFO: 2008-12-05 11:54:54,083 [httpWorkerThread-8080-0] ERROR org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.

      and may be ignored. None of the messages that indicate classloading, as shown for GlassFish v2 above, are displayed. I suspect these are standard messages displayed by MyFaces without taking into consideration that an alternate JSF runtime can be used to run these samples.
  4. Deploy using MyFaces on GlassFish v3 Prelude - There is no way to override JSF implementation with GlassFish v3 Prelude. So even though deploying "myfaces-simple-v2.war" will work fine but viewing the web page at "http://localhost:8080/myfaces-simple-v2/" will show the following exception:



    Basically, a web application cannot use MyFaces implementation on GlassFish v3 Prelude. However Mojarra provides a fully-compliant and feature-rich JSF implementation and is already baked in GlassFish v3 Prelude.
  5. Deploy using Mojarra on GlassFish v3 Trunk
    1. Pick your GlassFish v3 Build Flavor, this blog uses the trunk.
    2. Deploy the original sample as "asadmin deploy myfaces-example-simple-1.1.8.war" and the following log messages are shown:

      Dec 5, 2008 12:35:17 PM com.sun.faces.config.ConfigureListener contextInitialized
      INFO: Initializing Mojarra 2.0.0 (SNAPSHOT b05) for context '/myfaces-example-simple-1.1.8'
      Dec 5, 2008 12:35:18 PM org.apache.catalina.core.ApplicationContext log
      SEVERE: WebModule[/myfaces-example-simple-1.1.8]PWC1275: Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener
      java.lang.NoClassDefFoundError: com/sun/facelets/tag/jsf/ComponentHandler
              at java.lang.ClassLoader.defineClass1(Native Method)
              at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
              at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
              at org.glassfish.web.loader.WebappClassLoader.findClass(WebappClassLoader.java:974)

      This happens because the application has dependencies on internal classes of Facelets 1.1.x. That makes the application non-compatible with Mojarra 2.x which comes bundled with Facelets 2.0.
    3. Lets instruct the application to disable the Facelets 2.0 baked in Mojarra by adding the following application wide context parameter in "web.xml":

      <context-param>
             <param-name>javax.faces.DISABLE_FACELET_JSF_VIEWHANDLER</param-name>
             <param-value>true</param-value>
       </context-param>

      Now the Facelets 1.1.x classes bundled with the application are used. With this change, the application gets deployed correctly and shows the following log message:

      Dec 5, 2008 2:50:21 PM com.sun.faces.config.ConfigureListener contextInitialized
      INFO: Initializing Mojarra 2.0.0 (SNAPSHOT b05) for context '/myfaces-simple-v3'
      Dec 5, 2008 2:50:21 PM com.sun.enterprise.web.WebApplication start
      INFO: Loading application myfaces-simple-v3 at /myfaces-simple-v3
      Dec 5, 2008 2:50:21 PM org.glassfish.deployment.admin.DeployCommand execute
      INFO: Deployment of myfaces-simple-v3 done is 1513 ms

      The important thing to note here is that Mojarra 2.0.0 implementation (as indicated by the bold text) is used as JSF runtime. This is the newest and the greatest runtime that implements JSF 2.0 specification and baked in GlassFish v3 trunk. The main page from this deployed application at "http://localhost:8080/myfaces-simple-v3/" looks like:

  6. Deploy using MyFaces on GlassFish v3 Trunk
    1. Download the latest GlassFish v3 Nightly.
    2. Lets deploy the WAR file previously created as "asadmin deploy myfaces-simple-v2.war". The main page of the application is accessible at "http://localhost:8080/myfaces-simple-v2".
    3. The "useMyFaces" property, as specified in "sun-web.xml", is expected to work for any bundled JSF implementation. The recommended way to deploy such a web application in GlassFish v3 is to use the property "useBundledJsf". The updated "sun-web.xml" is shown below:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
      <sun-web-app>
      <class-loader delegate="false"/>
      <property name="useBundledJsf" value="true"/>
      </sun-web-app>
    4. Create a WAR file in "simple" directory as "jar cvf myfaces-simple-v3-usebundled.war \*".
    5. Deploy the generated WAR on GlassFish v3 as "asadmin deploy myfaces-simple-v3-usebundled.war". It shows the following message:

      . . .

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,786 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config jar:file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/tomahawk-1.1.8.jar!/
      META-INF/faces-config.xml

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,806 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/examples-config.xml

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,828 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/testSuite-config.xml

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-api in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/myfaces-api-1.1.6.jar

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-impl in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/myfaces-impl-1.1.6.jar

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - MyFaces-package : tomahawk-sandbox not found.

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : tomahawk in version : 1.1.8 from path : file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/tomahawk-1.1.8.jar

      . . .

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,763 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the RI-JSF-Implementation.

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,764 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,764 [httpWorkerThread-4848-1] ERROR org.apache.myfaces.shared_impl.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,764 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.webapp.StartupServletContextListener - ServletContext '/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/' initialized.

      Dec 5, 2008 3:19:55 PM com.sun.enterprise.web.WebApplication start
      INFO: Loading application myfaces-simple-v3-usebundled at /myfaces-simple-v3-usebundled
      Dec 5, 2008 3:19:55 PM org.glassfish.deployment.admin.DeployCommand execute
      INFO: Deployment of myfaces-simple-v3-usebundled done is 1994 ms

      The first thing to note is that the message "Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03)" is not shown. That indicates Mojarra is not used as the JSF runtime. Then you can see how MyFaces 1.1.6 API and Implementation are loaded, Tomahawk 1.1.8 is loaded and finally started using MyFaces JSF implementation.

      The main page from this deployed application at "http://localhost:8080/myfaces-simple-v3-usebundled" is very similar as shown below:



Here is a brief summary of how MyFaces/Tomahawk sample is deployed using Mojarra and MyFaces on GlassFish:

JSF Implementations
Mojarra MyFaces
GlassFish v2 Default "useMyFaces" property in "sun-web.xml"
GlassFish v3 Prelude Default Not supported
GlassFish v3 Trunk Disable Facelets 2.0 in "web.xml" "useMyFaces" OR "useBundledJsf" property in "sun-web.xml"
Disable Facelets 2.0 in "web.xml" (only for Facelets 1.1.x dependencies)

The steps described above for MyFaces can be used with alternate JSF implementations as well. Which JSF implementation do you use ?

Just like Tomahawk components, Trinidad and Tobago libraries should work with Mojarra as well. Have you tried them ?

Technorati: glassfish javaserverfaces mojarra apache myfaces tomahawk

Wednesday Nov 19, 2008

TOTD #54: Java Server Faces with Eclipse IDE


Ed pointed me to this excellent tutorial that explains how JavaServer Faces applications can be easily created using Eclipse IDE. The article clearly shows all the steps to create a Java Server Faces application and demonstrates the following JSF concepts:
  • How to register managed beans to a JSF application ?
  • Different templates for creating JSF pages
  • Validators
  • Resource Bundles
  • Navigation rules in faces-config.xml (very intuitive and easy-to-use)
  • Dependency injection
  • Value and Method Binding
Few code/snapshot mismatches but knowing that it's only version 0.3, it's a damn good job!

Couple of differences from the article:

First, I deployed all the samples on GlassFish v3 Prelude which has Mojarra 1.2 baked in. The screencast #28 explains how to configure GlassFish with Eclipse IDE.

Secondly, instead of using WTP, I used Eclipse 3.4 for Java EE developers which has built-in support for JSF 1.1 and 1.2 applications. So there is no need to download/configure JSP/JSTL libraries. Instead the libraries are specified during project creation as shown below:



And then let the server side provide JSF implementation by selecting radio button as shown below:



That's it, now the Mojarra baked in GlassFish v3 Prelude is used for JSF runtime.

The faces-config editor is really cool, intuitive and easy-to-use. Here is a snapshot:



Here is a snapshot of the project explorer window (package names are different from the original article):



And now finally the outputs from 4 JSF applications:












All of this using Mojarra and GlassFish v3 Prelude :)

Let us know your feedback on Mojarra at GlassFish Webtier forum, file bugs in Issue Tracker, and find the latest information about Mojarra at javaserverfaces.dev.java.net.

Technorati: totd javaserverfaces eclipse glassfish v3 mojarra
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