Doing Two Models at the Same Time


We used to throw the best parties in our Coolidge Corner[1] bachelor pad.  The recipe was simple: we’d blast an eVite to the city of Boston, pick up a keg of Good Decision[2], break out the Beirut[3] table, and ask the local police to turn a blind eye.

In the midst of one of our more smashing affairs, conversation turned to concurrent polygamy and if any of us were fortunate enough to have practiced the art firsthand.

Josh had.  Of course, Josh had.

And he offered us this advice: “You don’t go looking for it.  It’s given to you, so don’t ask questions and just take advantage of the opportunity.”

Don’t you know it, opportunity knocked upon my roommate Jon’s door not three hours later.  With a couple of part-time models.  Two models at the same time.

While the next morning’s brunchtime report was entertaining enough, my inner geek preferred to explore how some of the same themes might be applied to component architecture.

Models:
* Are not necessarily mutually exclusive
* Should be encouraged to focus on their own domains
* May share in some concerns, each from a different angle
* Combined are worth more than the sum of their parts

Shoot forward a few years, when an enabling technology caught up with my musings in the form of JBoss Microcontainer[4].

My first impression of MC was that it was “another DI Container”.  And at its core, sure, it provides the kind of POJO autowiring that we’ve come to expect from this class of framework.  Over the past year, however, I’ve come to appreciate MC for its extensibility, a truly differenciating characteristic from other offerings.

DI is all very nice, but I’m accustomed to having some greater utilities available to create my runtime environment.  A quick glance at the MC feature list boasts Virtual Deployment Framework (VDF), a filesystem abstraction (VFS) and aspectized classloading facilities.  Armed with these, I was set to kick the tires in hopes of discovering some deficiencies in the design and thus gaining bragging rights over Ales[5].

Mission: Provide @EJB injection into MC Beans

In short, I want MC Beans to be able to inject references to EJB3 proxies.  This will be our integration point for interacting with EJB from MC-based Services.

MC applies a metadata-collecting vistor to beans that are installed, and this is passed along to an AnnotationPlugin[6] whose responsibility is to apply the requisite info to the visitor.  By implementing an AnnotationPlugin to handle javax.ejb.EJB, we’ve got our hook[7].  This process is eased by abstract support from FieldAnnotationPlugin, and the main goal here is to supply a ValueMetaData describing the injection value.:

/**
* Create @EJB value meta data.
*
* @param annotation
* @return @EJB metadata
*/
@Override
protected ValueMetaData createValueMetaData(FieldInfo propInfo, EJB annotation)
{
// Get properties from the annotation
String beanName = annotation.beanName();
String beanInterface = annotation.beanInterface().getName();
String mappedName = annotation.mappedName();
// Supply beanInterface from reflection if not explicitly-defined
if (beanInterface == null || beanInterface.equals(Object.class.getName()))
{
String reflectType = propInfo.getType().getName();
beanInterface = reflectType;
}
// Create a reference
EjbReference reference = new EjbReference(beanName, beanInterface, mappedName);
log.debug("Found @EJB reference " + reference);
// Return a new ValueMetaData w/ the reference
return new AbstractEjbReferenceValueMetadata(this.getResolver(), reference, this.getNamingContext());
}

The “EjbReference” above is a value object used by the EJB3 Reference Resolver, responsible for finding the JNDI Name to which a reference is bound.

The return value is AbstractEjbReferenceValueMetadata[8], an implementation of ValueMetaData able to:

1) Declare a dependency upon the JNDI target value.  This ensures our MC Bean will not deploy until the referenced EJB has
2) Obtain the EJB Proxy from JNDI so that it may be injected

Simple enough.

From here, the only thing left to do is let MC know that it should consider our new AnnotationPlugin upon installation of new beans.  For this task I’ll create a simple POJO[9] which, installed, will alter MC’s behaviour.  The key here is in the lifecycle “@Start”:
@Start
public void start() throws Exception
{
// Install the BeanAnnotationAdapter w/ callback to add annotation plugins on install
BeanAnnotationAdapter beanAnnotationAdapter = BeanAnnotationAdapterFactory.getInstance()
.getBeanAnnotationAdapter();
String beanAnnotationAdapterBindName = MC_NAMESPACE_EJB3 + "BeanAnnotationAdapter";
BeanMetaDataBuilder bmdb = BeanMetaDataBuilder.createBuilder(beanAnnotationAdapterBindName, beanAnnotationAdapter
.getClass().getName());
bmdb.addMethodInstallCallback("addAnnotationPlugin");
bmdb.addMethodUninstallCallback("removeAnnotationPlugin");
try
{
this.getKernel().getController().install(bmdb.getBeanMetaData(), beanAnnotationAdapter);
}
catch (Throwable e)
{
throw new RuntimeException("Could not install " + beanAnnotationAdapter, e);
}
}

