Saturday, December 6, 2008

Using JBoss Seam Hot Deployment with a Maven Build

[UPDATE: The new plugin version is documented here]

As you might have read in previous posts, one of our favorite web application stacks consists of JBoss Seam. While combining this with our favorite tooling suite consisting of Eclipse and Maven, we had to realize that Seam has a much longer tradition with Ant, and Maven support is only slowly moving in. Today I want to share some ideas on how to tackle the combination issues.


While JBoss Tools provides a nice code hot deployment feature when working with Seam on JBoss, things can get a little hairy when using a Maven build with the project. Seam uses a special classloader and relies on monitoring the WEB-INF/dev folder for changed classes - where Maven is completely unaware of this and uses the standard WEB-INF/classes folder to deploy all classes in the project. More than once I've seen the situation where JBoss Tools and Maven got in each others way, ending with JBoss rejecting to restart the application due to "duplicate components". The reason was that Eclipse hot deployed classes to WEB-INF/dev where Seam expects them, but Maven being completely unaware of it packaging all classes in the common WEB-INF/classes folder.

In order to avoid trouble and also to allow using hot deployment from a command line build, I experimented with several approaches to achieve hot deployment with Maven. The main challenges here are:
  • Distinguishing compiler output: The Maven compiler plugin by default compiles everything in the same output folder. We need to be able to distinguish between hot and regular deployable code.
  • Publish updated resources to JBoss, including domain model classes, seam components as well as XHTML pages.
  • Make sure Seam unit tests still compile.
The solution I came up with was to write a new Maven plugin which extends the Maven compiler plugin with a new hotdeploy:compile goal and the following functionalities (source code as well as a simple Maven 2 repository is available in our Google Code account):
  • Hook into the compile phase and compile the source code to a dedicated directory. The source code location is configurable as well as the output directory.
  • Remove outdated hot deployable class files from the JBoss deployment. This is necessary for the Seam classloader to pick up the changes, only updating the file is not enough.
