Using InitialContext for Inversion of Control in Java

If I were to try to apply my approach to IofC in C++ to Java, the logical starting point is the JNDI Context object.  In JNDI, to get an instance of an object, you call InitialContex.doLookup(String name); Which allows you to set a Generic type parameter to make sure that Casting is handled for you.    This is really close to what I want.  Also, When you request an object by name, what you have registered is either an instance of that object (via the InitialCOntext.bind method) or it calls a factory to create the instance, and the Factory gets registered earlier.  So far, we are in the right vicinity.

I’ve been doing some Tomcat work recently, so I’ll use that as a starting point. The JNDI implementation embedded in Tomcat is an apache project with the top level package name of org.apache.naming.  The InitialContext object is actually a participant in a Bridge design pattern.  Specifically, the user creates an InitialContext, and that will call a factory to create an Context object to use internally. Apache Naming creates an instance of org.apache.naming.NamingContext.  The interesting code is here

protected Object lookup(Name name, boolean resolveLinks)
throws NamingException {

// Removing empty parts
while ((!name.isEmpty()) && (name.get(0).length() == 0))
name = name.getSuffix(1);
if (name.isEmpty()) {
// If name is empty, a newly allocated naming context is returned
return new NamingContext(env, this.name, bindings);
}

NamingEntry entry = (NamingEntry) bindings.get(name.get(0));

if (entry == null) {
throw new NameNotFoundException
(sm.getString(“namingContext.nameNotBound”, name.get(0)));
}

We don’t really care what comes after this.  The point is that if the NamingEntry is not in the locally defined set of names, it does not know how to create the instance, and throws and exception.

What would happen if we turn this assumption on its head.  What if the failure to resolve a name just meant that the context factory should delegate it to the next context factory in the chain.  We could restrict this approach to a certain naming scheme.  If the name give falls inside a new scheme, say java:comp/chain/<classname>, use a chain of responsibility to walk the Contexts back up toward to the root to resolve the object.

The concept of lookupLink as  the default way to fetch something is intriguing.  It means that there is some method of chaining available.  Right now the only things that get resolved are the links that are explicitly put into the namespace.  Immediately following the code quoted above is:

if (name.size() > 1) {
// If the size of the name is greater that 1, then we go through a
// number of subcontexts.
if (entry.type != NamingEntry.CONTEXT) {
throw new NamingException
(sm.getString(“namingContext.contextExpected”));
}
return ((Context) entry.value).lookup(name.getSuffix(1));

Beware that there are two trees here.  the  naming tree, and  scopes of resolution.  It makes sense to think of this as a two dimensions rather than one.  The name may be a compound name, and we need to traverse down the tree to find it.  This is the top down thing I was talking about before: JNDI is designed assuming that initial context is the root of the tree, as opposed to the current leaf node.  At least, Tomcat starts there.

The nice thing about lazy resolution (back tracking) is that creating a new context is really quick.  If  most components are  resolved in the request namespace, and only rarely make it all the way up to the global namespace, than there is no performance problem.

In the current Java landscape, there are many APIs for resolving a reference.  Baseline to the language is java.naming.  The Servlet API has explicit ones for looking for objects in the request, session ,and global contexts.  Spring has the the BeanFactory interface.  OSGI has Bundle Context.  Pico container has the pico object.  The fact is that, even with inversion of control, at some point you need to kick of an object creation chain.

For instance, struts maps a segment of an URL to a class that extends the struts Action class, after binding the context to an Action form.  These objects are configured via an XML file.  The Action object is a flyweight, designed to encapsulate business behavior, where as the form object is a minimal request or session scoped object designed to do some validation prior to handover to the action.   All of this is configured by a servlet.  Once the Servlet is deployed, there is no way to change the URL scheme of the application without redeploying the app, making it ill suited to end user defined content such as a Wiki or blog.  Layout is controlled by Tiles, another related project that merged with struts, leading to a hybrid API.  Java server faces has its own object registration and creation API as well.  Since JSF and struts solve similar issues, with similar approaches, what I write about one can be applied fairly easily to the other.

As I look at the these APIs, I am struck once again by the procedural nature of them.  Time and again, we see:  create object, set properties, call execute method.  Most of these take the Class.forName approach to create the objects, and dependencies are injected via setters.  Not my style.

When I last did this full time, I ended up with a common approach where the primary interaction between the parameters and the the java objects was through builders. I was never fonds of the concept of ‘Validators’ or objects who’s sole purpose was to validate a string, and then pass it on as a string.  once I have validated a string, I want to bind it to a class that states the validation is a precondition. For instance, a Social Security number is in the format DDD-DD-DDDD.  Further business objects should not pass around String ssns, but rather instances of class SSN.   If the SSN is part of a Person object, the SSN is then passed in as a Constructor parameters, and bound to a final field, making the end object immutable.  If there is an intermediate stage, perhaps a multe page form to construct the ‘Person,’ intermediate state is held in a PersonBuilder.  The create method of the PersonBuilder enforces the preconditions are met, or returns a collection of errors.  The completed Person object probably then becomes either a Session or Application scoped variable.  Note that all fields would be final and immutable, meaning the end product is thread safe.

Struts, tiles, and so on have an API where a context object is passed around from object to object throughout the hierarchy.  Each of these should be wrapped in an Adapter so that extends java.naming.Context and bound to a well known name via InitialContext.bind().  These objects can then be stacked one after another inside a composite naming context, and called each in turn.  Here’s a first take at the adapter for tile .

public TilesApplicationContextAdapter(
TilesApplicationContex conetxt){
if (context == null) throw new IllegalArgumentException(MESSAGE);
    this.context = context;
    new InitialCOntext.bind("java:/comp/context/"+TilesApplicationContextAdapter.class.getName(),context);
}

public final TilesApplicationContext context;

public void bind(Name arg0, Object arg1) throws NamingException {
...
}
/* now the hard works starts, converting from one API to another. */

Now,  the trick is to encapsulate all of this inside a typesafe API.

import javax.naming.NamingException;

public class GenericResolver<T> {

Class<T> classOf;

GenericFactory(Class<T> c) {
classOf = c;
}

public T fetch(Context context) throws NamingException {
return (T) context.lookup( lookupStrategy(classOf));
}

public T fetch() throws NamingException {
return fetch( new InitialContext());
}

}

I’ll leave on this note:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.