Here we get at the BeanAnnotationAdapter and install it into the KernelController along with some callbacks to automatically add AnnotationPlugins when they, in turn, are installed.  From here on out, all we need is to throw EjbReferenceAnnotationPlugin into MC.

I’ve tracked this feature[10], along with passing integration tests in the EJB3 TestSuite[11].

Unfortunately, I’m left with nothing to hold aver Ales’ head as MC provided me, as a framework developer, with all the tools needed to extend the provided groundwork.  In fact, I’m even at a deficit because I needed to consult the Microcontainer Users’ Forum[12] for some suggestions.

I’d like some input from application developers – in what situations would you like to call an EJB from a POJO?  Managed objects within Microcontainer act as singletons within the confines of the system, so there should be plenty of occasions to call upon a pooled/cached distributed component.  This is the goal we address by providing integration between component models.

Because nothing catches on without a proper title, I’ll name our approach right now: Concurrent Polyforma.

So now we’ve put JBoss MC to a real-world test, proving that it can wrap your favorite model.  As an additional exercise, I also did this quite literally:

Caylin Loves MC

Caylin Loves MC

This is how we’ll help you bridge two models.  You just can’t Eiffel Tower[13] them.

S,
ALR

[1] http://en.wikipedia.org/wiki/Coolidge_Corner
[2] http://www.beeripedia.com/index.php/Samuel_Adams
[3] http://en.wikipedia.org/wiki/Beer_Pong
[4] http://www.jboss.org/jbossmc/
[5] http://www.jboss.org/community/people/alesj
[6] http://anonsvn.jboss.org/repos/jbossas/projects/microcontainer/trunk/kernel/src/main/java/org/jboss/kernel/plugins/annotations/AnnotationPlugin.java
[7] http://anonsvn.jboss.org/repos/jbossas/projects/ejb3/trunk/mc-int/src/main/java/org/jboss/ejb3/mcint/metadata/plugins/EjbReferenceAnnotationPlugin.java
[8] http://anonsvn.jboss.org/repos/jbossas/projects/ejb3/trunk/mc-int/src/main/java/org/jboss/ejb3/mcint/metadata/plugins/AbstractEjbReferenceValueMetadata.java
[9] http://anonsvn.jboss.org/repos/jbossas/projects/ejb3/trunk/mc-int/src/main/java/org/jboss/ejb3/mcint/annotationadaptor/AddAnnotationPluginOnBeanAnnotationAdaptorCallbackService.java
[10] https://jira.jboss.org/jira/browse/EJBTHREE-1624
[11] http://anonsvn.jboss.org/repos/jbossas/projects/ejb3/trunk/testsuite/src/test/java/org/jboss/ejb3/test/ejbthree1624/
[12] http://www.jboss.com/index.html?module=bb&op=viewforum&f=228
[13] http://www.urbandictionary.com/define.php?term=eiffel%20tower&defid=1242963

~ by ALR on December 20, 2008.

6 Responses to “Doing Two Models at the Same Time”

  1. Great stuff. JBossMC desperately needs more documented use-cases like this.

  2. Perhaps a missing detail that gave you problems as well is the no-fields by default.
    Meaning one must change BeanAccessMode –> FIELDS or ALL.

    But otherwise it looks great! ;-)

  3. Only the one and only ALR could combine an EJB3 post with an urban dictionary link and come out making sense.

    Hit me up by email, you’ve got no contact info on your site.

    CKC lives on

  4. You have an odd way of making a point my friend.

  5. You ask what would I do with this?

    I have a need to build a corba server in jboss as a replacement for an existing standalone corba server as java application. I’ll implment a corba servant (which implements the corba interface) as a facade, which delegates to local ejb session bean (where the real meat of the replacement will be implemented). I think the best way to implement a servant in jboss is to implement a microcontainer pojo.

    It doesn’t look like microcontainer would inject the ejb proxy as part of the jboss-beans.xml file, as in: . That would be too easy, I guess.

    So, I’m left with doing two models at the same time. The corba servant would declare a field with the @EJB annotation. And the code above would cause it to be injected. I don’t understand enough about the microcontainer, but from what I see so far, I think it would be simpler if my corba servant simply did a lookup against an InitialContext for the ejb.

    Thanks for the article.

  6. I REMEMBER THAT NIGHT!!! hahaha. have nooooo idea about anything after the 3rd paragraph, but yes, those were amazing parties ;) making one final trip to beantown in 2 weekends before retreating to the islands for good this time. hopefully i can catch up with you and cay? miss you both… xo

Leave a Reply