The plugin configuration is straight forward as it's based on the regular compiler plugin and is shown in the XML snippet below. Note that it is recommended to create a profile for this build setup as both your continuous build as well as your operations team might not care too much about using hot deployment.
<plugin>
<groupId>com.ctp.seam.maven</groupId>
<artifactId>maven-hotdeploy-plugin</artifactId>
<version>0.1.0</version>
<configuration>
<source>${java.source.version}</source>
<target>${java.source.version}</target>
<hotdeployOutputDirectory>${directory.hotdeployables}</hotdeployOutputDirectory>
<includes>
<include>**/session/**</include>
</includes>
<deployDirectory>
${directory.deploy.jboss}/${build.finalName}.${project.packaging}
</deployDirectory>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>

The main additions to a regular compiler plugin setup are:
  • This variant uses the common /src/main/java source folder and uses in- and excludes to distinguish the hot deployable sources. Alternatively you can set the sourceDirectory configuration value pointing to a dedicated source folder (similar as JBoss Tools does the setup for you). Don't forget that this requires then the Build Helper Maven plugin to add source folders to your regular build.
  • The deployDirectory is a reference to your exploded application directory inside the JBoss deploy folder. This is needed in order to remove outdated hot deployable classes.
  • You can specify the hotdeployOutputDirectory directory where the code should be compiled to. Note that this defaults to the value shown in the example - feel free to skip this part. The plugin will compile into this folder after appending a WEB-INF/dev to the path.
The rest of the setup we can do by simply reconfiguring existing plugins. Note the Google Code Wiki contains a complete sample POM ready for you to start your own Seam webapp. The details on the configuration are:
  • Reconfiguring the WAR plugin so the webappDirectory points inside our JBoss deploy folder. Maven uses this folder to assemble the WAR file, which perfectly corresponds to an exploded deployment. Additionally we define our hot deployment compilation folder as a webResource, which will copy our compilation exactly to the WEB-INF/dev folder in the exploded deployment.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${directory.hotdeployables}</directory>
<filtering>false</filtering>
</resource>
</webResources>
<webappDirectory>
${directory.deploy.jboss}/${build.finalName}.${project.packaging}
</webappDirectory>
</configuration>
</plugin>

  • Similarly, we have to add our output folder to the test classpath. This is simplest done by adding it as a resource folder, which will copy the classes to the target/test-classes directory before the test classes are compiled:
<testResources>
<testResource>
<directory>${directory.hotdeployables}/WEB-INF/dev</directory>
<filtering>false</filtering>
</testResource>
...
</testResources>

If you want to run a similar luxury setup as you get from JBoss Tools, you can add a Maven builder to your project. Simply go to the Eclipse Project properties and click "New" on the "Builders" properties. The new Maven build should look like the following:



Make sure that the following conditions apply to your Eclipse setup:
  • The JRE you have configured is actually a JDK - otherwise the builder will fail. Once you see that the builder does not fail, you can also switch off the console allocation in the "Common" tab.

  • Also take care that you always build with your specific hot deploy profile - otherwise make sure to clean before using the build again.

  • Assert that Eclipse uses a dedicated output folder and not the Maven target/classes.

Unfortunately when activating the builder Eclipse might prompt you when editing files and (depending on the speed of your machine) hang for a second or two after saving a file. Still, this is much better than waiting a minute for your JBoss server to restart.

Happy coding!

Friday, November 28, 2008

Portal Update November 2008

Another month has passed, year end is close so let's see what happened this month in the portal space:
  • SUN:
    - WebSynergy Milestone 3 Release! This is the last milestone release before the upcoming commercial release. Enhancements are mainly in documentation, integration between Liferay and WebSynergy.

  • JBoss:
    - JSR-286 Portal: Release 2.7 has been released on Oct 30th, right after I posted last month's summary ;-) This release supports all features specified by the Portlet 2.0, namely Public Parameters, Portlet Resource Serving, Portlet Filters, Portlet Coordination and provides some additional features not actually specified by JSR-286.

  • eXo:
    - eXo Portal 2.5 beta released: Fully JSR-286 compliant, supports Google Gadgets and comes with an integrate Gadget Repository
    - At DevFest in Bangkok, eXo announced a new product called eXo Social. It is consisting of two modules, eXo People and eXo Spaces, both running on top of eXo Portal 2.5. Both modules feature API based on OpenSocial and will bring social networking closer to the enterprise!
    The release of eXo Social 1.0 is targeted for January 2009.

  • Oracle (BEA):
    In some Oracle Open World 2008 slide decks I picked up these interesting statements:

    WebLogic Portal (WLP):
    - The whole WSRP framework of the WebLogic Portal will be integrated into WebCenter
    - WebLogic Portal's VCR (Virtual Content Repository) will also be integrated into WebCenter
    - Supported Content Management APIs in next year's releases of Oracle's portal products will be focused on JSR-170, REST and the recently announced new standard from OASIS called CMIS (announced Sept 10th 2008, involved companies are SUN, Microsoft, IBM, Oracle, Alfresco)
    - Next release (11g) has codename "Sunshine"

    AquaLogic User Interaction (ALUI):
    - Fully part of WebCenter Suite and WebCenter Services, means:
    - ALUI Blogs/Wikis and Tagging have been integrated into WebCenter Services
    - ALUI Collaboration and Interaction Mgmt have been integrated into WebCenter Suite
    - Next release (11g) has codename "Neo"


  • Other portal and Java related quick news:
    - Dec-10: Devoxx is already sold out! ;-) (fka JavaPolis, Javoxx)
    - Dec-02: SUN announced that JavaFX Desktop should be released!
    - Nov-27: JPA 2.0 released (public review)
    - Nov-19: NetBeans 6.5 is out
    - Nov-11: SpringSource acquires G2One (Groove and Grails specialists company)
    - Nov-08: Seam 2.1 supports GlassFish v2
    - Nov-06: GlassFish v3 Prelude released! Together with the OpenPortal Portlet 2.0 Update 1 and OSGi, RESTful Web Services, support for Rails and Grails, and technology previews (JSF 2.0, JAX-RS 1.0, EJB 3.1)
    - Nov-05: JSR-299 WebBeans released (public draft)
    - Nov-03: Metro 1.4 released ( = WSIT 1.4 + JAX-WS RI 2.1.5 + JAXB RI 2.1.7)
    - Oct-31: GlassFish includes EclipseLink as its default JPA implementation

  • IBM: no portal news

  • Eclipse: no portal news

  • NetBeans: see quick news above

  • IntelliJIDEA: no portal news

Wednesday, October 29, 2008

Portal Update October 2008

This month's portal summary got a little slimmer than the others:
  • SUN: Groovy Support: WebSynergy and the associated Portal Pack 3.0 continue to add features as part of its partnership with Liferay. Besides Ruby and PHP, you can now run Groovy apps as JSR-286 portlets deployed to WebSynergy as described by Frerk Meyer.

  • Oracle (BEA): no news.

  • IBM: Finally, WebSphere Application Server 7 is out. This means that IBM has joined the Java EE 5 vendor parade. With this release, the server also supports JSR-286 portlets as described in a very detailed release post.

  • eXo: The next release of eXo Portal (v2.5) will support right-to-left (RTL) languages (see picture) like Arab or Hebrew. A wiki dedicated to this RTL framework provides more details.

  • JBoss:
    > JSR-168 Portal:
    Release of JBoss Portal 2.6.7, a maintenance release of JBoss Portal 2.6: Main improvements have been done in scalability. JBoss claims that you can tune your portal application on a 1-node environment as the new version scales linearly.

    > JSR-286 Portal: Release 2.7 is in the process to go GA.

  • Eclipse: The first milestone of Eclipse Portal Pack 2.0 has been released. The portal pack consists of three plugins: JSR-286/168 Portlet Wizard, WebSynergy Plugin and the OpenPortal Plugin.

  • NetBeans and IntelliJIDEA: no news regarding portal support.

Friday, October 24, 2008

Giving EJB 3.1 a Test Drive

Although not yet final, project GlassFish features already an alpha implementation of EJB 3.1. TheServerSide posted a nice series of articles on what you can expect to come - but honestly, wouldn't it be much more fun to actually get some hands dirty? Here's a quick description on how you can give it a spin. We will demonstrate the following new features:
  • Singleton Beans
  • Simplified EJB packaging
  • Simplified EJB without Interfaces
  • Unified JNDI naming
Start with downloading the latest release of GlassFish v3. The Windows installer guides you through the installation. Use the default settings except for the authentification - choose a username and a password (this used to default to "admin/adminadmin"). At the end you will be prompted by the Updatetool - start it and install the Add-Ons shown in the image below:


Beside the EJB Container we'll also install the new JAX-RS REST API to access the EJB. The JAX-RS JSR has just recently gone final, and is definitely also worth a look. Once the installation is done, we'll switch to the IDE to code our beans. I'm using Eclipse with the Maven 2 plugin to get started quickly.

Choose New Maven Project and select the maven-archetype-webapp archetype as shown in the screenshot below. We're naming our project "ejbtestdrive" - note the name as it will be used a couple of times in the further process. Finish the create wizard and add the src/main/java folder as a source folder in Eclipse after creating it.


To resolve our dependencies, lets first configure the Maven repositories to download the EJB 3.1 as well as the JAX-RS API. Add the following lines to your pom.xml:
<repositories>
<repository>
<id>glassfish</id>
<name>Glassfish Repository</name>
<url>http://download.java.net/maven/glassfish</url>
</repository>
<repository>
<id>java.net</id>
<name>java.net Repository</name>
<url>http://download.java.net/maven/2</url>
</repository>
</repositories>

Which allows us to download following dependencies:
<dependencies>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb-api-3.1-alpha</artifactId>
<version>10.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

Almost done with the Maven setup. We'll just add the GlassFish Maven plugin to our build and set the compiler to deal with Java 6 (Java 5 should be fine too):
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.glassfish.maven.plugin</groupId>
<artifactId>maven-glassfish-plugin</artifactId>
<version>2.1</version>
<configuration>
<glassfishDirectory>${glassfish.home}</glassfishDirectory>
<domain>
<name>domain1</name>
<adminPort>4848</adminPort>
</domain>
<user>${domain.username}</user>
<adminPassword>${domain.password}</adminPassword>
<components>
<component>
<name>${project.artifactId}</name>
<artifact>${project.build.directory}/${project.build.finalName}.${project.packaging}</artifact>
</component>
</components>
<autoCreate>true</autoCreate>
<debug>true</debug>
<echo>true</echo>
</configuration>
</plugin>
</plugins>
</build>

The referenced properties should be defined in a Maven profile, but for simplicity we'll just add them now to our POM (just replace the values with your installation location and your username/password):
<properties>
<glassfish.home>E:\work\servers\glassfish\glassfishv3-prelude\glassfish</glassfish.home>
<domain.username>admin</domain.username>
<domain.password>adminadmin</domain.password>
</properties>

You're now ready to run the WAR file on GlassFish. Just run
mvn package glassfish:deploy

to start GlassFish and get your WAR file deployed (Note: If the Maven plugin complains about asadmin not be a Win32 application, just remove the UNIX script so the .bat will be taken).

Finally, time to write some code! Go back to Eclipse and create a package. Our EJB is going to be a (surprise surprise) HelloWorld bean. Create a new class which looks like the following:
package com.ctp.ejb;

import java.util.LinkedHashSet;
import java.util.Set;

import javax.ejb.Singleton;

/**
* The friendly first EJB 3.1 bean.
* @author [you!]
*/
@Singleton
public class HelloWorldBean {

private Set<String> names = new LinkedHashSet<String>();

public String hello(String name) {
names.add(name);
return "Hello " + names;
}
}
In case Eclipse complains about the compiler compliance, just set the Java project facet in the project's properties to something > 1.4. You've now created one of the new Singleton EJBs. The bean is going to remember everybody who said "hello" and give back a friendly greeting. Note that there is no local or remote interface at all! Also using a global state in a bean is something nasty to achieve before EJB 3.1. Run
mvn package glassfish:redeploy

to deploy your bean - noteably in just a simple WAR file! Did you notice how fast this deploys?

Now it's time to access our bean over JAX-RS. Create another class which looks like this:
package com.ctp.ejb;

import javax.naming.InitialContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

