Thursday, January 28, 2010

JMX Portable Extension for CDI

CDI (Contexts and Dependency Injection) is a new standard that makes application development easier by providing type safety dependency injection, scope binding (request, session, application, etc.) and contextual lifecycle management of Java components. It also  exposes a powerful SPI (Service Provider Interface) to extend its functionality through portable extensions.

JMX (Java Management Extensions) provides a consistent, well defined interface to monitor and manage your applications by exposing objects (MBeans) through an MBeanServer. Currently, there are two ways to expose an object as an MBean: you can either provide an interface of your class, in which case, you won’t be able to add textual descriptions for your exposed fields and methods; or you can implement javax.management.DynamicMBean, which is cumbersome and difficult to maintain.

JSR-255, the JMX specification 2.0, is an initiative that will make the writing of MBeans easier through annotations. However, by the time of this writing, the JSR is inactive as stated here.

I’ve decided to write my first own portable extension that will allow you to expose any object automatically or manually through JMX by just adding some simple annotations. You can download the complete code from here.

Let’s take a look at the following example:

When the bean is instantiated by CDI, a dynamic MBean is created and registered on an MBeanServer to expose the attributes and methods annotated with @ManagedAttribute and @ManagedOperation respectively. You can then use any JMX Agent Viewer to monitor and manage your code.

jmx-view 
Figure 1. JBoss AS JMX Console. A view of an MBean.

You don’t have to worry anymore about obtaining an MBeanServer, registering the MBean and unregistering it. This is all done automatically for you. It’s a simple way of instrumenting your code without writing complex and uneven administration interfaces!

Creation and registration of the MBean is done when the bean is instantiated by CDI, not on startup. If you want the MBean to be registered on startup, you will have to annotate your class with the @Singleton and @Startup annotations.

If you don’t want the object to be automatically registered on instantiation but still want to register it yourself later in the code, you can set the autoRegister property of the @MBean to false. To register your object programmatically, you use the MBeanFactory service to create a DynamicMBean instance, and then register it to an MBeanServer. For example:

You can even expose objects that are not annotated with @MBean. In this case, all fields and methods from the class are exposed. Any @ManagedAttribute or @ManagedOperation annotations will be ignored.

CDI Integration

Writing the portable extension was pretty straightforward. First, I created a class org.gescobar.management.cdi.ManagementExtension that extends javax.enterprise.inject.spi.Extension with a method to observe the ProcessInjectionTarget event:

Basically, what we are doing here is replacing the InjectionTarget with a wrapper class that will register and unregister the MBean if the @MBean annotation is present and autoRegister is true

To register the portable extension, I created a file called javax.enterprise.inject.spi.Extension with only one line:

Testing

I used TestNG and Arquillian to write and execute the tests inside a remote JBoss AS 6.0.0.M1 container. One of the tests looks like this:

Arquillian is a JBoss project for running tests on different containers. By the time of this writing, it hasn’t been release but you can download the code from SVN and build it using Maven 2.

What’s next?

It would be nice to support the following:

  • Automatic and manual registration of MBeans for JBoss Seam.
  • Manual registration of MBeans in any J2SE environment.
  • @ManagedAttribute annotation on methods that return information.
  • Name for operation parameters.
  • Notifications using annotations.
  • Message keys from resource bundles for descriptions.

You can check the project on Google Code here. Please, feel free to download it and give it a try!

Sunday, January 17, 2010

From JBoss Seam to CDI (JEE6)

Seam is a popular open source application framework that has led to the creation of CDI (Contexts and Dependency Injection), a specification that is now part of the JEE 6 ecosystem. In this post I’ll show you the architectural similarities and differences between both and how Seam has influenced CDI. So lets start!

Contexts

Contexts are definitely one of the most exciting features of Seam (you can read more about them in this post) and remain in the core of CDISeam defines six stateful contexts: request (event), session, application, page, conversation and business process context. CDI only define 4, leaving page and business process contexts out. However, CDI allows you to define new contexts which was not possible in Seam. You can see an example of creating a context (the equivalent of the page context in Seam) by Steven Verborgh here.

Additionally, CDI now defines a new “dependent” context which allows a bean to have the same context as the bean that declares it. They will share the same lifecycle meaning that “it [the dependent bean] is instantiated when the object it belongs to is created and destroyed when the object it belongs is destroyed”, as stated in the Weld documentation.

Dependency Injection

Even though Seam and CDI both make heavy use of the Dependecy Injection pattern, they take different approaches to implement it. The most notable differences are the following (I’ll explain each one in more detail below):

  • Seam uses a string-based approach to search for components which is not type safe while CDI brings type safety to the limit.
  • Seam uses dynamic injection while CDI uses static injection.

