EJB 3.1 and JSF 2.0 with GlassFish V3 Prelude
I got finally some time to write a simple CRUD web application with EJB 3.1 (JPA) and JSF 2.0 (facelets). Keep in mind that JSF 2.0 and EJB 3.1 are still in development and that some features are not yet implemented or can change. The goal was to make a simple GlassFish V3 Prelude project setup for a CRUD web application with EJB 3.1, JSF 2.0 (facelets) and maven.
First Install EJB 3.1 and JSF 2.0
I used for this this example the GalssFish V3 Prelude Platform-independent download file with Java 1.6 on a Ubuntu 8.04 Linux.
Unzip the GlassFish zip file and run the updatetool to install the EJB 3.1 and JSF 2.0 components.
$ ./updatetool
Remark: You can also install JSF 2.0 and EJB 3.1 over the GlassFish web administration console (http://localhost:4848). Be sure to restart GlassFish after you have updated JSF 2.0 and EJB 3.1.
After that you can run the pkg command to list the installed components.
$ ./pkg list
As you can see the EJB and JSF components were installed.
felix 1.2.2-0 installed ---- glassfish-amx 3.0-28.3 installed ---- glassfish-api 3.0-28.3 installed ---- glassfish-common 3.0-28.3 installed ---- glassfish-ejb 3.0-28.3 installed ---- glassfish-grizzly 1.8.6.2-0 installed ---- glassfish-gui 3.0-28.3 installed ---- glassfish-hk2 3.0-28.3 installed ---- glassfish-jca 3.0-28.3 installed ---- glassfish-jdbc 3.0-28.3 installed ---- glassfish-jdbc-gui 3.0-28.3 installed ---- glassfish-jdbc-management 3.0-28.3 installed ---- glassfish-jpa 3.0-28.3 installed ---- glassfish-jsf 2.0.0-5 installed ---- glassfish-jta 3.0-28.3 installed ---- glassfish-management 3.0-28.3 installed ---- glassfish-nucleus 3.0-28.3 installed ---- glassfish-registration 3.0-28.3 installed ---- glassfish-scripting 3.0-28.3 installed ---- glassfish-web 3.0-28.3 installed ---- glassfish-web-gui 3.0-28.3 installed ---- glassfish-web-management 3.0-28.3 installed ---- javadb 10.2.2.1-0 installed ---- pkg 1.0.7-15.1269 installed ---- pkg-java 1.0.7-15.1269 installed ---- python2.4-minimal 2.4.4.0-15.1269 installed ---- updatetool 2.0.0-15.1269 installed ---- wxpython2.8-minimal 2.8.8-15.1269 installed ----
Create a simple maven project setup
With the maven-archetype-webapp I created a simple webapp maven project.
mvn archetype:create -DgroupId=my.app.crud -DartifactId=CRUD-GVFv3 -DarchetypeArtifactId=maven-archetype-webapp
Now we have to customize our pom.xml file. We need some dependencies and the appropriate repositories. I used the following repositories:
<repositories>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>
<repository>
<id>glassfish-repository</id>
<name>Java.net Repository for Glassfish</name>
<url>http://download.java.net/maven/glassfish</url>
</repository>
</repositories>
To have the Java EE 6 JAR’s like EJB 3.1, JSF 2.0, etc in the build classpath I put the following dependencies in my pom.xml file.
<dependency> <groupId>org.glassfish</groupId> <artifactId>javax.javaee</artifactId> <version>3.0-Prelude-b28b</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-api</artifactId> <version>2.0.0-b05</version> <scope>provided</scope> </dependency>
I must say I’m not sure if these API’s are in sync with the current installed GlassFish. But an alternate way could be to use the maven system dependencies and point them to the the EJB, JSF, JPA, and common annotations JAR’s of the installed GlassFish.
I’m sure when the Java EE 6 API gets stable we will find it in the java.net maven repository, but for now we have to be patient. :-)
We will deploy our application as WAR and so we need to customize our maven project a little. I added src/main/resources as web resource to the maven war plugin, because we want to add some resources like META-INF/persistence.xml to the WAR file. The persistence.xml file is used to configure JPA and it must be placed inside of the META-INF directory of the WAR file.
pom.xml
<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>my.app.crud</groupId>
<artifactId>CRUD-GFv3</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>CRUD-GVFv3 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.javaee</artifactId>
<version>3.0-Prelude-b28b</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.0.0-b05</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<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.0</version>
<configuration>
<warName>${pom.artifactId}</warName>
<webResources>
<resource>
<!-- this is relative to the pom.xml directory -->
<directory>src/main/resources</directory>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>
<repository>
<id>glassfish-repository</id>
<name>Java.net Repository for Glassfish</name>
<url>http://download.java.net/maven/glassfish</url>
</repository>
</repositories>
</project>
Configure JPA
For this example I used the default datasource jdbc/__default in GlassFish to store the JPA entities. The jdbc/__default datasource uses the apache derby database that comes preconfigured with GlassFish.
As you can see the persistence.xml was adapted for EclipseLink, which is the new JPA implementation in GlassFIsh V3.
I used an example from the EclipseLink homepage and adapted it for the GlassFish container.
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="defaultPersistenceUnit"
transaction-type="JTA">
<jta-data-source>jdbc/__default</jta-data-source>
<properties>
<property name="eclipselink.jdbc.driver"
value="org.apache.derby.jdbc.ClientDriver" />
<property name="eclipselink.jdbc.url"
value="jdbc:derby://localhost:1527/CRUDGFv3;create=true" />
<property name="eclipselink.jdbc.user" value="app" />
<property name="eclipselink.jdbc.password" value="app" />
<property name="eclipselink.ddl-generation"
value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode"
value="database" />
<!-- Logging -->
<property name="eclipselink.logging.level" value="FINE" />
<property name="eclipselink.logging.timestamp" value="false" />
<property name="eclipselink.logging.session" value="false" />
<property name="eclipselink.logging.thread" value="false" />
</properties>
</persistence-unit>
</persistence>
Configure JSF
Hint: Be sure to use at least the 2.5 web.xml deployment descriptor. When you use a previous version of the deployment descriptor dependency injection like @EJB will not work.
In the web.xml we declare the mapping for the JSF servlet.
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>Sample CRUD EJB 3.1 / JSF 2.0 App</display-name> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> </web-app>
The faces-config was customized for JSF 2.0 and so we can use faclets which was include in JSF 2.0. Be sure that you use a JSF 2.0 faces-config.xml file when you want to use the new JSF 2.0 features.
I just added some old fashion navigation rules and to declare the managed bean we will use the new @ManagedBean annotation.
faces-config.xml
<?xml version="1.0"?> <faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" version="2.0"> <navigation-rule> <from-view-id>/listBooks.xhtml</from-view-id> <navigation-case> <from-outcome>editBook.xhtml</from-outcome> <to-view-id>/editBook.xhtml</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/editBook.xhtml</from-view-id> <navigation-case> <from-outcome>listBooks.xhtml</from-outcome> <to-view-id>/listBooks.xhtml</to-view-id> </navigation-case> </navigation-rule> </faces-config>
JSF 2.0 has some cool new annotations to declare managed beans an their scope. The following example shows a managed bean declared with the @ManagedBean annotation. The session scope for this managed bean is specified with the @SessionScoped annotation.
import javax.faces.model.ManagedBean;
import javax.faces.model.SessionScoped;
@ManagedBean(name = "BookBean")
@SessionScoped
public class BookManagedBean {
...
}
Create a simple CRUD Application with EJB 3.1 and JSF 2.0
I created the following Java artifacts.
- BookServiceBean.java (Session Bean)
- Book.java (JPA Entity)
- BookManagedBean.java (Managed Bean)
And the following JSF pages.
Prepare deployment
So now it’s time to startup GlassFish and the include derby database
$ ./asadmin start-domain $ ./asadmin start-database
We create our WAR file with the following maven command.
$ mvn package
The last step is to deploy our application.
$ ./asadmin deploy /home/mr/project/CRUD-GFv3/target/CRUD-GFv3.war
Remark: It seemed that when I deploy the WAR over the web administration console I had to restart GlassFish. After the restart the CRUD example worked correctly.
Finally the hard work is over…. :-) The application should now be deployed and you can try it out under the following address.
http://localhost:8080/CRUD-GFv3
Source Code CRUD-GFv3
You can download the full source code as ZIP file.
Remark I also tested my example with Windows XP and the GlassFish V3 Prelude Platform-independent download file. So nobody can say I only preferred Linux…. :-) But bear in mind that the example could not work because of some changes in the Java EE 6 API that occurred after the writing of this post.
Tags: java
This entry was posted on Wednesday, November 26th, 2008 at 3:13 pm and is filed under GlassFish, Java EE 6. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

