On Wednesday, November 11, the Netherlands Java Users Group (NL-JUG) organized the JFall 2009 Java conference. At the conference I had the pleasure of doing a presentation with a live demo about what steps can be taken to migrate an existing JEE5 web application to JEE6. The application ran on GlassFish v2 and I migrated it to GlassFish v3 using NetBeans 6.8 Beta. This article describes my experiences with GlassFish v3 and NetBeans 6.8 Beta and it explains what steps I took to migrate from JEE5 to JEE6.
The demo application
The application I used for the presentation is a simple web application I wrote. It displays the contents of an astronomical database called the SAC (Saguaro Astronomy Club) database. The database contains over 10,000 so called Deep Sky Objects. These are objetcs in space outside our solar system that are not stars, e.g. gaseous nebulae, star clusters and galaxies.
From left to right columns are shown for the name and aleternate name of the object, it's position in the sky (R.A. = Right Ascension, dec = Declination) and its brightness (Magnitude). On the top of the table select boxes are shown that allows the user to filter the data. At the bottom of the page is a button to add a new object.
The application was built using NetBeans 6.7.1 on top of GlassFish v2. The pages are JSP pages with JSF tags in them. There is a JSF Managed Bean that communicates with a Local Session Bean. The Local Session Bean, finally, uses TopLink Essentials JPA to communicate with the database.
Both the Object Type (Star Cluster, Nebula, Galaxy etc.) and the Constellation of a Deep Sky Object are stored in separate tables and are connected to the Deep Sky Object by means of OneToMany associations. In order to deal correctly with these associations, I introduced two Converters. One Converter converts a Constellation to a String and back, the other does that for a DeepSkyType.
First steps to migrate to JEE6
During the presentation I showed what steps were needed to run the application on GlassFish v3. The short answer is: none! JEE6 is fully backward compatible with JEE5. Simply deploying the EAR on GlassFish v3 did the trick. However, since I wanted to use some new features of JEE6 in my application, I had to migrate parts of my application to JEE6.
First of all, TopLink Essentials no longer is used in GlassFish v3 as JPA layer. The reference implementation of JPA 2.0 is called EclipseLink. This essentially is an open source version of TopLink. The EclipseLink project is hosted under the Eclipse foundation and that is why TopLink was renamed to EclipseLink. Secondly, JSP no longer is the default view layer in JEE6. It has been replaced with Facelets. Facelets has been available for JEE5 for a long time now. Using the final build version of Facelets (version 1.1.14) would have worked on GlassFish v2. However, it does NOT work on GlassFish v3. The reason is that Facelets now is incorporated in JSF 2.0 while it was a separate technology with JSF 1.2. So, in order to migrate to Facelets, I had to migrate to JSF 2.0 as well.
The steps that were necessary to do so were
- create xhtml files for each jsp file, copy the contents over and make sure they are proper xhtml files
- modify faces-config: make sure the version used is 2.0 instead of 1.2 and also make sure all references to jsp files are replaced by xhtml files
- modify web.xml and make sure to configure it to use Facelets.
The last step means adding this bit to web.xml
<!-- Facelets pages will use the .xhtml extension --> <context-param> <param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name> <param-value>*.xhtml</param-value> </context-param>
Deploying the new EAR file showed the application to be working ok.
Introducing JEE6 stuff
In JEE5 an application with both a web part (in a WAR) and an EJB part (in a JAR) needed to be deployed in an EAR (WAR + JAR) file. One of the changes that comes with JEE6 is that EAR files no longer are needed. Now it suffices to have a WAR that contains both the web part and the EJB part. There are two ways to accomplish this. One way is to add all EJB classes in a separate JAR and place that in the lib dir within WEB-INF. Another way is to have all EJB classes in the same class structure as the web classes (Managed Beans, Converters etc.) and deploy all of it in a single WAR. I chose the latter way.
To do so, I created a new Web Application project in NetBeans 6.8 Beta and chose JEE6 as Java EE version.
Then I copied over all pages, sources, style sheets and configuration files to the new project. Undeploying the old project and deploying the new showed the new application to work totally fine.
The next step was to get rid of faces-config.xml. In JSF 2.0 it is no longer necessary to define all Managed Bean and Converters in faces-config. Instead, they can be annotated with the @ManagedBean and @FacesConverter annotations. Navigation is implicidly done depending of the outcome of an Action. I, for instance, the addAction returns a String "add", then JSF will try to find the view named "add" and navigate to it. In my case it means that JSF will navigate to add.xhtml to add a new Deep Sky Object to the database.
Without any content in faces-config, the file may be deleted. Doing so, however, resulted in a FileNotFoundException thrown by GlassFish over and over again. The bug that was reported for this already has been resolved.
Finally, I was able to show the functionality of the Bean Validation framework. This new JEE specification looks a lot like the Hibernate Validation framework. There are annotations like @NotNull, @Size, @Min, @Max, @DecimalMin, @DecimalMax and @Pattern to validate the data in, e.g., Entity classes before they are persisted in the database. One thing to be aware of is that @NotNull doesn't really work on String members. The reason is, that JSF will always submit an empty String in a form and "" != null! So beware to use the @Size annotation on String members.
Stuff prepared but not shown
Regrettably time went rather quickly during the presentation. I had prepared a fair bit about the new Metamodel and Criteria APIs in JPA 2.0 but I didn't have enough time to show more of it that just a quick code example. This was the only part of my preparations in which I encountered incomplete APIs. According to the Proposed Final Draft of the JPA 2.0 specifications there should be a @TypeSafeMetamodel annotation that indicates that a class is a Metamodel class for an Entity. The annotation, however, doesn't exist in the current version of EclipseLink 2. Apart form that I found the example code in the JPA 2.0 specification to slightly differ from the implementation in EclipseLink. With some puzzling, however, I was able to create a working example of the Criteria API. That is very good news indeed. A few months ago we hosted a session on JPA 2.0 at AMIS and then the Criteria API wasn't even available yet.
All in all I am very much impressed by the state of the reference implementationsof the forthcoming JEE specs. I hardly encountered any problems at all. If I encountered a problem, like one I had with my Converters suddenly stopping working when I switched to JSF 2.0, it turned out to be an error in my code. Both NetBeans 6.8 Beta and GlassFish v3 proved to be very stable and very pleasant to work with. If you have a chance to check out JEE6 stuff, I suggest you do it now!