/**
* A RESTful bean being hopefully quite busy!
* @author [you!]
*/
@Path("/hello/{username}")
public class HelloWorld {

@GET
@Produces("text/plain")
public String hello(@PathParam("username") String name) throws Exception {
HelloWorldBean hello = (HelloWorldBean)
new InitialContext().lookup("java:global/ejbtestdrive/HelloWorldBean");
return hello.hello(name);
}
}

Simple enough, right? This is taking requests under /hello/... with a username, looking up the bean in JNDI and call it's hello method. Did you notice the format of the JNDI lookup? Yes, this is finally standardized, making your applications much more portable! In case you named your application differently, make sure the names match between global/ and /HelloWorldBean.
Further details on the JAX-RS functionalities can be found here.

As a last step, we need to add the Jersey servlet to our web.xml. Modify it to match this snippet:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
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>embeddable</display-name>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.ctp</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Check that your package name matches in the Servlets init param. Now package and redeploy - and we're ready to go! Just go to http://localhost:8080/ejbtestdrive/hello/[your name] to see you greeted by your new EJB! Experiment with different names and browser sessions and see the global state preserved.

Hope you enjoyed this little test drive. Let us know on how you're using EJB 3.1 and what your experience is with it!

Sunday, October 19, 2008

Java People Spotlight: Piyush Shah

"People Spotlight" is going to bring some light into the undercover hacker rooms at CTP where Piyush is getting his hands dirty on new frameworks and technologies. The picture tells both: his strong developer skills as well as his social engagements at CTP being official "CTP Staff" of the Social Committee...Enjoy!

Java Community Role:
Developer [aka 0800-DEBUG: "Who you gonna call?" - "Bug-Shah Buster!!!!"]
My Master Kung-Fu Skills
:
Apache Tomcat 6, WebLogic 10, Javascript
I'd be excited to get my hands dirty on:
Spring and JBoss Seam

Q&A

Q: Hi Piyush, how would your message look like if you would have to tell it via Twitter what you are currently doing?
A: Trying to break and rebuild Interwoven Teamsite to incorporate Xopus.

Q:
What was the greates piece of code you have ever written so far?
A: request.getRequestDispatcher(URL).forward(request, response);

Q: What is the best quote you have ever heard from one of your peers?
A: "Developing an application is like making a movie"

Q: What is the best quote you have heard from our managers?
A: "XYZ technology, you can do it. It’s a piece of cake."

Q: What is the most cutting-edge technology or framework you actually used on projects?
A: Porting my custom code using SSH client on Solaris server and making sure it is Java1.4 compatible.

Q: What is your favorite podcast?
A: TSS (TheServerSide.com)

Q: Which Java book can you recommend?
A: SCJP6 - by Katherine Sierra

Tuesday, October 7, 2008

Java People Spotlight: Douglas Rodrigues

Our "People Spotlight" series continues with an official JUG Brazil member... "Braziiiiiiiiiiiiiiiiiiiiiiiil !!! ;-) ". Besides contributing his excellence to CTP's Java Community, Douglas makes sure that Brazil stays the number 2 in the list of the countries with most hits to this blog! ;-) ... and here are Douglas answers:

Java Community Role:
Developer [aka Java Code Spitter]
My Master Kung-Fu Skills
:
Write code that (almost) anyone can read and understand in the future.
I'd be excited to get my hands dirty on:
JBoss DNA and IntelliJ IDEA 8.

Q&A

Q: Hi Douglas, how would your message look like if you would have to tell it via Twitter what you are currently doing?
A: while (!weekend) { iTunes.open(); while (!night) { iTunes.play(); doCode(); iTunes.pause(); getCoffee(); } iTunes = null; } // One-liners rocks! \o/
Q': and where is the exception handling??!!! ;-)

Q: What was the greates piece of code you have ever written so far?
A: An image to HTML converter. It takes a 30kB image and produces a 5MB HTML file.

Q: What is the best quote you have ever heard about programming?
A: "The nice thing about standards is that there are so many of them to choose from", by Andrew S. Tanenbaum.

Q: What is the best quote you have heard from our managers?
A: Well, I hear "we're all in sales" at least once every month.

Q: What is the most cutting-edge technology or framework you actually used on projects?
A: Java Content Repository API (JCR).

Q: What is your favorite podcast?
A: I'm not a big fan of technology related podcasts, but I tried Java Posse and it's kinda funny.

Q: Which Java book can you recommend and for what reason?
A: Head First Design Patterns

Tuesday, September 30, 2008

Portal Update September 2008

Despite autumn degrees start dropping, portal updates don't get freezed:
  • SUN presents Mango*: Traditionally when we talk about the FOSS stack (free open source software), the first thing that still comes to mind is the LAMP/SAMP stack (Linux/Solaris, Apache, MySQL, PHP/perl/pyhton).
    While LAMP/SAMP has been very successful for lots of Internet based businesses (e.g. Facebook), it may not be enough for enterprises looking for advanced middleware features found in commercial products (like JavaEE5 features in general, Portals, SSO, etc.).
    Along with the evolution of Java based open source products, SUN positions certain bundles to build the official successor of FOSS:
    MANGO* (MySQL And Netbeans, Glassfish and an Open*-Glassfish product) can be seen as the next generation FOSS stack or FOSS 2.0 which brings reliable, scalable and open software to the enterprise. So with the OpenPortal project, there is a strong OSS portal stack ready as a Mango... nice!
  • SUN: WebSynergy Community Build 5 has been released at the end of this month! Updates are: WSRP 2.0 improvements, jBPM integration into SAW and first functionalities of SWA (Secure Web Access, originally packaged with OpenPortal).
  • SUN: Netbeans 6.5: Portal Pack 3.0 M1 has been released. It supports WebSynergy Stable Build 2, and has provides tooling for the following:
    - Non-Java portlets: Groovy, Ruby and PHP
    - SAW-Plugin included (Simple API for Workflow)
    - The plugin for the JCR based Mirage product is also included

  • eXo:
    - People News: Sep 8th: former JBoss portal project lead Julien Viet starts as new eXo Portal Product Manager with focus on portlet container and JCR.
    - They announced a new release for september including GWT application support in the eXo Portal. I have not seen such a release this month, so if I missed it, let me know. Otherwise I'll post it next month.

  • JBoss:
    - JBoss released JBoss Portal 2.7.0 CR1
    - JSR-286 Portlet Coordination: a very good post about how JBoss Portal has implemented this new Portlet 2.0 feature.

  • Oracle (BEA)
    - WebLogic Portal 10g3: On Sep 16th, Oracle has released Oracle WebLogic Portal 10g3 for download. It is pretty much like WLP 10.2 with the major difference that it runs on WebLogic Server 10.3. The codename for this release is Sunrise.
    - WebCenter Interaction (formerly known as BEA ALUI): No news during this month.
    - Oracle seeds the cloud: At Oracle OpenWorld, Oracle announced that it will certify/support deployments of Oracle Database (all editions), Oracle Enterprise Linux, Oracle Enterprise Manager and Oracle Fusion Middleware (and therefore WLP and WebCenter Suite) to Amazon Web Services' (AWS) Elastic Compute Cloud (EC2). In fact you may transfer your existing licenses to AWS if you like. Oracle is also providing free Amazon Machine Images (AMIs) in that environment, so you can get up and running on a full Oracle-on-EC2 environment in minutes.
    - Oracle Beehive: At OpenWorld 2008, Oracle announced Oracle Beehive (for the developers: this is NOT Apache Beehive): "Oracle Beehive is the solution to cure the present communication fragmentation", said Oracle President Charles Phillips and continued: "The goal is to take a company's setup, in which various communication and collaboration software applications from a number of vendors are running on an army of servers, and integrate the offerings into one Beehive system."

    Architecturally, it is an open, secure, scalable and standards based Collaboration Platform providing all collaboration features through web services (using WSDL, SOAP, WS-Security based on SAML). The core of the platform is based on an event-driven architectural style which allows easy logic implementations for certain events (like "customer got an email"). Content-wise the platform features a JSR-170 compliant interface for document accesses as well as interfaces for protocols like IMAP and SMTP (mail), WebDAV (documents), CalDAV (calendar events), XMPP (instant messaging).

    Beehive has been quoted already as "Oracle's answer to Microsoft's Sharepoint, but with real enterprise readiness".
    However the uphill battle in the collaboration market will look like, I wonder how Oracle will position it with the feature-overlapping WebCenter Suite (which includes collaboration components of BEA ALUI already). It probably addresses a different business need (e.g. build collaboration platform from scratch or from existing).

  • IBM: no updates for September:
    - still WebSphere Portal Version 6.1 with a couple of extension modules, called portal accelerators
    - WebSphere Portals can be tried out without installation at IBM's Greenhouse

  • Vendor agnostic:
    - CTP: Our collegues from the Advisory Solutions have posted a nice overview on enterprise portals in the future.
    - As indicated in last month's post, InfoQ has now posted all three articles about writing portlets using JSF, Ajax and Seam deployed to JBoss Portal: Part 1 , Part 2 and Part 3.

