Deployment Options on GlassFish 3
Everybody who has done some kind of web development using JEE are familiar with the deployment procedure: create a deployment descriptor, package the application into a WAR and either drop it in an autodeploy directory or use some deployment tool. Any third-party libraries (such as Vaadin) has to be either present in the server's classpath or included in the WAR.
With GlassFish 3, Sun's latest application server, we get two new deployment options thanks to GlassFish's built-in support for OSGi. In this article, we are going to explore the deployment options and briefly discuss their pros and cons.
This article does not contain any code examples, but some basic knowledge of OSGi and JEE web application development is needed to fully understand it.
The Deployment Alternatives #
With GlassFish 3, we have three ways of deploying a Vaadin application instead of one. The following figure tries to illustrate the ways and the differences between them:
In the following, we are going to look a little closer at each deployment alternative.
Classic Deployment #
The classic deployment alternative should be familiar to all Vaadin developers. Here, both the application and the Vaadin library are packaged into a WAR, which is deployed to a web container. In GlassFish 3, this procedure is no different than any other JEE web container. However, there are a few JEE 6 features that could come in handy:
- Instead of configuring the servlets in the deployment descriptor web.xml, they can be configured using the new @WebServlet annotation. This, on the other hand, means that ApplicationServlet no longer can be used, and requires the Vaadin applications to subclass AbstractApplicationServlet instead. This approach has some advantages, though, that we will return to later in this article.
- EJBs can be packaged together with the Vaadin application inside the same WAR and they do not require a deployment descriptor.
The advantage with this approach is that it is the standard way of deploying JEE applications and therefore almost always works. However, if the size of the included libraries is large, the deployment process may take some time. In addition, if many applications using the same third party libraries are deployed to the same server, disk space gets wasted by redundant library files.
Today, disk space is almost free, so that is not a big issue. However, a lengthy compile-package-redeploy cycle can have a negative impact on both developer efficiency and the developer's patience. Server side components can often be tested in isolation using unit testing and so do not require frequent deployments. This is not the case with user interfaces, that need to be tested often and require deployment before testing is possible.
Combining Classic and OSGi Deployment #
In order to reduce the size of the WAR, we can strip it of all libraries and deploy these as OSGi bundles instead. The web application will still be deployed in the classical way and run inside the web container, but it will have access to all the packages that have been exported by the OSGi bundles currently installed.
Some third party libraries, such as the Spring Framework libraries, are already OSGi bundles and can be deployed as-is. Other libraries have to be converted before they can be deployed. This process can sometimes be as easy as creating a manifest and repackaging the JAR, sometimes a bit more difficult and sometimes impossible.
The reason for this is that OSGi handles class loading in a different way than an ordinary JVM. An OSGi bundle can only see classes that it explicitly imports. If a library relies on Class.forName(..) or otherwise has a design that clashes with the OSGi model, it is probably easier to deploy it inside the WAR and wait until the developers release an OSGi ready version. JPA, for example, does currently not play well with OSGi, although the problem is being solved (according to this blog entry).
The 6.2 nightly builds of Vaadin support OSGi as of October 21, 2009. However, due to the class loading problem, we can no longer use ApplicationServlet as it tries to look up the application class by name. Instead, we have to subclass AbstractApplicationServlet and provide the application class instance directly. An example on how to do this can be found in the Hello GlassFish 3 article.
The advantage of this deployment approach is that all (in a perfect world, that is) of the third party libraries need to be deployed only once, separately from the application WAR(s). Thanks to this, the WAR sizes are reduced, which in turn leads to a faster compile-package-redeploy cycle.
However, if there are applications running on the same server that require different versions of the same third-party library, things can get a little tricky. OSGi supports deploying several versions of the same bundle, but the web applications will always have access to the newest version only. Fortunately, there is a solution to this problem as well.
Pure OSGi Deployment #
In GlassFish 3, it is possible to deploy the application itself as an OSGi bundle (called a Web Application Bundle (WAB)). By including a directive in the manifest, the OSGi container will detect all the servlets upon bundle startup and run them inside the web container. Thus, you can have both JEE and OSGi at the same time! This in turn makes it possible to deploy different versions of the same bundle (provided that they have separate context paths, of course) using different versions of e.g. the Vaadin library on the same server at the same time.
The main disadvantages with this approach is firstly the class loading problems mentioned in the previous section, and secondly lack of the tool support that is available for ordinary JEE development.
Some Benchmarks #
So which approach is faster? It is impossible to give a definitive answer without a more extensive investigation. In addition to the deployment procedure, there are other factors that play in, such as tool support. For example, some IDEs support automatic deployment after every change in the source code, whereas others require an explicit redeploy operation.
To give you a rough idea, here are the deployment times for two applications, Hello World and Address Book. Both applications were deployed as standard JEE applications using the asadmin tool. The deployment times have been taken from the GlassFish log file.
|Application||with Vaadin||without Vaadin|
|Hello World||1016 ms||266 ms|
|Address Book||2356 ms||450 ms|
No reliable deployment times could be measured for the OSGi-only approach. First of all, the deployment time is not printed to the log so it has to be measured in some other way. Secondly, OSGi uses load-on-demand, which means that even though a bundle has been deployed, it is not started until it is actually needed. Thus, the first time a bundle is deployed, it may take a while before all the required bundles are started. The second time, however, may be significantly faster.
Further Reading #
For a practical example on how to use the different deployment options, check the Hello GlassFish 3 article. Once you have read this, you could move on to the Creating a Modular Vaadin Application with OSGi article, which dives a little deeper into the possibilities that OSGi offers Vaadin developers. And if you want to see some of the new JEE 6 features in action, check the Adding JPA to the Address Book Demo article.