Hi,

In this example we will see how to bind custom objects in the JNDI tree of “JBoss AS7.1.1 Final” and What kind of JNDI name we should choose in order to make the Remote client to be able to access (lookup) those JNDI entries.

Point-1). JBoss AS7.1.1.Final provides a Jar file for the Client side in order to perform remote lookup’s of JMS and EJB components “jboss-as-7.1.1.Final/bin/client/jboss-client.jar”. This jar should be used with standalone clients only, not with deployments are that deployed to an AS7 instance.

Point-2). If we want to make the JNDI name accessible for a remote client then the JNDI name must have “exported” keywork in the following pattern: “java:jboss/exported/YOUR_JNDI_NAME”

Point-3). On the client side we will need to use a new Protocol “remote://” as following:

.
  String JBOSS_CONTEXT="org.jboss.naming.remote.client.InitialContextFactory";;
  Properties props = new Properties();
  props.put(Context.INITIAL_CONTEXT_FACTORY, JBOSS_CONTEXT);
  props.put(Context.PROVIDER_URL, "remote://localhost:4447"); 
  props.put(Context.SECURITY_PRINCIPAL, "testuser");
  props.put(Context.SECURITY_CREDENTIALS, "testpassword");
  context = new InitialContext(props);	
.

Point-4). We will use the “jboss-cli.sh” script to configure the custom JNDI bindings on JBoss AS7.1.1.Final

Point-5): [ IMPORTANT ] Security is the main focus now so before running “JBoss AS7.1.1.Final” we will need to create a new Application User by running “${JBOSS_HOME}/bin/add-user.sh” script as following so that Remote User will be able to access the JNDI :

[userone@localhost bin]$ ./add-user.sh 

What type of user do you wish to add? 
 a) Management User (mgmt-users.properties) 
 b) Application User (application-users.properties)
(a): b

Enter the details of the new user to add.
Realm (ApplicationRealm) :  ApplicationRealm
Username : testuser
Password : testpassword
Re-enter Password : testpassword

What roles do you want this user to belong to? (Please enter a comma separated list, or leave blank for none) : testrole
About to add user 'testuser' for realm 'ApplicationRealm'

Is this correct yes/no? yes

Added user 'testuser' to file '/home/userone/jboss-as-7.1.1.Final/standalone/configuration/application-users.properties'
Added user 'testuser' to file '/home/userone/jboss-as-7.1.1.Final/domain/configuration/application-users.properties'
Added user 'testuser' with roles testrole to file '/home/userone/jboss-as-7.1.1.Final/standalone/configuration/application-roles.properties'
Added user 'testuser' with roles testrole to file '/home/userone/jboss-as-7.1.1.Final/domain/configuration/application-roles.properties'
.
.

Source Code (Git Repo) Source Code for this Demo Can be downloaded from GIT Repository:
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/Binding_Custom_Object_IN_JBossAS711Final

Start JBoss AS7.1.1.Final like following:

$ ./standalone.sh  -c standalone-full.xml

Binding Simple Objects in the JNDI Tree.

Step-1). Open a terminal (command prompt) then nevigate inside your “/home/userone/JBoss_All/jboss-as-7.1.1.Final/bin” directory and then run the following command in order to start and connect the JBoss CLI utility with the running JBoss instance:

$    ./jboss-cli.sh -c --controller=localhost:9999
OR
[userone@localhost bin]$    ./jboss-cli.sh -c 
OR
[userone@localhost bin]$    ./jboss-cli.sh -c --controller=localhost:9999  --gui        
.

Step-2). Now in order to bind a simple Integer Data type value in the JNDI tree just run the following command:

.
/subsystem=naming/binding=java:jboss/exported/test/:add(binding-type=simple,value=100,type=int)
.

If you dont want to use the command line utility to achieve the above then you can edit the naming subsystem of your “standalone-full.xml” file as following:

        <subsystem xmlns="urn:jboss:domain:naming:1.1">
            <bindings>
                <simple name="java:jboss/exported/test" value="100" type="int"/>
            </bindings>
        </subsystem>

Binding Complex/Custom Objects in the JNDI Tree.

Step-1). Suppose you have created a class like “TestBean.java” and you want to bind an instance of this class in the JNDI tree of your JBoss, then we will need to compile this class and we will need to make sure that this class is present inside the JBoss Classpath (using the JBoss Modules concept we can do that). Just write the following kind of class “TestBean.java”

