IBM Support

ClassNotFoundException when using JNDI in a CICS JVM Server

Troubleshooting


Problem

You experience a ClassNotFoundException for the initial context factory when attempting to use Java™ Naming and Directory Interface (JNDI) from a CICS Java program hosted in a Java Virtual Machine (JVM) Server. For example, using the com.ibm.websphere.naming.WsnInitialContextFactory from the WebSphere Application Server thin client.

Cause

JNDI is an application programming interface (API) that can be implemented by many different vendors. It is often necessary to use a specific vendor's JNDI Factory when connecting to their JNDI server. For example, if you wish to use the JNDI API in a CICS Java program to interact with a WebSphere JNDI server, you would add the WebSphere client jar file to your CICS Java environment.

The java.naming.factory.initial property is used to specify the vendor specific factory class that the javax.naming classes should load. In an OSGi environment bundles have to identify the packages they are allowed to import, so the standard javax.naming classes do not have visibility to load vendor specific classes, causing the ClassNotFoundException.

Environment

JVM server

Diagnosing The Problem

Stack trace will return:

Caused by: java.lang.ClassNotFoundException: com.ibm.websphere.naming.WsnInitialContextFactory
        at java.lang.Class.forName(Class.java:176)
        at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:75)
        at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:682)

Resolving The Problem

Use of an OSGi JNDI registry service. For example, the open source Apache Aries project provides the infrastructure required for such a service here: http://aries.apache.org/modules/jndiproject.html .

CICS Transaction Server for z/OS (CICS TS) V5.1 and later enables a JNDI registry service automatically.

For CICS TS V4.2, you will need to provide your own version.

The registry service enables JNDI implementation classes to register themselves within the OSGi framework. This will typically happen when the JVM is started. The javax.naming classes use the registry in order to resolve the registered JNDI implementation classes on behalf of the application.

In addition to a registry, you will also need a suitable OSGi bundle for the JNDI implementation classes, and an OSGi Activator to register the vendor specific JNDI Factory class. The vendor specific OSGi Bundle might include an Activator, but this is not always the case. For example, the WebSphere thin client is an OSGi bundle that includes the implementation classes for the JNDI service, but at time of writing it does not include an OSGi Activator for JNDI.

It might be necessary to supply your own Activator for JNDI. If you need to do so, the following example might be helpful. It is suitable for use with CICS TS V4.2, and CICS TS V5.1 or later. It demonstrates an Activator for the IBM WebSphere JNDI initial context factory:

public class JNDIActivator implements org.osgi.framework.BundleActivator
{

    public void start (org.osgi.framework.BundleContext bundleContext) throws java.lang.Exception
    {
      // Load the WebSphere JNDI Initial Context Factory
      javax.naming.spi.InitialContextFactory initialContextFactory
        = new com.ibm.websphere.naming.WsnInitialContextFactory();

      // Find the factory class names to register
      String[] interfaceNames =
      {
        javax.naming.spi.InitialContextFactory.class.getName(), com.ibm.websphere.naming.WsnInitialContextFactory.class.getName()
      };

      // Register the class names with the Service Registry
      org.osgi.framework.ServiceRegistration serviceRegistration =
        bundleContext.registerService(interfaceNames,
        initialContextFactory, null);
      }

    public void stop (org.osgi.framework.BundleContext bundleContext) throws java.lang.Exception
    {
    }
}


The OSGI manifest for the Activator above would be similar to the following:


    Manifest-Version: 1.0
    Created-By: 1.5.0 (IBM Corporation)
    Bundle-ManifestVersion: 2
    Bundle-Name: JNDI Activator for WAS thin client
    Bundle-SymbolicName: was.jndi.activator
    Bundle-Version: 1.0
    Bundle-RequiredExecutionEnviornment: J2SE-1.6
    Bundle-Activator: JNDIActivator
    Import-Package:
    com.ibm.websphere.naming, org.osgi.framework

The JNDI Activator will need compiling and packaging into a CICS Bundle as normal. You can then install the Activator Bundle just like any other CICS OSGi Bundle.

The key field in the OSGi manifest file above is the 'Bundle-Activator' line. This identifies a class that will run as the OSGi Bundle is activated. The OSGi framework will call the start() method of the Activator as the Bundle is initialized, and the Activator will register the JNDI Initial Context Factory with the JNDI registry service. All of this will happen before the application is used. When the application runs, the javax.naming.* classes should be able to resolve the vendor specific JNDI implementation classes using the Initial Context Factory that was previously registered.

Some JNDI implementations might have further dependencies that need importing into the Activator bundle, and registering with the Service Registry. For example, if the IBM MQ JNDI implementation is used, the following services may need to be registered in the Activator:

    // Find the factory class names to register
    String[] interfaceNames =
    {
      InitialContextFactory.class.getName(), RefFSContextFactory.class.getName()
    };

    // Register the class names with the Service Registry
    ctx.registerService(interfaceNames, new RefFSContextFactory(), null);

    // Load the MQ object factories   ctx.registerService(MQConnectionFactoryFactory.class.getName(), new MQConnectionFactoryFactory(), null);
    ctx.registerService(MQQueueConnectionFactoryFactory.class.getName(), new MQQueueConnectionFactoryFactory(), null);
    ctx.registerService(MQTopicConnectionFactoryFactory.class.getName(), new MQTopicConnectionFactoryFactory(), null);
    ctx.registerService(MQTopicFactory.class.getName(), new MQTopicFactory(), null);
    ctx.registerService(MQQueueFactory.class.getName(), new MQQueueFactory(), null);

[{"Product":{"code":"SSGMGV","label":"CICS Transaction Server"},"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Component":"Java","Platform":[{"code":"PF035","label":"z\/OS"}],"Version":"5.2;5.1;4.2","Edition":"","Line of Business":{"code":"LOB35","label":"Mainframe SW"}}]

Product Synonym

CICS/TS CICS TS CICS Transaction Server

Document Information

Modified date:
15 June 2018

UID

swg21608608