eXo Platform 3.5

## Chapter 65. JNDI naming

## Prerequisites

We need to configure JNDI environment properties and Reference binding with the eXo container standard mechanism.

The Naming service covers:

- Configuring the current Naming Context Factory implemented as an ExoContainer Component `org.exoplatform.services.naming.InitialContextInitializer`.

- Binding Objects (References) to the current Context using `org.exoplatform.services.naming.BindReferencePlugin` component plugin.

## How it works

Make sure you understand the Java Naming and Directory InterfaceTM (JNDI) concepts before using this service.

### JNDI System property initialization

After the start time the Context Initializer (org.exoplatform.services.naming.InitialContextInitializer) traverses all initial parameters (that concern the Naming Context) configured in `default-properties` and `mandatory-properties` (see Configuration examples) and:

- For `default-properties`: Check if this property is already set as a System property (`System.getProperty(name)`) and set this property if it's not found. Using those properties is recommended with a third party Naming service provider.

- For `mandatory-properties`: Set the property without checking.

Standard JNDI properties:

- `java.naming.factory.initial`

- `java.naming.provider.url`

and others (see JNDI docs)

### JNDI reference binding

Another responsibility of Context Initializer `org.exoplatform.services.naming.InitialContextInitializer` is binding of preconfigured references to the naming context. For this purpose, it uses a standard eXo component plugin mechanism and in particular the `org.exoplatform.services.naming.BindReferencePlugin` component plugin. The configuration of this plugin includes three mandatory value parameters:

- `bind-name`: the name of binding reference.

- `class-name`: the type of binding reference.

- `factory`: the object factory type.

And also `ref-addresses` property parameter with a set of references' properties. (see Configuration examples) Context Initializer uses those parameters to bind the neccessary reference automatically.

## Configuration examples

The `InitialContextInitializer` configuration example:

      <component>

        <type>org.exoplatform.services.naming.InitialContextInitializer</type>

        <init-params>

          <value-param>.

            <name>bindings-store-path</name>.

            <value>bind-references.xml</value>.

          </value-param>.

          <value-param>

            <name>overload-context-factory</name>

            <value>true</value>

          </value-param>

          <properties-param>

            <name>default-properties</name>

            <description>Default initial context properties</description>

            <property name="java.naming.factory.initial" value="org.exoplatform.services.naming.SimpleContextFactory"/>

          </properties-param>

          <properties-param>

            <name>mandatory-properties</name>

            <description>Mandatory initial context properties</description>

            <property name="java.naming.provider.url" value="rmi://localhost:9999"/>

          </properties-param>

        </init-params>

      </component>

where

binding-store-path is file path which stores binded datasources in runtime

overload-context-factory allows to overload the default initial context factory by a context factory that is ExoContainer aware and that is able to delegate to the original initial context factory if it detects that it is not in the eXo scope. By default the feature is disabled since it is only required on AS that don't share the objects by default like tomcat but unlike JBoss AS

The `BindReferencePlugin` component plugin configuration example (for JDBC datasource):

      <component-plugins>

        <component-plugin>

          <name>bind.datasource</name>

          <set-method>addPlugin</set-method>

          <type>org.exoplatform.services.naming.BindReferencePlugin</type>

          <init-params>

            <value-param>

              <name>bind-name</name>

              <value>jdbcjcr</value>

            </value-param>

            <value-param>

              <name>class-name</name>

              <value>javax.sql.DataSource</value>

            </value-param>

            <value-param>

              <name>factory</name>

              <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>

            </value-param>

            <properties-param>

              <name>ref-addresses</name>

              <description>ref-addresses</description>

              <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>

              <property name="url" value="jdbc:hsqldb:file:target/temp/data/portal"/>

              <property name="username" value="sa"/>

              <property name="password" value=""/>

            </properties-param>

          </init-params>

      </component-plugin>

## Recommendations for Application Developers

- `SimpleContextFactory` is created for testing purposes only, do not use it for production.

- In J2EE environment use Naming Factory objects provided with the Application Server.

## InitialContextInitializer API

`InitialContextInitalizer` also provides feature of references binding in runtime. References have bind in runtime will be persisted and automatically rebinded on a next system start.

Service provides methods for binding reference.

         public void bind(String bindName,

                          String className,

                          String factory,

                          String factoryLocation,

                          Map<String, String> refAddr)

                     throws NamingException, FileNotFoundException, XMLStreamException;

- `bindName`: name of binding.

- `className`: the fully-qualified name of the class of the object to which this Reference refers.

- `factory`: the name of the factory class for creating an instance of the object to which this Reference refers.

- `factoryLocation`: the location of the factory class.

- `refAddr`: object's properties map.

Example of usage:

          // obtain InitialContextInitializer instance from ExoContainer (e.g. PortalContainer)

          InitialContextInitializer initContext = (InitialContextInitializer)container.getComponentInstanceOfType(InitialContextInitializer.class);

          Map<String, String> refAddr = new HashMap<String, String>();

          refAddr.put("driverClassName", "oracle.jdbc.OracleDriver");

          refAddr.put("url", "jdbc:oracle:thin:@oraclehost:1521:orcl");

          refAddr.put("username", "exouser");

          refAddr.put("password", "exopassword");

          initContext.bind("jdbcexco", "javax.sql.DataSource", "org.apache.commons.dbcp.BasicDataSourceFactory", null, refAddr);

          // try to get just bound DataSource

          DataSource ds = (DataSource)new InitialContext().lookup("jdbcexo");