How To Add Custom JNDI Resource Factory That Will Return Your Custom Object6 min read


This is legacy stuff, which means you either stuck somewhere or you are about to get stuck somewhere.

Am I right or am I right? 😀

The JNDI stuff is really confusing especially if you have not seen the younger architecture of the web. So, let’s talk about the earlier architecture and System Design where it was used.

Monolith Architecture

Mostly all of the legacy architectures are a monolith. They have a large code base with dependent modules. Here, the dependency that I’m referring to is not in the code terms but in the architecture terms.

For example – there is a server (host) where we are going to deploy all our applications. So, to deploy the JAVA application we need an application server like Tomcat.

The Java application will be deployed on the Tomcat server.

Monolith deployment architecture

Now, one tomcat instance is capable of running multiple application. In other words, multiple JAVA applications are deployed on a single tomcat instance running on the server.

This is a monolith architecture for deploying the applications.

This is a common architecture I found across multiple organization with whom I have worked. It definitely has benefits but also has drawbacks.

And when drawbacks start to weight more than benefits, architects decided to move away from this architecture and started deploying single instances of application which is much easier to maintain and scale. This is what we know of as Microservices.

So, you get the idea, right?

Monolith can simply be referred to as one large unit consists of multiple application tied together tightly.

How Did JNDI Come Into The Big Picture

As you already know JNDI stands for Java Naming and Directory Interface. And this name perfectly suits what it does.

In a very simple definition, you can understand JNDI as a Dictionary that maintains the entries of the object against a literal string. So, that you can retrieve the object by calling its name. This mapping of a string with the object is called Binding. And a set of these binding is called Context.

Next time whenever you hear the word binding getting used in the JNDI context, you know what that means. It’s a simple mapping of String with the Object.

So, one more time in very simple and Java-style definition, you can look at it as a HashMap of String and Object (<String, Object>). Here string will be the name for the object and Object will the actual object that you put in there.

This explains the Naming and Directory part of the JNDI. So, where does the interface comes into the picture?

This is where the magic happens.

JNDI provides an API that you can use to register objects to the JNDI which then can we retrieved at a later timer.

How Is JNDI Used In Monolith Architecture?

When multiple applications are deployed on the same tomcat instance that requires the same data source, it makes sense to keep all the commonly used objects in one place.

This is where JNDI is used majorly.

It is used to store multiple objects in the JNDI context which application can use at the runtime dynamically.

In other words, it allows the developer to push the responsibility of creating and the data source (and other commonly used objects) objects to the external environment (Tomcat). And whenever the application needs it, it can directory ask for the object by its name.

Applications deployed on the Tomcat will have access to the JNDI resources
Applications deployed on the Tomcat will have access to the JNDI resources

Are you with me so far?

I hope I’m making sense for you 😀

Let’s get to the final part then…

Create Custom JNDI Resource Factory That Will Return Your Custom Object

I’ll start with the project structure of the WAR file that I have.

I have shared the link to the GitHub project at the end. But make sure you read the entire article to understand completely.

Project WAR structure
Project WAR Structure

This is a typical WAR file structure that is deployed on the Tomcat instance.

So far, you should have a tomcat server running on your host. And later you will be deploying the WAR file on your tomcat instance.

Context Resource

Let’s create a Context Resource inside META-INF/context.xml.

<Context>
    <Resource name="HelloJndi" auth="Container"
              type="com.bma.poc.jndi.MyJNDIResource"
              factory="com.bma.poc.jndi.MyJNDIResourceFactory"
              personName="Varun Shrivastava" message="Hello From JNDI Object!!!" />
</Context>

Here, you have defined the Resource that you will use in your application. This resource will be read by the tomcat at the startup time and the respective bean will be created. The tomcat passes this referenced resource to the FACTORY that you will create next.

JNDI Resource Factory

Now, you need a Custom JNDI Resource Factory that will create and return your custom resource based on the properties that you have set (i.e. personName and message) to your referenced object in the context.xml file.

This Custom factory that you create will get the referenced object as its parameter (see the code below).

public class MyJNDIResourceFactory implements ObjectFactory {
    @Override
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
        Reference referencedObject = (Reference) obj;
        MyJNDIResource myJNDIResource = new MyJNDIResource();
        myJNDIResource.setPersonName(referencedObject.get("personName").getContent().toString());
        myJNDIResource.setMessage(referencedObject.get("message").getContent().toString());
        return myJNDIResource;
    }
}

This factory knows how to retrieve information from the JNDI reference object and create a Custom Resource (MyJNDIResource).

How To Retrieve Object From JNDI In Application

Here’s the code for the retrieving the object from the JNDI context.

public String helloFromJNDIWorld() throws NamingException {
        Context initialContext = new InitialContext();
        Context envContext = (Context) initialContext.lookup("java:comp/env");
        MyJNDIResource jndiResource = (MyJNDIResource) envContext.lookup("HelloJndi");
        return jndiResource.getPersonName() + " wants to say " + jndiResource.getMessage();
    }

As you know that JNDI is a directory of objects that can be looked-up by their names.

So, here we will look for the JNDI object by its name “HelloJndi”. This name should exactly match the name that you gave in the Context Resource (context.xml).

So, when you deploy the application and load the URL, you should see this,

Example JNDI From The Browser
Navigate to the /example/jndi in your Browser

Github Project URL -> https://github.com/vslala/Spring-mvc-boilerplate/tree/jndi-sample

Let me know if you have any doubts or questions. You can always find me here. Comment below so that I can get the notification immediately.

If you are interested in reading other programming related articles then browse the Programming Category.

Conclusion

The example that I showed is used with the application context. If you have more than two applications deployed on the tomcat. Then you can move this context resource in the tomcat’s server.xml file.

Let me know how you find this article. I know I rushed through various parts but hey you can always read about the JNDI online but its the implementation that matters 😀


  • Article By: Varun Shrivastava

  • Varun Shrivastava is an innovative Full Stack Developer at ThoughtWorks with around 4 years of experience in building enterprise software systems in finance and retail domain. Experienced in design, development, and deployment of scalable software. He is a passionate blogger and loves to write about philosophy, programming, tech and relationships. This is his space, you can get in touch with him here anytime you want.