Enterprise Integration Zone is brought to you in partnership with:

Ales has posted 6 posts at DZone. View Full User Profile

A Look Inside the JBoss Microcontainer, Part I -- Component Models

10.01.2008
| 49598 views |
  • submit to reddit

Looking at the current state of Java, we can see that POJOs (Plain Old Java Objects) rule the land yet again. Their dominance stretches from enterprise applications to middleware services. At JBoss we were known for our modular JMX-based kernel. The application server was nothing more than a bunch of flexible MBeans and a powerful MicroKernel in the middle. But, as you could feel the change is coming, we still wanted to be ahead of the pack. We could see different POJO based component models popping up all over the place (EJB3, JPA, Spring, Guice, … to name a few), yet nothing was out there that would bind them all, flattening out the differences on a single component model. Hence the Microcontainer project was born.

The JBoss Microcontainer project is about many things. The Microcontainer's features range from reflection abstraction, a virtual file system, a simple state machine to transparent AOP integration, a new classloading layer, a deployment framework and an OSGi framework implementation. I'll try to address them all over a short series of articles that will be published here on DZone. This article will examine the Microcontainer's component models.

Read the other parts in DZone's exclusive JBoss Microcontainer Series:

 

 

What is a component model?

What do we consider a component model? First of all, what do we consider being a component? One abstract way to express this would be that “components are reusable software programs that you can develop and assemble easily to create sophisticated applications.” To consider a bunch of components as an actual model, we also need to declare what kind of interactions we allow.

JMX MBeans are one example of a component model. Their interactions include executing MBean operations, referencing attributes, setting attributes and declaring explicit dependencies between named MBeans.

As mentioned, we had advanced JMX handling already with the MicroKernel. And as expected, the Microcontainer brought extensive POJO support. The default behavior and interactions in the Microcontainer are what you also normally get from any other IoC container and are similar to the functionality that MBeans provided: plain method invocations for operations, setters/getters for attributes and explicit dependencies.

However, having only this functionality would mean we didn't get much further than just relieving the pain of declaring MBeans, hence it was only logical for us to do something more. I'll leave the discussion of these new IoC features for the next article in the series.

There are many existing POJO component models out there, Guice and Spring being amongst the most popular. Effective integration with these frameworks was an important goal for us.

Demo environment setup

Before we begin, I'd like to first describe the various parts that constitute the demo. All the source code can be found at this location of our Subversion repository:

http://anonsvn.jboss.org/repos/jbossas/projects/demos/microcontainer/branches/DZone_1_0/

 

The project is fully mavenized, so it should be easy to adjust it to your IDE.

I will first go over the sub-projects within the demo and describe their usage. At the end of my article series, I will provide a more detailed look at what certain sub-projects do.

Below are the JBoss Microcontainer demos and sub-projects that are relevant for this article:

• bootstrap (as the name suggests, it bootstraps the Microcontainer with demo code)
• jmx (adds the JMX notion to demo's bootstrap)
• models (source code of our components / services)

The demo has only one variable you need to set - demos home - but even this one can be optional if you checked-out your project into the \projects\demos directory. Otherwise, you need to set the system property demos.home (e.g. -Ddemos.home=<my demos home>). You should now be able to run JMXMain as a main class. Make sure you include the models sub-project in the classpath, since some of the services require additional classes in the classpath, several more then what the jmx sub-project expects. Once the Microcontainer is booted it starts to scan the ${demos.home}/sandbox directory for any changes. Now all we need to do is provide a deployable unit and drop it in there.

Models

Let’s now turn our attention to the models sub-project. This is where the previously mentioned deployable unit should come from. You can see if everything is in place by building the models sub-project (mvn package) and dropping it into the sandbox. You should get a bunch of debug and info messages on the console log, showing how the Microcontainer got booted. Any error message indicates some problems.
Let’s go over exactly what the models sub-project does, its integration code and try to redeploy it. If we look at the models src/main/resources/META-INF directory, we'll see plenty of -beans.xml resource files and one -service.xml. You’ll notice that each has a meaningful name that matches the source code package from models's src/main/java/org/jboss/demos/models directory. Let's dissect them one by one, starting with the ones that have no dependencies.

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="PlainPojo" class="org.jboss.demos.models.plain.Pojo"/>

<beanfactory name="PojoFactory" class="org.jboss.demos.models.plain.Pojo">
<property name="factoryClass">org.jboss.demos.models.plain.PojoFactory</property>
</beanfactory>

</deployment>



This is a simple Micrcocontainer beans descriptor file. Anyone who crossed paths with some other IoC’s configuration file should be familiar with it. And, as I already mentioned, I'll follow up on more advanced usage in the next article.

The next file shows what we have done to support Spring integration:

<beans xmlns="urn:jboss:spring-beans:2.0">

<!-- Adding @Spring annotation handler -->
<bean id="SpringAnnotationPlugin" class="org.jboss.spring.annotations.SpringBeanAnnotationPlugin" />

<bean id="SpringPojo" class="org.jboss.demos.models.spring.Pojo"/>

</beans>

 

Note that this file's namespace is different from the previous Microcontainer bean’s plain-beans.xml file. The urn:jboss:spring-beans:2.0 namespace points to our version of the Spring schema port, meaning you can describe your beans Spring style, but it's the Microcontainer that's going deploy then, not Spring's bean factory notion.

public class Pojo extends AbstractPojo implements BeanNameAware
{
private String beanName;

public void setBeanName(String name)
{
beanName = name;
}

public String getBeanName()
{
return beanName;
}

public void start()
{
if ("SpringPojo".equals(getBeanName()) == false)
throw new IllegalArgumentException("Name doesn't match: " + getBeanName());
}
}

 

Although the SpringPojo bean has a dependency on Spring lib via implementing BeanNameAware interface, this dependency is only there to expose and mock some of the Spring's callback behavior (see SpringBeanAnnotationPlugin for more details).

Since we introduced Spring integration, let's have a look at Guice integration. As Guice users know, Guice is all about type matching. Configuration of Guice beans is done via Modules which means that in order to generate beans, one must implement a Module.

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="GuicePlugin" class="org.jboss.guice.spi.GuiceKernelRegistryEntryPlugin">
<constructor>
<parameter>
<array elementClass="com.google.inject.Module">
<bean class="org.jboss.demos.models.guice.PojoModule"/>
</array>
</parameter>
</constructor>
</bean>

</deployment>

 

Two important parts to watch from this file are PojoModule and GuiceKernelRegistryEntryPlugin. The first one is where we configure our beans:

public class PojoModule extends AbstractModule
{
private Controller controller;

@Constructor
public PojoModule(@Inject(bean = KernelConstants.KERNEL_CONTROLLER_NAME) Controller controller)
{
this.controller = controller;
}

protected void configure()
{
bind(Controller.class).toInstance(controller);
bind(IPojo.class).to(Pojo.class).in(Scopes.SINGLETON);
bind(IPojo.class).annotatedWith(FromMC.class).toProvider(GuiceIntegration.fromMicrocontainer(IPojo.class, "PlainPojo"));
}
}

 

The second class provides integration with the Microcontainer:

public class GuiceKernelRegistryEntryPlugin implements KernelRegistryPlugin
{
private Injector injector;

public GuiceKernelRegistryEntryPlugin(Module... modules)
{
injector = Guice.createInjector(modules);
}

public void destroy()
{
injector = null;
}

public KernelRegistryEntry getEntry(Object name)
{
KernelRegistryEntry entry = null;
try
{
if (name instanceof Class<?>)
{
Class<?> clazz = (Class<?>)name;
entry = new AbstractKernelRegistryEntry(name, injector.getInstance(clazz));
}
else if (name instanceof Key)
{
Key<?> key = (Key<?>)name;
entry = new AbstractKernelRegistryEntry(name, injector.getInstance(key));
}
}
catch (Exception ignored)
{
}
return entry;
}
}

 

Notice how we created an Injector from the Modules and then did a lookup on it for matching beans.
In mbeans-service.xml we declare our legacy usage of MBeans:

<server>

<mbean code="org.jboss.demos.models.mbeans.Pojo" name="jboss.demos:service=pojo">
<attribute name="OtherPojo"><inject bean="PlainPojo"/></attribute>
</mbean>

</server>

 

What’s interesting to note here is how we injected a POJO into an MBean. The preceding demonstrated our first interactions between different component models.

In order to allow for MBean deployment via the Microcontainer, we had to write entirely new component model handling code. See the system-jmx-beans.xml for more details. The code from this file lives in the JBossAS source code: system-jmx sub-project. One note here, this is currently only possible with JBoss's JMX implementation, since the system-jmx code uses some implementation details.

Now what if we wanted to expose our existing POJOs as MBeans, registering them into an Mbean server?

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="AnnotatedJMXPojo" class="org.jboss.demos.models.jmx.AtJmxPojo"/>

<bean name="XmlJMXPojo" class="org.jboss.demos.models.mbeans.Pojo">
<annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(exposedInterface=org.jboss.demos.models.mbeans.PojoMBean.class, registerDirectly=true)</annotation>
</bean>

<bean name="ExposedPojo" class="org.jboss.demos.models.jmx.Pojo"/>

<bean name="AnnotatedExposePojo" class="org.jboss.demos.models.jmx.ExposePojo">
<constructor>
<parameter><inject bean="ExposedPojo"/></parameter>
</constructor>
</bean>

</deployment>

 

As you can see from looking at any of the beans in this file, in order to expose your POJOs as MBeans, it’s simply a matter of annotating them with an @JMX annotation. You can either expose the bean directly or its property:

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="XMLLoginConfig" class="org.jboss.demos.models.old.XMLLoginConfig"/>

<bean name="SecurityConfig" class="org.jboss.demos.models.old.SecurityConfig">
<property name="defaultLoginConfig"><inject bean="XMLLoginConfig"/></property>
</bean>

<bean name="SecurityChecker" class="org.jboss.demos.models.old.Checker">
<property name="loginConfig"><inject bean="jboss.security:service=XMLLoginConfig"/></property>
<property name="securityConfig"><inject bean="jboss.security:service=SecurityConfig"/></property>
</bean>

</deployment>

 

Here we see how you can use any of the injection lookup types by either looking up a plain POJO or getting a handle to an MBean from the MBean server.

One of the injection options is to use type injection, which is also sometimes called autowiring:

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<bean name="FromGuice" class="org.jboss.demos.models.plain.FromGuice">
<constructor><parameter><inject bean="PlainPojo"/></parameter></constructor>
<property name="guicePojo"><inject/></property>
</bean>

<bean name="AllPojos" class="org.jboss.demos.models.plain.AllPojos">
<property name="directMBean"><inject bean="jboss.demos:service=pojo"/></property>
<property name="exposedMBean"><inject bean="jboss.demos:service=ExposedPojo"/></property>
<property name="exposedMBean"><inject bean="jboss.demos:service=ExposedPojo"/></property>
</bean>

</deployment>

 

The FromGuice bean injects the Guice bean via type matching, where PlainPojo is injected with a common name injection. We then test if Guice binding works as expected:

public class FromGuice
{
private IPojo plainPojo;
private org.jboss.demos.models.guice.Pojo guicePojo;

public FromGuice(IPojo plainPojo)
{
this.plainPojo = plainPojo;
}

public void setGuicePojo(org.jboss.demos.models.guice.Pojo guicePojo)
{
this.guicePojo = guicePojo;
}

public void start()
{
f (plainPojo != guicePojo.getMcPojo())
throw new IllegalArgumentException("Pojos are not the same: " + plainPojo + "!=" + guicePojo.getMcPojo());
}
}

 

This only leaves us with an alias component model. Even though the alias is quite a trivial feature, in order to implement it as a true dependency, it has to be introduced as a new component model inside the Microcontainer. The implementation details for this is part of the AbstractController source code:

<deployment xmlns="urn:jboss:bean-deployer:2.0">

<alias name="SpringPojo">springPojo</alias>

</deployment>

 

Here we’ve mapped the SpringPojo name to the springPojo alias. The beauty of having aliases as true component models is that it doesn't matter when the real bean gets deployed. This means that the alias will wait in a non-installed state until the real bean triggers it.

Conclusion

We've seen how we can deploy simple Microcontainer beans, legacy MBeans, Guice POJOs, Spring beans and aliases. And since all of this is controlled by the Microcontainer, we saw how easily we can mix and match the different component models.

I can easily say, with the level of abstraction we put in our component model design, the sky is the limit on what we can handle. An example of this is the upcoming OSGi services, but that's another story, another article.

Stayed tuned for my next article which will provide a detailed look at the Microcontainer's IoC functionality.

 

About the Author

Ales Justin was born in Ljubljana, Slovenia and graduated with a degree in mathematics from the University of Ljubljana. He fell in love with Java seven years ago and has spent most of his time developing information systems, ranging from customer service to energy management. He joined JBoss in 2006 to work full time on the Microcontainer project, currently serving as its lead. He also contributes to JBoss AS and is Seam and Spring integration specialist. He represent JBoss on 'JSR-291 Dynamic Component Support for Java SE' and 'OSGi' expert groups.

 

Published at DZone with permission of its author, Ales Justin.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Peter Veentjer replied on Thu, 2008/10/02 - 3:09am

Good to see that the project is still alive. But if you go to the website

http://www.jboss.com/products/jbossmc

and check the news history:

News

 That would suggest that the project is not very alive.

 Since another well know IOC container changed their strategy I'm looking at other containers.

Peter Veentjer replied on Thu, 2008/10/02 - 4:17am

It appears that the sites are a littlebit out of sync. But good to see that there is another IOC container that is developed and used in various products.

Leo de Blaauw replied on Thu, 2008/10/02 - 4:30am

Hey,

The projects where transferred to jboss.org some time ago if i remember correctly. So jboss.org would be

the place for most if not all previously under the jboss.com developed projects.

Regards,
Leo

Oliver Plohmann replied on Thu, 2008/10/02 - 6:04am in response to: Leo de Blaauw

In addition to not-developed-here syndrom now we also have older-than-6-months syndrom ... ;-).

