Skip to main content

Build an SOA framework with Apache Geronimo and POJOs

Simplify the task with POJO programming, GBeans, and the Geronimo kernel

J. Jeffrey Hanson (jeff@jeffhanson.com), Chief Architect, eReinsure.com, Inc.
Jeff Hanson
Jeff Hanson has more than 20 years of experience in the software industry, including work as senior engineer for the Windows OpenDoc project and lead architect for the Route 66 framework at Novell. Jeff is currently the chief architect for eReinsure.com, Inc. and builds Web service frameworks and platforms for Java EE-based reinsurance systems. Jeff is the author of numerous articles and books, including .NET versus J2EE Web Services: A Comparison of Approaches, Pro JMX: Java Management Extensions, and Web Services Business Strategies and Architectures.

Summary:  Developing software without regard to the application program interface (API) constraints enforced by libraries and frameworks is an appealing proposition. This lure has led many to accept the paradigm of Plain Old Java™ Object (POJO) programming -- the idea that you should be able to develop software on the Java platform without being required to use superfluous interfaces or third-party APIs. The Apache Geronimo framework provides a solid infrastructure for POJO development to build sophisticated applications and services. Discover some of the components and techniques of the Geronimo framework that you can use to realize successful service-oriented development using POJO tactics.

Date:  11 Jul 2006
Level:  Intermediate
Activity:  1443 views

Service-oriented architecture (SOA) and service-oriented programming are terms that refer to a style of software engineering that encapsulates business logic as modular services. These services target dynamic runtime environments in which associations between service providers and service consumers are loosely coupled. Services that are loosely coupled typically have no compile-time associations, so you can link them dynamically at run time, allowing deployment personnel the flexibility to make deployment decisions as needs arise. In addition to loose couplings, the following concepts are common in a service-oriented environment:

  • Coarse granularity: Granularity with services refers to the extent of functionality that a service presents publicly. Fine-grained services present public interfaces defining a specialized degree of functionality. Coarse-grained services present a more general degree of functionality, typically to suit a given business domain.
  • Location transparency: Location transparency refers to the idea that clients can access services without regard to location on a network.
  • Protocol independence: Protocol independence refers to the idea that clients can access services without regard to the communication/network protocol.

Building services with these concepts in mind can be a daunting task. POJO programming seeks to simplify this task.

Introducing POJOs

POJOs are Java classes that are not required to adhere to specific external interfaces or third-party APIs. This ability in itself essentially decouples code from external associations. One of the primary benefits of this decoupling is the freedom it gives software developers from ancillary tasks, such as persistence, transaction support, and remoting. Many techniques eliminate component/class decoupling and facilitate POJO programming, including:

  • Annotations are metadata that development tools consume and use to generate code that "decorates" a class or a portion of a class to support a given type of functionality or feature, such as remoting, persistence, and framework support.
  • Dependency injection is a technique for building pluggable components whereby object creation and association is removed from the components and carried out by containers or assembler components.
  • Reflection is the runtime discovery of information, such as methods, fields, and constructors, about a given class or interface.

Each decoupling technique has its advantages and disadvantages. This article proposes a simple SOA framework through POJO programming that uses reflection and Geronimo's GBean dependency injection to enable component decoupling.


JMX and Geronimo

Geronimo is built on a general-purpose kernel that uses Java Management Extensions (JMX) and a dependency injection framework of managed components called GBeans. Virtually everything in Geronimo (adapters, applications, containers, and so on) is either a GBean or is based on a GBean. GBeans share many similarities and underlying infrastructure with JMX and JMX Managed Beans (MBeans).

JMX

The JMX specification has emerged as the Java standard for systems management, applications management, and resource management. JMX defines a standard for dynamically augmenting Java classes, interfaces, and runtime objects with attributes and operations to be used for management purposes. This augmentation technique is known as instrumentation.