Type safety

In Seam, every component has a name defined by the @Name annotation. When an injection occurs, Seam searches for the name of the component which can lead to runtime exceptions. For example, suppose you have the following component:

@Name("myBean")
public class MyBean {
 ...
}

Now, suppose you mistakenly inject MyBean into a String like this:

@In
private String myBean;

This will compile just fine, but at runtime you will get an exception. In large applications, this is a problem as you will potentially have a lot of bugs at runtime, something you really want to avoid.

CDI implements dependency injection based on the type of the bean like in Google Guice. There is no need to name a bean unless you want to access it from EL, in which case, you will need to annotate your bean with the @Named annotation. Lets look at a simple case of injection in CDI:

public class Bean1 {
 ...
}

public class Bean2 {
 @Inject
 private Bean1 bean1;
 ...
}

When Bean2 gets instantiated, Bean1 will be injected on Bean2. As you can see, there is no need to name the beans.

Static vs. Dynamic Injection

In Seam, injection occurs on each method call. After the method completes, all injected values are desinjected (set to null). This is known as dynamic injection and it has its benefits and drawbacks. The most outstanding benefit is that you can inject components from different contexts (i.e. a request component injected in a conversation component)  and you will always have the “correct” instance on each method call. However, dynamic injection has some problems including performance and null values on concurrency.

CDI uses static injection, meaning that all the values are injected on the creation of the bean and they are not desinjected between method calls. To handle injection of beans from different contexts, it uses proxies that reference the “correct” instance of each bean. A much more elegant solution in my opinion.

Factories

Remember the @Factory annotation in Seam? It allows you to obtain objects that are not Seam components; or it could also be used when you need to perform some custom initialization on a component before returning it. In CDI, there is an equivalent functionality called “producer method”:

@Produces
public User getUser {
      ...
}

Every time a User object is injected, this method will be called to obtain a reference. CDI provides a simpler alternative to a producer method called a producer field:

@Produces
private User user;

Events

In Seam, you can decouple your components using events. Each event must have a name. You can raise an event using the @Raise(“<name_of_event>”) annotation or programmatically using the Events.instance().raiseEvent(“<name_of_event>”) method. To observe for an event, you mark the method you want to be called on the event with the @Observer(“<name_of_event>”) annotation.

CDI grabs this concept from Seam and makes it type safe. So, for raising an event we can obtain an Event object by injection:

@Inject
private Event<User> userEvent;

And then call the fire method on the Event object:

userEvent.fire(user);

Now, for observing an event you use the @Observes annotation:

public void observeUserEvent(@Observes User user) {
 ...
}

Interceptors

Seam relies heavily on interceptors for injection, security, persistence and much more. CDI also provides an interception facility called interceptors bindings, based on the Java Interceptors specification. Furthermore, CDI provides the concept of “decorator”, which is a kind of interceptor for implementing the decorator pattern.

Wrapping up

Let’s take a look at the services provided by CDI and see if they were inspired by Seam:

  • Contexts: heavily inspired by Seam.
  • Dependency Injection: mostly inspired by Google Guice but we have an equivalent in Seam (which is not type safe).
  • EL integration (the #{} notation): completely inspired by Seam.
  • Interceptors: completely inspired by Seam.
  • Events: heavily inspired by Seam but type safe.

Wait a minute! Are these all the services provided by CDI? What about all the out-of-the-box functionality I used to have in Seam (page flows, business process integration, security, scheduling, caching, remoting, etc.)? Don’t worry! Portable Extensions, the only service we are missing in this list, will solve this question, so just keep reading!

Portable Extensions and Seam 3

Besides the services described above, CDI provides a powerful SPI (Service Provider Interface) you can use to create extensions (called Portable Extensions in CDI). This is where Seam 3 enters the game!

Seam 3 will be a set of portable extensions that will provide almost all of the out-of-the-box functionality you actually have in Seam 2. At the time of this writing, Seam 3 is on its first steps and there is no official release yet. However, you can start developing your own portable extensions on top of CDI. Take a look at this post by Matt Corey to start writing your own first portable extension!

Conclusion

CDI has been heavily influenced by Seam with two major architectural changes:

  • Instead of providing everything out-of-the-box as Seam, CDI provides a set of core technologies and a powerful SPI that will enable any one write its own portable extensions.
  • Type safety. This was included in every aspect of CDI (Contexts, DI and events), except for the EL integration.

Remember that Seam is a framework and CDI is a specification (Weld is the Reference Implementation). For more information on CDI, check the Weld documentation and the CDI specification.