Ales Justin replied on Thu, 2008/10/02 - 8:00am

@ Peter

 The  project is more than alive. ;-)

And I agree with you, we definitely need to fix those links.

But like Leo says, check our .org site.

And since MC is all fully mavanized, the best/simplest way  to use it is via maven.

Check the demo site on how it's done.

 

@ Leo

Thanks for pushing the info. :-)

 

@ Oliver

 NDH?

The point of MC is here: " We could see different POJO based component models popping up all over the place (EJB3, JPA, Spring, Guice, … to name a few), yet nothing was out there that would bind them all, flattening out the differences on a single component model. Hence the Microcontainer project was born."

;-)

Henri Gomez replied on Sun, 2008/12/07 - 10:07am

Now that JBoss 5.0 is out, It will be nice to update the pom.xml with the up to date dependencies :)

I started on my side but it will be better from the article author.

  <properties>
    <version.jboss.jbossas>5.0.0.GA</version.jboss.jbossas>
    <version.jboss.man>2.0.0.GA</version.jboss.man>
    <version.jboss.mdr>2.0.1.GA</version.jboss.mdr>
    <version.jboss.microcontainer>2.0.2</version.jboss.microcontainer>
    <version.jboss.deployers>2.0.3</version.jboss.deployers>
    <version.jboss.classloader>2.0.1.GA</version.jboss.classloader>
    <version.jboss.common.core>2.2.10.GA</version.jboss.common.core>
    <version.jboss.common.logging.spi>2.0.5.GA</version.jboss.common.logging.spi>
    <version.jboss.common.logging.log4j>2.0.5.GA</version.jboss.common.logging.log4j>
    <version.jbossxb>2.0.0.GA</version.jbossxb>
    <version.jboss.aop>2.0.0.SP1</version.jboss.aop>
    <version.jboss.vfs>2.0.0.GA</version.jboss.vfs>
    <version.org.jboss.test>1.0.5.GA</version.org.jboss.test>
    <version.junit>4.4</version.junit>
    <version.javassist>3.9.0.GA</version.javassist>
    <version.xerces>2.9.1</version.xerces>
    <version.spring>2.5.5</version.spring>
  </properties>

 Great works on this mc