JMX can manage any resource (such as an application, device, or service) that you can abstract using the Java programming language. Each managed resource is referred to as an MBean. JMX defines four types of MBeans:

  • Standard MBeans use Java interfaces to define their management attributes and operations.
  • Dynamic MBeans use runtime discovery to define their management attributes and operations.
  • Model MBeans act as proxies for objects wanting to expose manageable operations and attributes.
  • Open MBeans use a predefined metadata vocabulary to expose the manageable attributes and operations of classes and objects.

The primary interface to interacting with MBeans is the javax.management.MBeanServer. The MBeanServer acts as a central repository of MBeans and facilitates communication with the MBeans from MBean clients.

MBeans are uniquely identified by an ObjectName object. An ObjectName instance consists of:

  • A domain, which is an arbitrary name for a given domain; conventions recommend using reverse domain name system (DNS) naming for domains in the same manner as Java package naming.
  • A key property list, which is an arbitrary, unordered set of keys and associated values.

The following code demonstrates constructing a typical ObjectName object:

String domain = "com.jeffhanson.test";
String keyPropertyList =
"domain:Name=TestBean,Type=GenericService";
ObjectName objName =
new ObjectName(domain + ":" + keyPropertyList);



ObjectName objects are used as parameters to many of the MBeanServer methods to retrieve attributes and invoke operations on an MBean.

Geronimo's GBean framework

GBeans are managed components in Geronimo that share many similarities and relationships with JMX MBeans, such as exposing attributes and operations according to a class named GBeanInfo, which is strikingly similar to the JMX equivalent MBeanInfo class. Geronimo uses the MX4J library (see Resources at the end of this article for a link) as its implementation of JMX.

GBeans maintain states and association dependencies, and they handle life cycle events. A GBean can register as an interested party in the status of other GBeans. After the GBean of interest is started, the interested GBean will receive a reference to the GBean of interest through dependency injection. A GBean can be in one of these seven life cycle states at any given time:

  1. Loaded
  2. Unloaded
  3. Starting
  4. Running
  5. Stopping
  6. Stopped
  7. Failed

Listing 1 illustrates a simple GBean containing one attribute (message).



































Listing 1. A typical GBean
public class TestGBean
   implements GBeanLifecycle
{
   private static GBeanInfo GBEAN_INFO = null;

   static
   {
      GBeanInfoBuilder infoFactory =
         GBeanInfoBuilder.createStatic(TestGBean.class);
      infoFactory.addAttribute("message", String.class, true);
      infoFactory.addOperation("getMessage");
      GBEAN_INFO = infoFactory.getBeanInfo();
   }

   private String message;

   public String getMessage()
   {
      return message;
   }

   ...
}

You can start (activate) and stop the GBean with the code illustrated in Listing 2.


Listing 2. Starting a typical GBean
ObjectName testGBeanOName =
   ObjectName.newInstance("jeffhanson.test:ID=test");
GBeanData gBeanData =
   new GBeanData(testGBeanOName, TestBean.GBEAN_INFO);
gBeanData.setAttribute("message", "Hello world");
geronimoKernel.loadGBean(gBeanData,
                         Thread.currentThread().
                            getContextClassLoader());
geronimoKernel.startGBean(testGBeanOName);
...
geronimoKernel.stopGBean(testGBeanOName);
geronimoKernel.unloadGBean(testGBeanOName);

You can use GBeans extensively throughout the Geronimo kernel.


A Geronimo kernel

A Geronimo kernel is a framework of GBeans. Using this framework, you can model and build most any sophisticated system as a set of GBean containers and GBean components to manage state, relationships, and event handling.

Creating a Geronimo kernel programmatically is a simple process using the KernelFactory classes. Listing 3 demonstrates how to create a new Geronimo kernel named TestGeronimo, booting the kernel, logging the boot time, and loading and starting a servlet GBean.