Friday, September 26, 2008

Adding JCR support to your existing web application

In addition to the two recent technology posts (1, 2) that contained a product and technology overview about JCR, this post is guiding you through the practical steps in order to add JCR support to your web applications.

A new alternative to manage your application data is to store it in a content repository. The approach brings some advantages if compared to the most widespread persistence mechanism in use currently, the relational databases. The main advantage is the ability to have unstructured data. You can store your data first, and then define how it’s going to be organized and how the pieces of persistent information relate to each other. Besides the fact that not enforcing data integrity constraints, when they are not necessary, certainly helps in your application performance. This feature is especially useful when it’s necessary to enhance the data model. Relational databases are known for not having a very flexible structure. On the other hand, the JCR API was designed to target this need.
Suppose that you got a request to have a modification date added to some of your entities. In the relational model you’ll have to find out which tables should get the new field, and maybe provide an initial value for the column. Using JCR, you can simply have this modification date available only in the newly created entities. There is no need to concern about the existing data, because with JCR you can add and remove attributes on-the-fly. There is also no need to change any structure information, because it’s not required to declare any structure at all. If you would like to add a JCR repository to your existing web application, here is a walkthrough covering all the required steps.
The presented scenario assumes a Maven 2 web application, to be deployed in a Tomcat 5.5 server.
If you don’t have a web application to start with, or if you prefer to use a test project first, I suggest you to use Apache Maven to create a simple web project. To do so, run the following command in an empty directory:


mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-webapp \
-DgroupId=com.ctp.jcr.sample -DartifactId=webapp -Dversion=0.1 \
-Dpackage=com.ctp.jcr.sample.webapp


The “archetype:create” Maven goal will create an empty web project called “webapp”. Let’s import this project into Eclipse, so it will be easier to change it. Change to the project directory and run the following command to generate the Eclipse specific project configuration files:


mvn eclipse:eclipse -Dwtpversion=1.5


The project is ready to be imported by Eclipse (File > Import > Existing projects into workspace; no Maven for Eclipse plugin is required, just an environment variable needs to be configurated).
Another approach to create this project is to use a Maven plug-in for Eclipse called m2eclipse. After installing it, you can create a Maven project by opening the menu “File > New > Other…” and choosing “Maven Project”. In the “New Maven Project” wizard, click “Next”, Choose the “Internal” catalog and in the archetypes list, choose “maven-archetype-webapp”. Click “Next” and provide the group ID “com.ctp.jcr.sample” and the artifact ID “webapp”. To complete the project creation, click “Finish”.
The next step is to add the proper dependencies to the project’s POM. So change it to match the following dependencies:


<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-core</artifactId>
<version>1.4.5</version>
<scope></scope>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-rmi</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-server</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-webapp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>


After changing the POM file, run the “eclipse:eclipse” goal again, and refresh your Eclipse project. As the JCR API has a “provided” scope, the JAR file which can be found in your local Maven repository (~/.m2/repository/javax/jcr/jcr/1.0/jcr-1.0.jar) should be copied to the shared/lib Tomcat folder.
Using a context descriptor file (create the file webapp/src/main/webapp/META-INF/context.xml) a shared resource, the JCR repository, will be defined. This resource receives essentially two important parameters: “configFilePath”, which is the absolute path to the repository descriptor (the “repository.xml” file, to be explained in the next steps) and “repHomeDir”, the absolute path to the directory which will contain the repository data files.


<Context>
<Resource name="jcr/repository"
auth="Container"
type="javax.jcr.Repository"
factory="org.apache.jackrabbit.core.jndi.BindableRepositoryFactory"
configFilePath="c:/TEMP/webapp/repository/repository.xml"
repHomeDir="c:/TEMP/webapp/repository" />
</Context>


This shared resource needs to be declared in the web.xml file:


<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Archetype Created Web Application</display-name>
<resource-ref>
<description>JCR Repository</description>
<res-ref-name>jcr/repository</res-ref-name>
<res-type>javax.jcr.Repository</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>


Don’t forget to create the repository descriptor file, in the same path as specified in the context descriptor. If you don’t have your own descriptor, or if you don’t want to concern about it right now, simply copy and paste this one:


<?xml version="1.0"?>
<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.4//EN"
"http://jackrabbit.apache.org/dtd/repository-1.4.dtd">
<Repository>
<FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
<param name="path" value="${rep.home}/repository" />
</FileSystem>
<Security appName="Jackrabbit">
<AccessManager class="org.apache.jackrabbit.core.security.SimpleAccessManager" />
<LoginModule class="org.apache.jackrabbit.core.security.SimpleLoginModule" />
</Security>
<Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default" />
<Workspace name="${wsp.name}">
<FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
<param name="path" value="${wsp.home}" />
</FileSystem>
<PersistenceManager
class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager" />
<SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
<param name="path" value="${wsp.home}/index" />
</SearchIndex>
</Workspace>
<Versioning rootPath="${rep.home}/versions">
<FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
<param name="path" value="${rep.home}/versions" />
</FileSystem>
<PersistenceManager
class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager" />
</Versioning>
</Repository>


This simplified repository descriptor doesn’t depend on any kind of specific storage system. You can enhance it to store your data in a relational database, for example, but in our example it will store everything as XML files under the repository home directory.
Now let’s create a session factory class. This class will locate a repository instance and authenticate to it, to get a javax.jcr.Session instance. Create the directory ./webapp/src/main/java, and create the following class on it:


package com.ctp.jcr.sample.webapp;

import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class SessionFactory {

public static Session getSession() throws RepositoryException, NamingException {
InitialContext ctx = new InitialContext();
Context env = (Context) ctx.lookup("java:comp/env");
Repository repo = (Repository) env.lookup("jcr/repository");
return repo.login(new SimpleCredentials("admin", "".toCharArray()));
}

}


With this setup, the JCR repository can be accessed through your web application. The following JSP shows how to use the service factory to list the repository contents:


<%@page import="javax.jcr.Node"%>
<%@page import="javax.jcr.Session"%>
<%@page import="com.ctp.jcr.sample.webapp.SessionFactory"%>
<%@page import="javax.jcr.NodeIterator"%>
<html>
<body>
<%!
private void printContents(Node n, JspWriter out, String padding) throws Exception {
out.println(padding + n.getPath() + "(" + n.getPrimaryNodeType().getName() + ")");
NodeIterator it = n.getNodes();
while (it.hasNext()) {
printContents(it.nextNode(), out, padding + " ");
}
}
%>
<%
Session jcrSession = SessionFactory.getSession();
Node root = jcrSession.getRootNode();
%>
<pre>
<%
printContents(root, out, "");
%>
</pre>
</body>
</html>


This is the result displayed by the page. Observe that even for an empty repository, the infrastructure nodes are displayed as well.

Optional step: exposing the repository through WebDAV



To access your repository through WebDAV, it’s necessary to declare a servlet, through which the repository will be exposed. Add the following servlet declarations to your web.xml file:


<servlet>
<description> This servlet provides other servlets and jsps a common way to
access the repository. The repository can be accessed via JNDI, RMI or
Webdav. </description>
<servlet-name>Repository</servlet-name>
<servlet-class>org.apache.jackrabbit.j2ee.RepositoryAccessServlet</servlet-class>
<init-param>
<description> Property file that hold the same initialization properties
than the init-params below. If a parameter is specified in both places
the one in the bootstrap-config wins. </description>
<param-name>bootstrap-config</param-name>
<param-value>WEB-INF/repository/bootstrap.properties</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet>
<description> The webdav servlet that connects HTTP request to the
repository. </description>
<servlet-name>Webdav</servlet-name>
<servlet-class>org.apache.jackrabbit.j2ee.SimpleWebdavServlet</servlet-class>
<init-param>
<description> defines the prefix for spooling resources out of the
repository. </description>
<param-name>resource-path-prefix</param-name>
<param-value>/repository</param-value>
</init-param>
<init-param>
<description> Defines various dav-resource configuration parameters.
</description>
<param-name>resource-config</param-name>
<param-value>/WEB-INF/repository/config.xml</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet>
<description> The webdav servlet that connects HTTP request to the
repository. </description>
<servlet-name>JCRWebdavServer</servlet-name>
<servlet-class>org.apache.jackrabbit.j2ee.JCRWebdavServerServlet</servlet-class>
<init-param>
<description> defines the prefix for spooling resources out of the
repository. </description>
<param-name>resource-path-prefix</param-name>
<param-value>/server</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet>
<servlet-name>RMI</servlet-name>
<servlet-class>org.apache.jackrabbit.servlet.remote.RemoteBindingServlet</servlet-class>
</servlet>
<servlet>
<description>Downloads binary data from repository</description>
<display-name>Repository Download Servlet</display-name>
<servlet-name>RepositoryDownloadServlet</servlet-name>
<servlet-class>br.com.hapkidocontato.site.presentation.RepositoryDownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Webdav</servlet-name>
<url-pattern>/repository/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JCRWebdavServer</servlet-name>
<url-pattern>/server/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RMI</servlet-name>
<url-pattern>/rmi</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RepositoryDownloadServlet</servlet-name>
<url-pattern>/content/*</url-pattern>
</servlet-mapping>


Other two configurations file are referenced by those servlets. Create the directory webapp/src/main/webapp/WEB-INF/repository/ and create the file bootstrap.properties with the following values:


repository.name=java:comp/env/jcr/repository
jndi.enabled=true
jndi.name=jcr/repository


In the same directory, create the file config.xml:


<?xml version="1.0" encoding="UTF-8"?>
<config>
<iomanager>
<class name="org.apache.jackrabbit.server.io.IOManagerImpl" />
<iohandler>
<class name="org.apache.jackrabbit.server.io.VersionHandler" />
</iohandler>
<iohandler>
<class name="org.apache.jackrabbit.server.io.VersionHistoryHandler" />
</iohandler>
<iohandler>
<class name="org.apache.jackrabbit.server.io.ZipHandler" />
</iohandler>
<iohandler>
<class name="org.apache.jackrabbit.server.io.XmlHandler" />
</iohandler>
<iohandler>
<class name="org.apache.jackrabbit.server.io.DirListingExportHandler" />
</iohandler>
<iohandler>
<class name="org.apache.jackrabbit.server.io.DefaultHandler" />
</iohandler>
</iomanager>
<propertymanager>
<class name="org.apache.jackrabbit.server.io.PropertyManagerImpl" />
<propertyhandler>
<class name="org.apache.jackrabbit.server.io.VersionHandler" />
</propertyhandler>
<propertyhandler>
<class name="org.apache.jackrabbit.server.io.VersionHistoryHandler" />
</propertyhandler>
<propertyhandler>
<class name="org.apache.jackrabbit.server.io.ZipHandler" />
</propertyhandler>
<propertyhandler>
<class name="org.apache.jackrabbit.server.io.XmlHandler" />
</propertyhandler>
<propertyhandler>
<class name="org.apache.jackrabbit.server.io.DirListingExportHandler" />
</propertyhandler>
<propertyhandler>
<class name="org.apache.jackrabbit.server.io.DefaultHandler" />
</propertyhandler>
</propertymanager>
<noncollection>
<nodetypes>
<nodetype>nt:file</nodetype>
<nodetype>nt:resource</nodetype>
</nodetypes>
</noncollection>
<filter>
<class name="org.apache.jackrabbit.webdav.simple.DefaultItemFilter" />
<namespaces>
<prefix>rep</prefix>
<prefix>jcr</prefix>
</namespaces>
</filter>
</config>


And that’s all: the default workspace can be accessed through WebDAV in the following URL: http://localhost:8080/webapp/repository/default. On Windows, you can go to “My Network places” and “Add network place” to map the WebDAV location as a folder. When prompted by a username and password, just provide anything; the repository is configured to grant access to any user.
To find more about JCR, Jackrabbit and its related technologies, visit the dev.day.com weblog.

Thanks Douglas for this post! - [Tom & Balz]

Thursday, September 25, 2008

Java People Spotlight: Stefan Malär

Our "People Spotlight" series continues with the first candidate from CTP's Business Analysis team. "Java and BA? Make sure they don't consider PHP!" -- "No worries... having Stefan on a Java project is like doubling HP of your sports car:-)" -- Enjoy this spotlight on Stefan Malär:

Java Community Role:
  Senior Business Analyst [aka Java Backseat Driver]
My Master Kung-Fu Skills
:
  Hitting the Achilles heel: discovery of bugs and weak spots in the code.
  Finding the missing link: getting to work whatever doesn’t.
I'd be excited to get my hands dirty on:
  DISC (AJAX Framework) in WLP10.2, Flex integration in WLP10.2, WSRP that actually works out-of-the-box...

Q&A

Q: Hi Stefan, how would your message look like if you would have to tell it via Twitter what you are currently doing?
A: Getting our project live with whatever it takes, even coding… and of course telephone conferences with India, lots of those.

Q: What was the greates piece of code you have ever written so far?
A: A Firefox extension (that was in the days they were still called like that) to link and annotate websites and store this information through SOAP on a multimedia linking server.

Q: What is the best quote you have ever heard from one of your peers?
A: "Don’t explain it away" (bugs stay bugs...)

Q: What is the best quote you have heard from our managers?
A: "If you use JIRA you don’t need a code versioning system anymore, right?"

Q: What is the most cutting-edge technology or framework you actually used on projects?
A: WSRP, AJAX and SOAP mixed on WLS10 and WLP10. Really a lot of cutting and bleeding involved...

Q: What is your favorite podcast?
A: I was forced to write Java Posse here…, no seriously they are quite good, especially if they talk about non-Java stuff ;-)

Q: Which Java book can you recommend and for what reason?
A: Why read books if you can ask your colleagues whatever you need to know? (How cheesy is that answer! …, actually I can’t remember having read a Java book lately)

Wednesday, September 24, 2008

Top 10 Java Technologies Update: JCR Part 2

As promised in the Top 10 Technologies post, here are more details regarding JCR and the way we use it in projects.

In the other post, I have written about the requirements we usually encounter in projects when it comes to dealing with content in web applications. Not only functional requirements but also non-functional requirements such as "content is stored at different places and must be made available at a single point" were most probably the reasons for Day Software (located in Switzerland) to bring that extra layer to life and started leading the JSR-170.
Instead of rebuilding all that from scratch, Cambridge Technology Partners has chosen many times to propose and implement a JSR-170 based solution.

Being in contact with Day directly, we carefully track the evolution of JCR, currently mainly in the JSR-283 area where the JCR 2.0 standard is about to reach its final state (currently in Public Review Ballot phase).

Since JSR-170 started, it is a hot topic in different places:
a) at conferences like JavaOne in 2006,
b) on the feature lists of product vendors (JSR-170 compliance),
c) used internally in open source products like Drools BRMS for managing business rules, Apache Sling for universal resource storage and Mule Galaxy for SOA governance management and last but not least
d) CTP had many projects in the Enterprise Content Management area where we used JSR-170 bridges (e.g. "SPI to JSR-170 bridge" in the BEA WebLogic Portal where SPI is the BEA custom content interface to their Virtual Content Repository in the portal), we used JCR products directly in projects (mostly Alfresco but also Jackrabbit which is the reference implementation both being good enough for small companies, Vamosa as content migration tool where customers wanted to automate content migration from a legacy content repository to a JCR (and yes, vice-versa also :-). To make the list complete, on projects we never had the chance to use Day's Content Repository Extreme (CRX), eXo JCR (part of the eXo platform), Mirage or Jeceira (part of the Jackrabbit alternative Magnolia).

As said earlier, the official successor JSR-283 is on its way and addresses enhancements in the areas of federation, remoting, client/server protocol mappings and extensions to content modeling capabilities just to name a few. I'm sure we'll compile an extra post on this topic... so check back later.

Tuesday, September 23, 2008

Java People Spotlight: Phuong Nguyen

Our "People Spotlight" series continues with the next Java Community member Phuong Nguyen!

Java Community Role:
  Developer [aka Fongdroid or JTroubleshooter]
My Master Kung-Fu Skills
:
  Aikido (Java incompatible and performance leak issues debug & solve)
  Judo (Java unexpected errors debug & solve)
I'd be excited to get my hands dirty on
:
  Android 1.0 SDK with a Google Dream phone

Q&A

Q: Hi Phuong, how would your message look like if you would have to tell it via Twitter what you are currently doing?
A: Twitter??? Never heard about. Is it a new facebook application? :D

Q: What was the greates piece of code you have ever written so far?
A:


String documentId = request.getAttribute("documentid");
  • This line of code will fail to get what we expect to get in a WSRP scenario if the consumer doesn't federate the data to the producer.
  • In addition, for some specific configuration of an application server, it would be executed only once, or several times or not executed at all.
  • With IPC (Interportlet Communication), it could have the effect that the second portlet get the old value of the last request (one step back effect).
  • Many lessons learned from a single line of code. Isn't it great?
Q: What is the best quote you have ever heard from one of your peers?
A: "No problems :-)"

Q: What is the best quote you have heard from our managers?
A: "At the end of the day, we have to focus" (in french accent)

Q: What is the most cutting-edge technology or framework you actually used on projects?
A: WebLogic Portal 10.0 with WSRP

Q: What is your favorite podcast?
A: Jave Posse ! What else!

Q: Which Java book can you recommend and for what reason?
A: "The Java™ Language Specification", know Java as well as a Java compiler does

Monday, September 22, 2008

How to use Google's Syntax Highlighter in Blogspot

Being a techie, we sometimes wish to post source code. Now, we all know that reading it can be a pain in the neck, especially if it's not nicely formatted. As convenient as blogspot is, it doesn't provide any funtionality to format source code. Luckily there's a thing called syntax highlighter and it's quite easy to have it working with your blog. Simply follow those four steps

1. Download Syntax Highlighter from Google
2. Extract files and upload them to a webserver ([your URL])
3. Edit your template and replace

</div></div> <!-- end outer-wrapper -->
</body>
</html>


by

</div></div> <!-- end outer-wrapper -->
<link href='[your URL]/SyntaxHighlighter.css' rel='stylesheet' type='text/css'/>
<script src='[your URL]]/shCore.js' type='text/javascript'/>
<script src='[your URL]/shBrushCpp.js' type='text/javascript'/>
<script src='[your URL]/shBrushCSharp.js' type='text/javascript'/>
<script src='[your URL]/shBrushCss.js'type='text/javascript'/>
<script src='[your URL]/shBrushJava.js' type='text/javascript'/>
<script src='[your URL]/shBrushJScript.js' type='text/javascript'/>
<script src='[your URL]/shBrushSql.js' type='text/javascript'/>
<script src='[your URL]/shBrushXml.js' type='text/javascript'/>
<script class='javascript'>
//<![CDATA[
function FindTagsByName(container, name, Tag){
var elements = document.getElementsByTagName(Tag);
for (var i = 0; i < elements.length; i++){
if (elements[i].getAttribute("name") == name) {
container.push(elements[i]);
}
}
}
var elements = [];
FindTagsByName(elements, "code", "pre");
FindTagsByName(elements, "code", "textarea");
for(var i=0; i < elements.length; i++) {
if(elements[i].nodeName.toUpperCase() == "TEXTAREA") {
var childNode = elements[i].childNodes[0];
var newNode = document.createTextNode(childNode.nodeValue.replace(/<br\s*\/?>/gi,'\n'));
elements[i].replaceChild(newNode, childNode);
} else if(elements[i].nodeName.toUpperCase() == "PRE") {
brs = elements[i].getElementsByTagName("br");
for(var j = 0, brLength = brs.length; j < brLength; j++) {
var newNode = document.createTextNode("\n");
elements[i].replaceChild(newNode, brs[0]);
}
}
}
//clipboard does not work well, no line breaks
// dp.SyntaxHighlighter.ClipboardSwf =
//"[your URL]/clipboard.swf";
dp.SyntaxHighlighter.HighlightAll("code");
//]]>
</script>
</body>
</html>



4. Write your post and add source code (in the HTML tab) using either

<pre name="code" class="java">
// your code here
</pre>

or

<textarea name="code" class="java">
// your code here
</textarea>

As an example, the following code

<textarea name="code" class="java">
/**
* Hello World Example
*/
   class HelloWorld {
      public static void main(String[] args) {
         String message="Hello World!";
         System.out.println(message);
   }
}
</textarea>