Ales Justin replied on Sun, 2008/12/07 - 10:21am in response to: Henri Gomez

[quote=hgomez]

Now that JBoss 5.0 is out, It will be nice to update the pom.xml with the up to date dependencies :)

I started on my side but it will be better from the article author.

[/quote]

Yeah, forgot to update the branch.

Thanks for reminding me, will do it right now.

But I was updating the trunk constantly. :-)

 

Henri Gomez replied on Sun, 2008/12/07 - 11:02am

The correct versions in pom are :

 

  <properties>
    <version.jboss.jbossas>5.0.0.GA</version.jboss.jbossas>
    <version.jboss.man>2.0.0.GA</version.jboss.man>
    <version.jboss.mdr>2.0.1.GA</version.jboss.mdr>
    <version.jboss.microcontainer>2.0.2.GA</version.jboss.microcontainer>
    <version.jboss.deployers>2.0.3.GA</version.jboss.deployers>
    <version.jboss.classloader>2.0.1.GA</version.jboss.classloader>
    <version.jboss.common.core>2.2.10.GA</version.jboss.common.core>
    <version.jboss.common.logging.spi>2.0.5.GA</version.jboss.common.logging.spi>
    <version.jboss.common.logging.log4j>2.0.5.GA</version.jboss.common.logging.log4j>
    <version.jbossxb>2.0.0.GA</version.jbossxb>
    <version.jboss.aop>2.0.0.SP1</version.jboss.aop>
    <version.jboss.vfs>2.0.0.GA</version.jboss.vfs>
    <version.org.jboss.test>1.0.5.GA</version.org.jboss.test>
    <version.junit>4.4</version.junit>
    <version.javassist>3.9.0.GA</version.javassist>
    <version.xerces>2.9.1</version.xerces>
    <version.spring>2.5.5</version.spring>
  </properties>