Listing 3. Creating a simple Geronimo kernel
try
{
   Kernel geronimoKernel =
      BasicKernelFactory.newInstance().
         createKernel("TestGeronimo");

   geronimoKernel.boot();
 
   log.debug("Geronimo BootTime: "
             + geronimoKernel.getBootTime());

   // add the servlet GBean
   ObjectName servletObjName =
      new ObjectName("jeffhanson.test:ID=MyGBean");
   GBeanData servletGBeanData = new GBeanData(servletObjName,
                                              GBEAN_INFO);
   ClassLoader classLoader = getClass().getClassLoader();
   geronimoKernel.loadGBean(servletGBeanData, classLoader);
   geronimoKernel.startGBean(servletObjName);
}
catch (Exception e)
{
   log.error(e);
}

After you create and run the kernel, invoking a method on a POJO service simply becomes an exercise in using the Geronimo kernel server and its reflection capabilities, as shown in Listing 4.


Listing 4. Invoking a call on a service registered with the kernel
private static
Object invokePOJOService(ObjectName serviceObjName,
                         String operationName,
                         String[] params)
   throws Exception
{
   String[] paramTypes = null;
   if (params != null && params.length > 0)
   {
      paramTypes = new String[params.length];
      for (int i = 0; i < params.length; i++)
      {
         paramTypes[i] = params[i].getClass().getName();
      }
   }

   Kernel geronimoKernel =
      KernelManager.getInstance().getGeronimoKernel();

   Object retVal = 
      geronimoKernel.invoke(serviceObjName,
                            operationName,
                            (Object[])params,
                            paramTypes);

   return retVal;
}


An adaptable framework of service-oriented POJOs in Geronimo

The POJO-for-SOA framework referred to in this article uses an instance of the Geronimo kernel to register POJOs as GBeans whereby interested clients can query and invoke them without the need for additional interfaces or APIs. The framework resides in the business tier of a multi-tiered enterprise application environment. A service-locator class is responsible for interacting with the kernel to find and, if needed, register POJOs to be used as services. The service-locator class then returns the POJOs to a business-delegate component where it invokes them. Figure 1 illustrates the relationships of components in the framework.


Figure 1. The POJO-for-SOA framework
POJO-for-SOA framework

The framework is designed to receive HTTP requests from a client, and then pass the request(s) through to a dispatcher component that massages and dispatches the request(s) to the business-delegate component. The business-delegate component then makes use of the service locator to find the service for a particular request. The business delegate component invokes the service and wraps any return value as a model object. The appropriate view component processes the model object and returns it as a formatted response to the client. The sequence diagram in Figure 2 illustrates these steps.


Figure 2. Round-trip sequences of a typical HTTP request and service invocation
typical HTTP request and service invocation

The class diagram in Figure 3 illustrates the relationships between the framework's classes.


Figure 3. Relationships between framework classes
Relationships between framework classes

Deploying and running the framework

The framework resides in the business tier of an enterprise application system. The framework exposes one servlet that receives HTTP requests and dispatches the content to the framework for processing. The next section explains the simple deployment process.

Deploy the framework

You can package the classes for the framework and the enterprise application in a .war file and place it within the geronimo_home/deploy directory. If this directory doesn't already exist, create it.

Geronimo deploys the .war file automatically on startup. Applications placed in the deploy directory are hot-loaded, enabling Geronimo to reload the application at run time when you make changes. This makes it convenient for debugging the applications.

Test the framework

You start the Geronimo application server using the startup script (startup.bat or startup.sh) found in the geronimo_home/bin directory. When you invoke the Geronimo startup script, the Geronimo console window becomes visible. After you deploy the framework and the application, Geronimo's console window on startup contains lines similar to those shown in Listing 5, confirming that the Web application has started successfully.


Listing 5. Confirmation the Web application has started successfully
0 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel  -
Starting boot
422 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for: :role=Kernel State changed from stopped to
starting
422 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for: :role=Kernel State changed from starting to
running
422 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel  -
Booted
640 [main] DEBUG com.jeffhanson.apptier.FrontController  - Geronimo
BootTime: Sat May 20 18:51:08 MDT 2006
656 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for: jeffhanson.test:ID=FrontController State
changed from stopped to starting
656 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for: jeffhanson.test:ID=FrontController State
changed from starting to running

