This post describes the JOnAS Showcase. This showcase illustrates how the JOnAS application server supports OSGi integration. Thanks to JOnAS, OSGi and Java EE can collaborate together in a very elegant way.
Java EE vs. OSGi
Since a couple of years, two different ways to develop enterprise applications “emerged”:
- Java Platform, Enterprise Edition or Java EE is a widely used platform for server programming in the Java programming language. The Java platform (Enterprise Edition) differs from the Java Standard Edition Platform (Java SE) in that it adds libraries, which provide functionality to deploy fault-tolerant, distributed, multi-tier Java software, based largely on components running on an application server.
- The OSGi framework is a module system for Java that implements a complete and dynamic component model, something that does not exist in standalone Java/VM environments. Applications or components (coming in the form of bundles for deployment) can be remotely installed, started, stopped, updated and uninstalled without requiring a reboot; management of Java packages/classes is specified in great detail. Life cycle management is done via APIs, which allow for remote downloading of management policies. The service registry allows bundles to detect the addition of new services, or the removal of services, and adapt accordingly.
Nowadays, a stringent problematic is to reunify those two worlds. Despite a large dominance of Java EE in enterprise application development, the OSGi wave is menacing the Java EE hegemony. There are several reasons for this menace. First, the OSGi modularity system is clean, tailored, and powerful. It also promotes good practices (modules, separation between the implementations and the specifications, etc.). Using OSGi improves the product “quality” and eases its maintenance. Moreover, the hot-deployment and the dynamism features of OSGi are interesting for enterprise applications.
Emerging trends are:
- Enterprise OSGi is a way to develop OSGi enterprise applications. Enterprise OSGi frameworks such as Spring-DM and the akquinet enterprise OSGi distribution. Those frameworks provide mostly the same technical services as Java EE application servers. However, the development model on the top of those frameworks is different compared to Servlets and EJBs. Spring-DM promotes the Spring component model, while the akquinet enterprise jumppack promotes an iPOJO development model integrating all technical services seamlessly in the business code.
- Java EE Application Servers are also looking at OSGi, and tend to run on the top of OSGi. It’s already the case for IBM Webshpere, Sun Glassfish, and OW2 JOnAS. JBoss made a slightly different choice by running OSGi and the Java EE application server side by side (JBossOSGi).
JOnAS has also made a very interesting choice. First, the server runs on the top of OSGi (Apache Felix), but they also extend the EJB capabilities to be able to communicate with OSGi services. Moreover, The EJBs can also be registered as OSGi service. This seamless integration of OSGi and Java EE is the most advanced as of today – allowing to reuse legacy EJBs from scratch without any changes.
OW2 JOnAS
JOnAS is a leading edge Open Source implementation by OW2 of the Java EE specification. The stable versions are J2EE 1.4 certified and the latest 5.1 release candidates are Java EE 5 certified. The OW2 development community includes many academic institutes (Grenoble University, INRIA, LIFL, Peking University, UPM) working with JOnAS and industrial partners (Bull, France Telecom). This fastens technology transfers and makes JOnAS a top-level product in term of technology innovation.
- JOnAS 5 is designed with an OSGi based services architecture to provide a dynamically adaptable application server
- JOnAS is implementing the full Java EE 5 execution stack and provides, with EasyBeans, an efficient, pluggable and easy to use EJB3 container
- The OW2 JASMINe project contains tools for creating, deploying and monitoring JOnAS clusters; it will include self-management features
About the OSGi integration, all technical services are exposed as OSGi services. So, regular OSGi bundles deployed in JOnAS can use those services and EJBs can interact with OSGi services delivered by plain OSGi bundles. Finally, EJBs may be registered as OSGi services, and plain OSGi bundles can interact with EJBs!
JOnAS 5 architecture
About the showcase
This series focuses on JOnAS and illustrates, using a simple “shop” example, how Java EE and OSGi can collaborate together. The goal is to show how a Java EE application can profit from OSGi dynamism.
This showcase presents a coffee shop (Dunkin’ JOnAS) where the core is provided by an EAR application. Products extend this core. The interesting aspect is that products are delivered separately as
- iPOJO components
- Stateless EJBs
JOnAS showcase architecture
The final application
The code of this showcase is available on the JOnAS showcase project.
Part 1: The Shop
The shop is composed of a WAR file containing a servlet and html pages, and an EJB. The interesting aspect of the shop is this EJB. The servlet uses this EJB which in turn uses OSGi services to return a list of available products.
How EJBs interact with OSGi services
The corner stone of the shop is an EJB retrieving available products from OSGi services. Let’s see how this can be achieved thanks to JOnAS:
@Stateless(name="CoffeeShopBean") public class CoffeeShopBean implements Shop { @OSGiResource private BundleContext bundleContext; @OSGiResource(multiplicity=Multiplicity.MULTIPLE, type=BeverageSupplier.class) private List<BeverageSupplier> bevSupps; //…
The JOnAS EJB container (called Easybeans) provides a set of annotations to inject either the bundle context or directly OSGi services. The bundle context is an object defined by OSGi that gives access to the OSGi service registry.
Once the bundle context is injected, the EJB can use it to retrieve available services:
// Get condiment providers with the bundle context ServiceReference[] refs = null; try { refs = bundleContext.getServiceReferences(CondimentSupplier.class.getName(), null); // No filter, get all providers. } catch (InvalidSyntaxException e) { // Cannot happen as the filter is null } if (refs != null) { // Returns null if no providers are available. for (int i = 0; i <= refs.length; i++) { CondimentSupplier supplier = (CondimentSupplier) bundleContext.getService(refs[i]); List<String> products = supplier.getAvailableProducts(); // ... Build product models. } }
This is regular OSGi code, nothing else it required!
Moreover, thanks to the @OSGiResource annotation, an EJB can easily get OSGi services without using the bundle context. As you can see above, the “bevSupps” member holds the list of beverage suppliers which are normal OSGi services.
So, the Easybeans container provides a quite simple and clean way to interact with the OSGi environment!
Deploying the shop
The shop is packaged inside an EAR. However to interact with OSGi easily, the interfaces used during this interaction must be delivered as a separate bundle, i.e. OSGi package. This bundle exports the package containing the interfaces used by the OSGi services and by the shop. This way, they share the same interface.
To deploy the shop, two artifacts have to be deployed: the bundle containing the interfaces and the EAR. Fortunately, JOnAS provides advanced deployment features. The JOnAS deployment agent allows deploying several artifacts (bundle, jar file, war file, ear file…) in one go. To use this feature, you just have to write a so-called deployment plan listing the artifacts to deploy by using URLs, OBR (OSGi Bundle Repository) resource descriptions or Maven 2 artifact identifier (group id, artifact id and version). By writing a simple deployment plan, the deployment process is completely automated.
Let’s say that your artifacts are deployed on a Maven 2 repository. The first thing is to write a file describing this repository in order to add it to the JOnAS deployment agent. The following file adds the maven repository containing the JOnAS Showcase artifacts:
<repositories xmlns="http://jonas.ow2.org/ns/deployment-plan/repositories/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="repositories-1.0.xsd"> <repository id="JOnAS-showcase-maven-repository"> <type>maven2</type> <url>http://jonas-showcase.googlecode.com/svn/maven-repository/</url> </repository> </repositories>
Next, we just need to write the deployment plan for the shop, describing the two artifacts to deploy:
<deployment-plan xmlns="http://jonas.ow2.org/ns/deployment-plan/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m2="http://jonas.ow2.org/ns/deployment-plan/maven2/1.0"> <deployment xsi:type="m2:maven2-deploymentType" id="interfaces"> <m2:groupId>de.akquinet.gomobile.jonas.showcase</m2:groupId> <m2:artifactId>interfaces</m2:artifactId> <m2:version>1.0.0</m2:version> </deployment> <deployment xsi:type="m2:maven2-deploymentType" id="shop"> <m2:groupId>de.akquinet.gomobile.jonas.showcase</m2:groupId> <m2:artifactId>shop-ear</m2:artifactId> <m2:version>1.0.0</m2:version> <m2:type>ear</m2:type> </deployment> </deployment-plan>
Once these two files are written, just drop them in the “deploy” folder of your JOnAS instance. This folder is watched periodically and contained files are processed. Once processed, you see the empty shop on http://localhost:9000/showcase/coffee.html
Note: Update the above URL according to your installation.
The Dunkin’ JOnAS shop with no product providers
Part 2: The Product Providers
The shop is currently empty as the EJB does not find any OSGi services. This section describes how to provide such services packaged in separate bundles.
Product Providers implemented with iPOJO
Apache Felix iPOJO is a component model drastically simplifying OSGi application development. iPOJO manages all the interactions with the OSGi framework. Developing a product provider is really easy:
@Component @Provides public class CoffeeProvider implements BeverageSupplier { private Map<String,CoffeeProduct> coffees; public CoffeeProvider(){ System.out.println("instantiate CoffeeProvider with 3 types of coffee"); coffees = new HashMap<String, CoffeeProduct>(); CoffeeProduct coffee1 = new CoffeeProduct("Sumatra", 2.55, "Coffee-Sumatra-0"); CoffeeProduct coffee2 = new CoffeeProduct("Costa Rica", 2.99, "Coffee-CostaRica-0"); CoffeeProduct coffee3 = new CoffeeProduct("Columbia", 3.05, "Coffee-Columbia-0"); coffees.put("Sumatra", coffee1); coffees.put("Costa Rica", coffee2); coffees.put("Columbia", coffee3); } //…
The class just implements the service interface implementation (BeverageSupplier). The iPOJO annotations (@Component and @Provides) ask iPOJO to register the Beverage Supplier as an OSGi service. This implementation is packaged inside an iPOJO bundle. This bundle imports the package, containing the service interface, from the bundle created for the shop.
For more info about iPOJO, just visit the Apache Felix iPOJO web site.
Product Providers implemented with EJB
Stateless EJBs can also provide OSGi services. The local interface of stateless EJBs packaged inside specific bundles is automatically registered as OSGi service by the Easybeans container.
Implementing a product provider with such mechanism is relatively simple as well:
@Local(CondimentSupplier.class) @Stateless(mappedName="MilkProvider") public class MilkProvider implements CondimentSupplier { //… }
As for the iPOJO implementation, the class just contains the business code and EJB 3.0 annotations.
Then this class is packaged inside an OSGi bundle with some special manifest headers:
- The bundle activator, used by the OSGi framework to activate the bundle, must be “org.ow2.easybeans.osgi.ejbjar.Activator”
- The import-package header, specifying which packages are imported from others OSGi bundles, must contains the package containing the service interface
- The DynamicImport-Package header must be set to *, meaning that anything can be imported. This is useful when the EJB uses ORM mechanisms such as hibernate.
Deployment
Product providers are packaged inside OSGi bundles. So to deploy them you just drop the bundle file into the “deploy” folder of your JOnAS instance. Obviously, you can also use deployment plans as we did for the shop:
<deployment-plan xmlns="http://jonas.ow2.org/ns/deployment-plan/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m2="http://jonas.ow2.org/ns/deployment-plan/maven2/1.0"> <deployment xsi:type="m2:maven2-deploymentType" id="shop"> <m2:groupId>de.akquinet.gomobile.jonas.showcase</m2:groupId> <m2:artifactId>product-coffeeprovider-bundle</m2:artifactId> <m2:version>1.0.0</m2:version> <m2:type>jar</m2:type> </deployment> </deployment-plan>
Dependening on which bundles are deployed, the set of provided products of the shop change. This way, the shop becomes highly extensible, as it is possible to deploy new product providers at runtime, as well as to remove them.
Conclusion
This post has explored the possibilities of JOnAS to create a Java EE / OSGi ecosystem. These two worlds can communicate seamlessly thanks to the JOnAS application server. This paves the road to new dynamic, modular, and extensible enterprise applications. Such applications profit from the Java EE infrastructure technical services as well as from the OSGi runtime provided features like modularity and dynamism.
In collaboration with the JOnAS team, akquinet leads the initiative to create modular, dynamic and extensible enterprise applications using both Java EE and OSGi. Feel free to contact us or post a comment if you have any questions.
Acknowledgments
The authors would like to thank the JOnAS team for their help during the development of the showcase.