Regards

Henri Gomez replied on Sun, 2008/12/07 - 11:05am

BTW, will you update samples with OSGI support, I'm very interesting in seing it in action.

Ales Justin replied on Sun, 2008/12/07 - 3:10pm

[quote=hgomez]The correct versions in pom[/quote]

Did I miss some version?

Ales Justin replied on Sun, 2008/12/07 - 3:09pm in response to: Henri Gomez

[quote=hgomez]BTW, will you update samples with OSGI support, I'm very interesting in seing it in action.[/quote]

It's on the articles road-map.

But I need to go step by step,

introducing things (sub-projects / features) in the order of dependency.

 

Henri Gomez replied on Sun, 2008/12/07 - 4:38pm in response to: Ales Justin

Nope,  I updated my modified pom.xml, just see you allready updated trunk.

 BTW, I used 2.2.10.GA for commo core

<version.jboss.common.core>2.2.10.GA</version.jboss.common.core>

Regards

Henri Gomez replied on Sun, 2008/12/07 - 4:44pm in response to: Ales Justin

I take a look in the osgi module see no pom.xml.

Taking a look at jbossmc trunk, I also notice that osgi pom may be not up to date.

http://anonsvn.jboss.org/repos/jbossas/projects/jboss-osgi/trunk/pom.xml

  <properties>