becomes

/**
* Hello World Example
*/
class HelloWorld {
public static void main(String[] args) {
String message="Hello World!";
System.out.println(message);
}
}

Note:
  • When posting XML or HTML, replace < by &lt; and > by &gt;
  • change class="java" as needed to java, csharp, css, xml, html, ... (complete list)
  • JavaScript removes <br/> tags because blogger automatically adds them in case of a linebreak but syntax highlighter would display them in plain text

Friday, September 19, 2008

Java People Spotlight: Christoph Reimann

We now start with a series of "People Spotlight" posts to introduce Java related CTP consultants. Our kickoff candidate is Christoph Reimann!

Java Community Role: Developer [aka Java Grizzly Bear]
My Master Kung-Fu Skills
: WebLogic 10, JSF 1.2, Hibernate 3
I'd be excited to get my hands dirty on
: EJB 3 , Spring 2.5

Q&A

Q: Hi Christoph, how would your message look like if you would have to tell it via Twitter what you are currently doing?
A: Right now I'm coordinating the database migration of a marketing application in production together with the single point of contact and the database team.

Q: What was the greates piece of code you have ever written so far?
A: Dynamic Form generation based on business rules

Q: What is the best quote you have ever heard from one of your peers?
A: "sure sure sure" (Martin L, onsite running gag)

Q: What is the best quote you have heard from our managers?
A: "Christoph, was isch denn das fĂĽren shizzle?" (BS)

Q: What is the most cutting-edge technology or framework you actually used on projects?
A: WebLogic Portal 10.0 portlet implementations using custom data federation with WSRP

Q: Which Java book can you recommend and for what reason?
A: Handbuch der Java-Programmierung (covers all J2SE topics easy to understand)

Top 10 Java Technologies at Cambridge Technology Partners

In the second part of our "Top 10" series, we dive into the actual technologies we use in our projects.
  • Enterprise JavaBeans (EJB) 3:
    Already declared as dead, Java EE has managed to jump back on the train with EJB 3. It incorporates many best practices like convention over configuration, dependency injection and usage of annotations, simplifying development a lot compared to its predecessor.

    Although the spec for EE 5 has been out for quite a while, adoption at our customers has taken a while - but now starts getting momentum. I've seen some very nice "Aha!" moments while demonstrating what the new platform has to offer to developers. The combination of POJOs, annotations and Java standard makes setting up projects and unit tests very easy and a powerful mix for development.

    EJB 3.1 looks also promising in terms of further simplifications (and fixing some holes left in the APIs) - we're looking forward to help our customers taking this turn as well!

  • Java Persistence API (JPA) and Hibernate:
    As a de facto standard for object persistence, Hibernate has been used in our projects for years now. While working with other persistence technologies like Beehive DB Controls, iBatis or even Entity Beans due to legacy code, Hibernate has proven most efficient once the domain model got a little complexer.

    With the new Java Persistence API coming in Java EE 5, Hibernate gets even easier to integrate and use into an enterprise application. We're still missing some Hibernate features like a criteria API in JPA, but JPA 2.0 is about to fix this. Besides easier integration, JPA makes applications also more portable - there are also a couple of other JPA implementations available: Oracle TopLink, openJPA (or its big brother Kodo) or Apache Cayenne to name the best known. Being part of the EE standard, it's not a surprise that integrating JPA with EJB (or vice versa) works great!

    Mentioning JPA 2.0, let's see how EclipseLink (nominated as reference implementation) compares to Hibernate!

  • JavaServer Faces (JSF):
    MVC frameworks seem to be around like sand on the sea. From old school Struts over Wicket to Google GWT (or other fancy new AJAX frameworks) - it's hard to decide for "the right one" on projects. My recommendation usually goes to using JSF (with Facelets). Investing in a standard is in general a good thing.

    In case of JSF:
    - It has proven to be extensibe. There are a couple of very nice AJAX component libraries around, like JBoss RichFaces, Woodstock or ICEfaces. And also, JBoss Seam adds a few killer features to JSF, just to name stateful navigation or transactional backing components here.
    - It is programmable with a declarative view definition in XHTML and an expression language. Facelets adds an extremely powerful templating to JSF, which I found much easier to use than frameworks like Tiles or SiteMesh.
    - Growing IDE support (Eclipse WTP, JBoss Tools, NetBeans and the latest IntelliJ to name some) featuring WYSIWYG editors or (for me much more useful) XHTML and EL code completion.

    By the way, Java EE 6 features JSF 2.0, including enhancements for component developers as well as standardazing on Facelets!

  • JBoss Seam:
    In my humble opinion, one of the most innovative frameworks over the last years. As already mentioned in a previous post, the stack around Seam works for me extremely well and efficient to develop web applications.

    Getting back on my previous statement on investing in standards - I'm looking forward to WebBeans (I hope JSR-299 makes it into Java EE 6), combining Seam with typesafe dependency injection of Google Guice! Looking back at my first servlet based web application during CS studies, things have become amazingly elegant to develop!

  • Spring Framework:
    Both EJB 3 and Spring in the same list? Yes, Spring is also a great piece of technology in use at many of our customers. It has not been the first open source dependency injection container (just to mention e.g. Pico) but was the first "enterprise ready" implementation out there making me extremely happy to work with after sweating on an EJB 2 project.

    Third party products (e.g. CRMs) which do not support Java EE 5 application server versions are sometimes limiting constraints for upgrading, which make usage of Spring a great alternative to customers which are still bound to EJB 2. Even if you don't deploy a Spring runtime, it offers great support for your unit tests - like using SimpleNamingContextBuilder to mock an InitialContext!

    The latest 2.5 release of Spring makes also (finally) use of annotations to inject bean dependencies, which is a great improvement over the previous "XML salad". Adam Bien has written a nice post on XML vs. annotations in EJB 3, which covers with my experiences and can be similarly handled in Spring.

  • JAX-WS:
    While we've gone through a couple of web service technology stacks, the JAX-WS standard has been for us the most convincing on to work with (did I already mention we generally like standards? ;-). Its reference implementation Metro has made its way into major application servers like Oracle WebLogic, JBoss, GlassFish (and probably others), allowing us to easily take best practices from customer to customer.

    If you're rather out for something simpler than a full SOAP stack, also have a look at JAX-RS, the standard for RESTful web services. Its reference implementation Jersey is on its way to version 1.0, but already now ready for some really cool use cases (try it out with e.g. JFreeChart to create dynamic charts in web applications)!


  • TestNG:
    While writing unit tests for years with JUnit, I've made the experience that some limitations of the framework have somehow led to ugly test code - clunky test method signatures with no arguments, no mechanism to define dependencies between tests and no built-in mechanism to run test methods with different test data.

    In a real world enterprise project, testing just the "unit" is not always enough. With Spring for example, we can run the whole container and execute test cases on it - this is definitely much faster than deploying to the container. TestNG has shown to be more useful than JUnit in this context. Also several large open source projects have decided for TestNG, to name JBoss (by the way: congrats for passing the EE 5 TCK!) or GlassFish.

  • jBPM and Drools:
    Probably not the most advanced BPM on the market, but at least in the open source space jBPM is the leading engine we've been working with so far. Now part of JBoss middleware suite, jBPM together with the Drools rule engine form a powerful couple when shaping SOA applications. But also running without jBPM, Drools has shown to be a great engine to externalise business rules in a very clean and maintainable way (which would otherwise probably have ended up in some ugly if-else jungle or rather complex decorator pattern classes).

  • Java Content Repository (JCR):
    It is extremely common for applications to store various pieces of information, most of the time in relational databases. While they do a great job when working with regular data types (e.g. int, string), we think they are not very efficient when dealing with binary data (unstructured), for example images or documents (structure binaries). On top of that, many features are not covered by pure DB products out of the box:
    Usually, such requirements we encounter on projects are proper management of documents, versioning, enhanced meta data tagging, handling of structured as well as unstructured content, proper handling of dependencies between content nodes (known as referencial integrity), flexibility with regards to node attribute extensions and inheritance, administration delegation, and many more.

    In such cases where an extra layer is needed on top of a database, JCR and JSR-170 quickly come into the picture of our solution proposals for our customers.

    More details will follow in a few days regarding JCR at CTP.

  • Scala:
    Honestly, we haven't had Scala in a customer project yet. Still it seems to be the most interesting newcomer in the "scripting on the JVM" category, offering static typing and a couple of interesting language constructs (to build e.g. DSLs). Unfortunately the learning curve is a little steeper than with other scripting languages, so a deeper analysis on where we can leverage this at our customers will have to wait until my next "beach time".