package test.jndi.demo;
public class TestBean implements java.io.Serializable
  {
      private String name;
      private String value;

      public TestBean(String name,String value)
       {
         this.name=name;
         this.value=value;
         System.out.println("[TestBean] TestBean initialized.");
       }

      public String getName()  
       {
          return name;
       }      
      public String getValue()  
       {
          return value;
       }      
  }

Step-2). Now in order to bind a Complex Data type value in the JNDI tree we will need to create a class which implements the “javax.naming.spi.ObjectFactory” interface and the getObjectInstance(…,…,..) method of this class should return the object which we want to bind in the JNDI tree of JBoss as following:

package test.jndi.demo;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
public class MyCustomObjectFactory implements ObjectFactory 
   {
       public MyCustomObjectFactory() 
       {
            System.out.println("[MyCustomObjectFactory] MyCustomObjectFactory initialized.");
       }

       public Object getObjectInstance(Object obj, Name name, Context nameCtx,Hashtable environment) throws Exception 
       {
            TestBean bean = new TestBean("City","Pune (India)");
            return bean;
       }
   }

Step-3). Now compile the above two classes “TestBean.java” and “MyCustomObjectFactory.java” and then make a Jar file which should contain these classes. Suppose your JAR file name is “testJndiBinding.jar”

Step-4). Now we will need to make a JBoss module containing the above Jar “testJndiBinding.jar”. In order to create JBoss Module simply create a directory “test/jndi/demo/main” inside JBoss modules directory like:

mkdir “/home/userone/JBoss_All/jboss-as-7.1.1.Final/modules/test/jndi/demo/main”

Step-5). Now place your “testJndiBinding.jar” file inside “jboss-as-7.1.1.Final/modules/test/jndi/demo/main” directory and then create a file with name “module.xml” inside “jboss-as-7.1.1.Final/modules/test/jndi/demo/main” as following:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="test.jndi.demo">
    <resources>
        <resource-root path="testJndiBinding.jar"/>
    </resources>
    <dependencies>
        <module name="javax.api"/>
    </dependencies>
</module>

Step-6). Restart your JBoss so that the Module can be utilized.

Step-7). Now in order to bind the “TestBean.class” object in the JNDI tree of JBoss AS7.1.1.Final we will need to run the following CLI command:

.
/subsystem=naming/binding=java:jboss/exported/test2/:add(binding-type=object-factory,module=test.jndi.demo,class=test.jndi.demo.MyCustomObjectFactory)
.

If you dont want to use the command line utility to achieve the above then you can edit the naming subsystem of your “standalone-full.xml” file as following:

        <subsystem xmlns="urn:jboss:domain:naming:1.1">
            <bindings>
                <simple name="java:jboss/exported/test" value="100" type="int"/>
                <object-factory name="java:jboss/exported/test2" module="test.jndi.demo" class="test.jndi.demo.MyCustomObjectFactory"/>
            </bindings>
        </subsystem>

Creating Aliases of the JNDI Names.

Step-7). If you want to create various alias Lookup names for your JNDI names then you can do the following….. (Suppose you want to create various alias names for your JNDI name “java:jboss/exported/test2”)

.
/subsystem=naming/binding=java:jboss/exported/test3/:add(binding-type=lookup,lookup=java:jboss/exported/test2)
/subsystem=naming/binding=java:jboss/exported/test4/:add(binding-type=lookup,lookup=java:jboss/exported/test2)
/subsystem=naming/binding=java:jboss/exported/test5/:add(binding-type=lookup,lookup=java:jboss/exported/test2)
/subsystem=naming/binding=java:jboss/exported/test6/:add(binding-type=lookup,lookup=java:jboss/exported/test2)
/subsystem=naming/binding=java:jboss/exported/test7/:add(binding-type=lookup,lookup=java:jboss/exported/test2)
.

If you dont want to use the command line utility to achieve the above then you can edit the naming subsystem of your “standalone-full.xml” file as following:

        <subsystem xmlns="urn:jboss:domain:naming:1.1">
            <bindings>
                <!-- Binding primitive Data types in the JNDI Tree -->
                <simple name="java:jboss/exported/test" value="1000" type="int"/>


                <!-- Binding Custom Objects in the JNDI Tree -->
                <object-factory name="java:jboss/exported/test2" module="test.jndi.demo" class="test.jndi.demo.MyCustomObjectFactory"/>
 

                <!--  Following is used for Aliasing JNDI names -->
                <lookup name="java:jboss/exported/test3" lookup="java:jboss/exported/test2"/>
                <lookup name="java:jboss/exported/test4" lookup="java:jboss/exported/test2"/>
                <lookup name="java:jboss/exported/test5" lookup="java:jboss/exported/test2"/>
                <lookup name="java:jboss/exported/test6" lookup="java:jboss/exported/test2"/>
                <lookup name="java:jboss/exported/test7" lookup="java:jboss/exported/test2"/>
            </bindings>
        </subsystem>