Now type the following URL into a Web browser window to instigate the setMessage operation on the HelloWorld service:

http://<host>:<port>/<context>?Action=
HelloWorld&Operation=setMessage&Params=Hello+everybody!



When the framework processes the request, your console output should be similar to that shown in Listing 6.


Listing 6. Output of setMessage operation processing
719 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
Adding service [HelloWorld] to kernel...
719 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
Loading GBean: jeffhanson.test:Name=HelloWorld,Type=GenericService
734 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for:
jeffhanson.test:Name=HelloWorld,Type=GenericService State changed
from stopped to starting
734 [main] DEBUG org.apache.geronimo.gbean.runtime.GBeanInstanceState
- GBeanInstanceState for:
jeffhanson.test:Name=HelloWorld,Type=GenericService State changed
from starting to running

Type the following URL into a Web browser window to instigate the sayHello operation on the HelloWorld service:

http://<host>:<port>/<context>?
Action=HelloWorld&Operation=sayHello



When the framework processes the request, your console output should be similar to that shown in Listing 7.


Listing 7. Output of sayHello operation processing
750 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
serviceObjName: jeffhanson.test:Name=HelloWorld,Type=GenericService
750 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
Service  [HelloWorld] already in kernel
1156 [main] DEBUG com.jeffhanson.businesstier.ServiceLocator  -
serviceObjName: jeffhanson.test:Name=HelloWorld,Type=GenericService
1156 [main] INFO com.jeffhanson.businesstier.services.HelloWorld  -
Hello everybody!

When the servlet engine shuts down the servlet and calls the destroy method on the servlet, the servlet shuts down the Geronimo kernel. When the servlet engine shuts down the servlet, your console output should be similar to that shown in Listing 8.


Listing 8. Output following servlet shutdown
1156 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel  -
Starting kernel shutdown
1156 [main] DEBUG org.apache.geronimo.kernel.basic.BasicKernel  -
Kernel shutdown complete

The HelloWorld class is a simple POJO with a setMessage method, a getMessage method, and a sayHelloWorld message. After you register an instance of this class with the Geronimo kernel, you can invoke the instance dynamically and associate it with other services and components at run time using dependency injection. The code in Listing 9 illustrates the simple HelloWorld POJO class.


Listing 9. A simple HelloWorld service
package com.jeffhanson.businesstier.services;

import org.apache.log4j.Logger;

public class HelloWorld
{
   private static Logger log = Logger.getLogger(HelloWorld.class);

   private String message = "Hello world";

   public void setMessage(String message)
   {
      if (message == null || message.length() <= 0)
      {
         throw new RuntimeException("HelloWorld.setMessage "
                                    + "param is not set");
      }

      this.message = message;
   }

   public String getMessage()
   {
      return message;
   }

   public void sayHello()
   {
      log.info(message);
   }
}


Summary

Designing a nimble and effective SOA that can respond to business domain changes and events in a timely manner is a complex task. However, an SOA built around a properly designed POJO layer can help simplify this task. The Geronimo platform provides frameworks and tools that you can use to build a flexible, scalable, and maintainable SOA using POJOs.



Download

DescriptionNameSizeDownload method
SOA with POJOs frameworkGeronimoSOAwithPOJOs.zip14KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

Discuss

About the author

Jeff Hanson

Jeff Hanson has more than 20 years of experience in the software industry, including work as senior engineer for the Windows OpenDoc project and lead architect for the Route 66 framework at Novell. Jeff is currently the chief architect for eReinsure.com, Inc. and builds Web service frameworks and platforms for Java EE-based reinsurance systems. Jeff is the author of numerous articles and books, including .NET versus J2EE Web Services: A Comparison of Approaches, Pro JMX: Java Management Extensions, and Web Services Business Strategies and Architectures.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source, Java technology, SOA and Web services, WebSphere
ArticleID=144940
ArticleTitle=Build an SOA framework with Apache Geronimo and POJOs
publish-date=07112006
author1-email=jeff@jeffhanson.com
author1-email-cc=ruterbo@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers