Access Cabon Data Sources within webapps in WSO2 Application Server

In a previous post of mine, I explained on how we can register JNDI Resources within webapp that are hosted in WSO2 Application Server. In this post I will be explaining about How we can access Carbon Data Sources, using JNDI, within your webapps that are hosted in the same WSO2 Application Server instance.

The Problem

We can create Data Sources using Admin Console in WSO2 Application Server. We can also expose those DataSources as JNDI resource form Admin Console. Then arise the requirement to access these within the webapps which are hosted in the Same Application Server instance. Currently, ie with WSO2 Application Server 5.0.1, it is not possible to access them from the web applications.

The main reason for this the the way that JNDI context isolation is implemented for webapps at tomcat level. The implementation states that one webapp’s JNDI context cannot be accessed by another webapp, unless the JNDI resources are defined within the global scope.

We can look at the how the current naming context factory class (i.e.
org.apache.naming.java.javaURLContextFactory), which is used as the default Initial Context Factory class in WSO2 Carbon, is implemented. The following code segment shows how the getInitialContext method is implemented.

public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
    if (ContextBindings.isThreadBound() ||
        (ContextBindings.isClassLoaderBound())) {
        // Redirect the request to the bound initial context
        return new SelectorContext(
               (Hashtable<String, Object>) environment, true);
    }

    // If the thread is not bound, return a shared writable context
    if (initialContext == null) {
        synchronized (javaURLContextFactory.class) {
            if (initialContext == null) {
               initialContext = new NamingContext(
                       (Hashtable<String, Object>) environment, MAIN);
            }
        }
    }
}

We can see that, it first checks whether the current context is bound to any Thread or ClassLoader. This is correct form the point of view for webapps. Because, they will be running is an isolated manner from each other and their context also will be isolated from each other.

But in order to handle the requirement, that is to access JNDI context of Carbon, on which where the Data Sources will be binded, it is not possible by using this InitialContextFactory. The JNDI context of carbon is also isolated from webapps as with normal cases.

The Solution

The solution is to avoid using this InitialContextFactory and use a custom written InitialContextFactory which extends this and by overriding the above mentioned method to suite the need. This solution is now been added to WSO2 Application Server and will be available with the release of 5.1.0.

The new implementation of javaUrlContextFactory in WSO2 Carbon does not check whether the current context is bound to a thread or CL. It will return the JNDI of the Carbon runtime.

This is set as the default Initial Context Factory class in carbon.xml

<DefaultInitialContextFactory>org.wso2.carbon.tomcat.jndi.CarbonJavaURLContextFactory</DefaultInitialContextFactory>

So when we want to access the Carbon JNDI Context to lookup for Data Sources, we can add the following JNDI Initial Context Factory Environment property

java.naming.factory.initial : “org.wso2.carbon.tomcat.jndi.CarbonJavaURLContextFactory”

Let us look at an example of how this works. Say that you want to add a DataSource in Carbon. Following are the steps you will be going through.

1. Go to Configure > DataSources. There you will find the option to add new Data Sources as below.

Adding new data source

Adding new data source

2. After giving the required details for your new data sources, you will find an option to expose it as JNDI Data Source as below. In here I’m exposing my new Data Source with the name ”jdbc/MyCarbonDataSource”.

Expose as JNDI Data Source

Expose as JNDI Data Source

3. Now the Data Source is exposed. The following would give an idea on how to access the exposed Data Source within your webapp .

try {
    Hashtable environment = new Hashtable();
    environment.put("java.naming.factory.initial", "org.wso2.carbon.tomcat.jndi.CarbonJavaURLContextFactory");
    Context initContext = new InitialContext(environment);
    Object result = initContext.lookup("jdbc/MyCarbonDataSource");
    if (result != null) {
        // Do your work here
    } else {
        System.out.println(“Cannot find MyCarbonDataSource”);
    }
} catch (NamingException e) {
    e.printStackTrace();
}

From the above code segment, what we are doing is creating an IntialContext with the relevant environment properties. This will give the JNDI context of the Carbon. Using that, you can look for any object which are bound to that context. Here I’m looking up for “jdbc/MyCarbonDataSource”.

Like wise we can lookup for any Carbon Data Sources, which are exposed as JNDI resources, from webapps.

Advertisements

About kishanthan

I’m currently working as a Software Engineer at WSO2, an open source software company. I hold an Engineering degree, majoring in Computer Science & Engineering field, from University of Moratuwa, Sri Lanka.
This entry was posted in How to, Java, Tomcat, WSO2 and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s