Thursday, August 28, 2008

Portal Update August 2008

Enjoy this year's last summer edition :-) of the monthly portal summary by Cambridge Technology Partners:
  • SUN: At JavaOne 2008, I attended the session about project SocialSite [PDF] where it was announced. Now it has been officially launched on August 8th: an open source project building Widgets and Web Services that make it easy for you to add social networking features to your existing web applications and therefore portals as well.
    One of the key technology used in SocialSite is Shindig, a reference implementation for the Google-initiated OpenSocial API (now up to v0.8). This API has strong backup from all the major social networks (LinkedIn, MySpace, Plaxo, Ning, SalesForce.com, Hi5, and more), Facebook is not on the list (so far).
    Side remark: SocialSite also belongs to the Glassfish Community.
  • SUN: WebSynergy: As posted in July's portal summary, Liferay and SUN jointly work on the next generation portal technology. On August 1st, this roadmap has been posted which gives some hints about what we can expect.
  • SUN: WebSynergy: On august 28th, Stable Build 2 has been released! The feature list is really impressive:
    - Fully JSR-286 compliant and full tooling support via Portal Pack for Netbeans.
    - WSRP 2.0 consumer feature is integrated in this release (more to come, see more details later)
    - Liferay Portal has been modified to use the Mirage API. This API enables WebSynergy access JCR-compliant repositories.
    - The Roller Blog app provides integration with Roller Weblogger version 4.0. Using this app, portal users can create and manage blogs on a Roller 4.0 server.
    - The Simple API for Workflow (SAW) feature is integrated now. You can use SAW to connect to a business process engine (which is provided through e.g. Java CAPS)
  • SUN: The WSRP Team of WebSynergy has finalized phase 1 of their current integration project and integrated the WSRP 2.0 Consumer into Liferay. This feature allows applications hosted on remote sites (e.g. OpenPortal portlets) to be presented through the Liferay portal desktop. Next step is integrating the producer part. Stay tuned.
  • SUN: Netbeans 6.1: Portal Pack 2.0.1 has been released. It features support for JSR-286 portlets, a visual portlet builder plugin to build JSF portlets and code auto completion for the portlet 1.0/2.0 taglib, just to name a few features.
  • eXo:
    - Aug 11th: eXo has released Portal 2.2: Support of Cometd, extended REST support, support latest Groovy version 1.5.6
    - Aug 15th: eXo has released an "all in one" bundle which includes Portal 2.1
    - No updates regarding WebOS
    Announcements for future releases:
    - With the next portal release in september, GWT applications can be run in the eXo Portal.
  • JBoss:
    - JBoss released JBoss Tools 3.0.0 alpha1 which features initial support for portlets (JSR-168 and JSR-286) including JSF and Seam. A nice guideline has been posted here.
    - They have announced that JBoss Portal 2.7 will be released in september. As indicated in our last month's portal post, Portal 2.7 integrates the new JBoss Portlet container implementing the Portlet 2.0 API (JSR 286).
  • Oracle (BEA): As announced in the strategic webcast beginning of july, the only strategic portal product is Oracle WebCenter Suite. I remember the slides with three columns "strategic", "continue & converge" and "maintenance". BEA WebLogic Portal (WLP), Oracle Portal as well as AquaLogic User Interaction (ALUI) were in the middle column.
    Nonetheless, it was not clear to me that today's WebCenter Suite contains most collaborative components of ALUI already. This I somehow discovered in the official description now. So it seams that ALUI has converged much quicker than WLP (if that is going to be converged at all).
    As far as WLP and Oracle Portal are concerned, they are both not strategic but Oracle currently assures support and product evolution for at least the next 9 years (e.g. upcoming WLP release). Evolution can also be reached through three different integration possibilities with WebCenter Suite: Either through Oracle WebCenter Services, Oracle ECM Services or via remote portlets over WSRP (which means that new applications are developed and deployed to WebCenter and consumed in the legacy portal...).
  • Oracle (BEA): no official details yet about upcoming release of WLP 10.3 yet (Codename Sunshine). Stay tuned.
  • IBM: no updates for August
  • Vendor agnostic:
    - InfoQ has posted Part 1 and Part 2 out of three articles about writing portlets using JSF, Ajax and Seam deployed to JBoss Portal. For a quick intro they are really worth looking at.
    - The OpenPortal community hosted by SUN contains many sub projects where JSF Portlet Bridge is one of those. End of July, they released version 1.2.3 which is a bugfix release for JSF 1.2. It enables JSF applications to run in a Portlet 2.0 container. The bridge fully supports JSR-301 which defines two bridges: JSF 1.2 with Portlet 1.0 container and JSf 1.2 with Portlet 2.0. The reference implementation for JSR-301 is the MyFaces Portlet Bridge. JBoss Portal runs with its own bridge implementation, which is also JSR-301 compliant and integrates well with Seam and AJAX.

Wow, quite a lot for one month!
Cheers,
Balz ... with inputs from CTP Java Fellow Thomas ;-) Messiiiiiiiii