Testing the Remote JNDI Lookup

Now as we have already binded various objects in the in the JNDI tree of JBoss, so now we will write simple Standalone Java code in order to perform the Remote JNDI Lookup.

Write the following code somewhere in your file system “BindJndiDemo.java”

import java.io.*;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class BindJndiDemo
{
public final static String JNDI_FACTORY="org.jboss.naming.remote.client.InitialContextFactory";

public static void main(String[] args) throws Exception 
  {
     if (args.length != 1) {
         System.out.println("Usage: java BindJndiDemo URL");
         System.out.println("Example:  java BindJndiDemo remote://localhost:4447");
         return;
     } 

     InitialContext ic = getInitialContext(args[0]);
     BindJndiDemo demo = new BindJndiDemo();

     System.out.println("nnt *** Following shows Looking up a Primitive Datatype located in the JNDI ***");
     Object primitiveLookup=ic.lookup("test");
     System.out.println("tic.lookup("test") primitiveLookup = "+primitiveLookup);


     System.out.println("nnt *** Following shows Looking up a Custom Bean/Object located in the JNDI ***");
     test.jndi.demo.TestBean testBean=(test.jndi.demo.TestBean)ic.lookup("test2");
     System.out.println("t(test.jndi.demo.TestBean)ic.lookup("test2") testBean = "+testBean);
     System.out.println("tname="+testBean.getName()+"tvalue="+testBean.getValue());

     System.out.println("nnt *** Following shows the JNDI Name Aliasing ***");
     Object obj=ic.lookup("test3");
     System.out.println("tAliasing Demo ic.lookup("test3") = "+obj);
     obj=ic.lookup("test4");
     System.out.println("tAliasing Demo ic.lookup("test4") = "+obj);
     obj=ic.lookup("test5");
     System.out.println("tAliasing Demo ic.lookup("test5") = "+obj);
  }


private static InitialContext getInitialContext(String url) throws NamingException
     {
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
        env.put(Context.PROVIDER_URL, url);

        //*************** UserName & Password for the Initial Context for JNDI lookup *************************
        env.put(Context.SECURITY_PRINCIPAL, "testuser");
        env.put(Context.SECURITY_CREDENTIALS, "testpassword");
        InitialContext ic=new InitialContext(env);
        System.out.println("nnt Got InitialContext ic: "+ic);
        return ic;
     }
  }

Now before compiling and running the above program just make sure that the “jboss-as-7.1.1.Final/bin/client/jboss-client.jar” is added in your CLASSPATH as following:

[userone@localhost Binding_Custom_Object_IN_JBossAS711Final]$ echo $PATH
/home/userone/MyJdks/jdk1.6.0_21/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/userone/.local/bin:/home/userone/bin


[userone@localhost Binding_Custom_Object_IN_JBossAS711Final]$ echo $CLASSPATH
/home/userone/JBoss_All/jboss-as-7.1.1.Final/bin/client/jboss-client.jar:.:


[userone@localhost Binding_Custom_Object_IN_JBossAS711Final]$  java BindJndiDemo remote://localhost:4447
Apr 29, 2012 12:38:43 AM org.xnio.Xnio <clinit>
INFO: XNIO Version 3.0.3.GA
Apr 29, 2012 12:38:43 AM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.0.3.GA
Apr 29, 2012 12:38:43 AM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 3.2.3.GA


	 Got InitialContext ic: javax.naming.InitialContext@671ff436


	 *** Following shows Looking up a Primitive Datatype located in the JNDI ***
	ic.lookup("test") primitiveLookup = 100


	 *** Following shows Looking up a Custom Bean/Object located in the JNDI ***
	(test.jndi.demo.TestBean)ic.lookup("test2") testBean = test.jndi.demo.TestBean@12b754b2
	name=City	value=Pune (India)


	 *** Following shows the JNDI Name Aliasing ***
	Aliasing Demo ic.lookup("test3") = test.jndi.demo.TestBean@63b0bdc8
	Aliasing Demo ic.lookup("test4") = test.jndi.demo.TestBean@359eda2c
	Aliasing Demo ic.lookup("test5") = test.jndi.demo.TestBean@4c349471
.
.

.
.
Thanks 🙂
Middleware Magic Team

If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.