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.
Is Linux the better choice for Java developers?
Last week I had a discussion with some colleges from work, if it would be better when we used Linux instead of Windows. I don’t want to start a flame war with my blog. I personally use Linux because when I was a student I couldn’t effort the licenses cost :-) and since then I pretty happy with my choice. But I must say that I don’t’ have a problem to work with Windows, but sometimes I think it would be easier for me to work with Linux. But thats my personal opinion. I really miss a package manager (apt-get, emerge, etc.) under Windows and the shell (bash, etc).
I started to think about this topic when they did a update of the antivirus software last week. Suddenly the build of our Java application took longer, because the antivirus software scanned during the build all jar’s, war’s, ear’s and class files. It took about a day and the problem was fixed from the IT support! Now the problem is solved but there are still some points which could be improved, like to exclude XML files from the scan.
A big company mostly have a Java development crew and they have to customize the workstations for them. For example when you are lucky you have local administration rights and you can install a JDK. So would it be better to give them Linux workstations (or a MacBook Air…;-) with a Windows Terminal Server client to access the MS applications?
A interesting post is from Cay Horstmann about why Java developers should switch to Linux.
http://weblogs.java.net/blog/cayhorstmann/archive/2006/06/why_java_develo.html
And naturally a blog from Eitan Suez about Mac and Java.
http://weblogs.java.net/blog/eitan/archive/2004/11/java_developmen_1.html