November 26th, 2008 at 9:28 pm
Immo says:Well done – good write-up! I’ve learned quite a lot from this.
November 28th, 2008 at 6:07 am
Krishna says:This article is very useful for the beginners. Keep posting nice articles.
December 5th, 2008 at 7:49 pm
Tanzan Nangi says:Seems like an awful lot of hard work just to get started.
December 6th, 2008 at 4:33 pm
Marcel says:It’s negatively incredible how burdensome it’s become in Java EE to get something so simple up’n running. Mind you, I’m Java developer myself. So, I’m saddened by this. I’ll get same with Rails or Grails in a few lines of code.
December 8th, 2008 at 9:02 am
Steve says:Lets be fair – most of the article above is putting together a build process which is not really part of the application. Nice work mate.
December 10th, 2008 at 7:49 pm
Rogério Valente says:Where do I find ManagedBean and SessionScoped classes?
December 10th, 2008 at 8:14 pm
Matthias Rüedlinger says:Hi Rogério
As far as I can remember you need at least JSF 2.0.0-b05. You should find the ManagedBean and SessionScoped annotation in the package javax.faces.model. There was recently a new JSF release in GlassFish V3 and I didn’t check if these annotation are still valid in the new release.
When you don’t want to work with the maven pom.xml file then try out the JSF 2.0 nightly build (https://javaserverfaces.dev.java.net/servlets/ProjectDocumentList?folderID=9814&expandFolder=9814&folderID=9814 ) and cross check if some of annotation have changed with JSR 314 specification (http://jcp.org/en/jsr/detail?id=314).
So the best way to see the actual state of JSF is to download the latest nightly release and look at the include javadoc (API).
Matt
December 10th, 2008 at 8:22 pm
Rogério Valente says:Sorry,
I founded the classes.
December 10th, 2008 at 9:06 pm
Rogério Valente says:Thanks Matt.
I got a “build failure” result after the “mvn package” command and the message is “\CRUD-GFv3\src\main\java\my\app\crud\presentation\BookManagedBean.java:[23,18] type javax.faces.model.DataModel does not take parameters”.
Any hints about it?
December 10th, 2008 at 11:32 pm
Matthias Rüedlinger says:Hi rogerio
I’m not sure but it seemed that the following declaration causes the error.
private DataModel
Do you have a least Java 5? Because this statement uses generics? I googled and I found some similar build failures which occurred when not at least a java 5 compiler was used.
Matt
December 14th, 2008 at 11:02 am
Ivan Mikushin says:Hi Matt,
I’ve encountered the same compile error as Rogerio, and I have source and target compiler settings set to “1.6″:
org.apache.maven.plugins
maven-compiler-plugin
1.6
1.6
The cause is: javax.javaee dependency includes jsf-api-1.2 which doesn’t have parameterized classes. To make the project compile we need to exclude it from the dependency tree (so jsf-api-2.0.0-b05 takes effect):
org.glassfish
javax.javaee
3.0-Prelude
provided
javax.faces
jsf-api
December 14th, 2008 at 2:46 pm
Jonas says:Finally found time to play with this example.
Works great also under OS X.
I only had a small problem that the updatetool did not list the JSF 2.0 update.
The admin-console however did list the update.
Could be this bug: https://updatecenter2.dev.java.net/issues/show_bug.cgi?id=774
Thanks.
December 14th, 2008 at 3:00 pm
Jonas says:I think the resource section in the pom.xml is not necessary for this app?
Since we have the resource section for the war plugin…
December 27th, 2008 at 1:29 am
Jonas says:I tried to implement the same application with Grails on GlassFish V3 Prelude.
I wrote a post about that here:
http://blog.jonasbandi.net/2008/12/simplistic-crud-application-with-grails.html
February 1st, 2009 at 5:42 pm
Cay Horstmann says:I tried this today and got the following error message that is only too familiar from the bad old days:
message: Exception while deploying the app : java.lang.RuntimeExceptio
n: Invalid ejb jar [CRUD-GFv3]: it contains zero ejb.
Note:
1. A va
lid ejb jar requires at least one session, entity (1.x/2.x style), or
message driven bean.
2. EJB3+ entity beans (@Entity) are POJOs and
please package them as library jar.
3. If the jar file contains vali
d EJBs which are annotated with EJB component level annotations (@Sta
teless, @Stateful, @MessageDriven), please check server.log to see wh
ether the annotations were processed properly.
exit-code: FAILURE
Any clue what might have changed?
Thanks,
Cay
February 4th, 2009 at 7:19 pm
Matthias Rüedlinger says:Thanks Cay for the hint.
Cay said:
> In your example, you (or maybe Maven) put persistence.xml in
> two places,
> and it took me a while to find out where it needs to go. I put an
> example with an Ant script at
> http://weblogs.java.net/blog/cayhorstmann/archive/2009/02/towards_java_ee.html
November 27th, 2009 at 2:16 pm
Steve says:Thanks for the great tutorial. Info on JSF2 is thin on the ground and I found your blog very enlightening.
With regard to storing the book being edited in a session scoped bean:- it seems the faces session is equivalent to the HttpSession and therefore the user can only edit one book at a time?
Even worse, if the use opens two records for edit at the same time they can overwrite the wrong record!
I’ve noticed that if
- I open the list in two browsers tabs
- select book 1 in the first
- select book 2 in the second
- edit and save book 1 in the first
- then book 2 is actually updated with the data entered for book 1.
(complicated but, unfortunately, within the realms of possibility for the average user)
I’m new to JFS so I’m wondering if I’m missing something? Is there a way around storing the entity bean in the session?
I’ve been racking my brain for a way to start a transaction (txn) at the edit action, then pick up the same txn object at the save, delete actions? #{BookBean.txnBook.title} kind of thing?
Can you offer any guidance to a Noob?
Thanks,
Steve.
November 27th, 2009 at 8:13 pm
Matthias Rüedlinger says:Hello Steve
Thanks for your comment.
Concurrency is a common problem for web applications. My example is a bit outdated and was attempt to show how ejb 3.1 and jsf interact together in a pre-release of galssfish.
So the keyword to your problem could be locking / optimistic locking.
Perhaps the following article can help you.
Locking and Concurrency in Java Persistence 2.0
http://blogs.sun.com/enterprisetechtips/entry/locking_and_concurrency_in_java
or when your work with Hibernate
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html
Regards
Matt
December 4th, 2009 at 1:26 am
malen christian says:Hi,
Thanks for your tuto.
With Java 1.6 and JSF 2.0 I had to modify the import statement of BookManagedBean.java :
“import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;” (from model to bean ) with (jsf-api version 2.0.2-b10 in pom.xml)
to make it compiling.
There is a warning that I do not understand :
The expression ${pom.artifactId} is deprecated. Please use ${project.artifactId} instead.
Any idea ?
thanks very much since your tuto had been very helpfull !
regards
cm