<version.jboss.microcontainer>2.0.0.CR1</version.jboss.microcontainer>
<version.jboss.deployers>2.0.0.CR1</version.jboss.deployers>
<version.jboss.common.core>2.2.8.GA</version.jboss.common.core>
<version.jboss.logging.spi>2.0.5.GA</version.jboss.logging.spi>
<version.jboss.logging.log4j>2.0.5.GA</version.jboss.logging.log4j>
<version.osgi.r4.core>1.0</version.osgi.r4.core>
<version.jboss.aop>2.0.0.CR17</version.jboss.aop>
<version.org.jboss.test>1.0.5.GA</version.org.jboss.test>
<version.junit>4.4</version.junit>
</properties>

 So my wonder about JBoss MC OSGI support.

Cheers

Ales Justin replied on Mon, 2008/12/08 - 5:38am in response to: Henri Gomez

[quote=hgomez]So my wonder about JBoss MC OSGI support.

 

[/quote]

It need some code love. ;-)

I'll pick up the pace now, with JBoss5.0.0.GA out.

Henri Gomez replied on Wed, 2008/12/10 - 6:58am

Hi to all

 I do the mvn clean package and got all the jars.

Started the bootstrap demo from eclipse after added guice/spring to classpath runtime in pom via :

     <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <scope>runtime</scope>
      <version>2.5.6</version>
    </dependency>
    
    <dependency>
      <groupId>com.google.code.guice</groupId>
      <artifactId>guice</artifactId>
      <scope>runtime</scope>
      <version>1.0</version>
    </dependency>
    
Drop the models jars in sandbox but got the following error:

Using bootstrap: file:/C:/workspace-34/jboss-demos/bootstrap/src/main/resources/META-INF/bootstrap-beans.xml
log4j:WARN No appenders could be found for logger (org.jboss.kernel.KernelFactory).
log4j:WARN Please initialize the log4j system properly.
Scan failed: org.jboss.deployers.client.spi.IncompleteDeploymentException: Summary of incomplete deployments (SEE PREVIOUS ERRORS FOR DETAILS):

*** CONTEXTS IN ERROR: Name -> Error

vfszip:/C:/workspace-34/jboss-demos/sandbox/jboss-demos-models.jar -> org.jboss.xb.binding.JBossXBRuntimeException: Failed to resolve schema nsURI=urn:jboss:spring-beans:2.0 location=beans


Scan failed: org.jboss.deployers.client.spi.IncompleteDeploymentException: Summary of incomplete deployments (SEE PREVIOUS ERRORS FOR DETAILS):

*** CONTEXTS IN ERROR: Name -> Error

vfszip:/C:/workspace-34/jboss-demos/sandbox/jboss-demos-models.jar -> org.jboss.xb.binding.JBossXBRuntimeException: Failed to resolve schema nsURI=urn:jboss:spring-beans:2.0 location=beans
 

 

Ales Justin replied on Wed, 2008/12/10 - 7:13am in response to: Henri Gomez

[quote=hgomez]vfszip:/C:/workspace-34/jboss-demos/sandbox/jboss-demos-models.jar -> org.jboss.xb.binding.JBossXBRuntimeException: Failed to resolve schema nsURI=urn:jboss:spring-beans:2.0 location=beans
[/quote]

You need to run JMXMain with models's classpath.

See model/pom.xml, it already includes Spring + MC-Spring-int, Guice + Guice-int.

Ales Justin replied on Thu, 2008/12/11 - 12:27pm

It looks like my libs upgrade broke aop-beans.xml. :-(

It's fixed now. :-)

Eric Chen replied on Mon, 2010/09/06 - 3:17am

Hi Ales Justin,

I am so appreciated to read this article!

It's so great! I have already read it twice!

The architecture is so amazing,I think!

But,Could you please send me an email and tell me how to make a application which is embeded into jboss server just like your demo code that can be running without jboss app sever,but is using many tools in Jboss?

Many many many thanks for your attention!!!!!!!

Tire Works replied on Tue, 2011/04/26 - 7:15am in response to: Eric Chen

But,Could you please send me an email and tell me how to make a application which is embeded into jboss server just like your demo code that can be running without jboss app sever,but is using many tools in Jboss?

 @Eric Chen Just Google this and you will find an answer, listing #2 looks trustworthy and accurate. - Tire Works Staff

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.