Some time ago I stumbled on a weird exception when deploying an EAR on IBM WebSphere Application Server 8.5. The EAR got successfully installed, but when the application server tried to start the WAR archive of my EAR I got this exception:

javax.naming.ConfigurationException: NamingManager.getURLContext cannot find the factory for this scheme: java
	at com.ibm.ws.naming.util.Helpers.checkForUrlContext(Helpers.java:1631)
	at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:160)
	at com.ibm.ws.naming.util.WsnInitCtx.lookup(WsnInitCtx.java:179)
	at org.apache.aries.jndi.DelegateContext.lookup(DelegateContext.java:161)
	at javax.naming.InitialContext.lookup(InitialContext.java:436)

After searching the web for this exception I came to the conclusion that I have to debug it on my own. Some days of debugging later I found out that there was a configuration problem that was not obvious. So I decided to write this blog and I hope that it can safe you a lot of time.

The problem arises when versions of the JEE descriptors (e.g. web.xml, ejb-jar.xml) and the type of container specific descriptors (e.g. ibm-web-bnd.xmi or ibm-web-bnd.xml) are not compatible.

In my case the version of the WEB-INF/web.xml in my WAR archive was set to 3.0.

<web-app 
    id="someApp" 
    version="3.0" 
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
   ...
</web-app>

and the ibm-web-bnd.xmi descriptor was used. E.g.

<?xml version="1.0" encoding="UTF-8"?>
<webappbnd:WebAppBinding xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:common="common.xmi" xmlns:webappbnd="webappbnd.xmi" xmi:id="WebAppBinding_1" virtualHostName="default_host">
  <webapp href="WEB-INF/web.xml#someApp"/>
  <resRefBindings xmi:id="ResourceRefBinding_1172302423734" jndiName="jdbc/someDS">
    <bindingResourceRef href="WEB-INF/web.xml#ResourceRef_12743024234335"/>
  </resRefBindings>
  
  <ejbRefBindings xmi:id="EjbRefBinding_1289572370126" jndiName="">
    <bindingEjbRef xmi:type="common:EJBLocalRef" href="WEB-INF/web.xml#EJBLocalRef_1367972173131"/>
  </ejbRefBindings>
  
</webappbnd:WebAppBinding>

The problem with this configuration is that for a web-app version 3.0 you have to use ibm-web-bnd.xml instead of xmi. Otherwise the container can not setup the jndi environment correctly which leads to the “javax.naming.ConfigurationException: NamingManager.getURLContext cannot find the factory for this scheme: java”.

Sometime you also get a javax.naming.NamingException telling you that the context java can not be found.

So at least one can say that

  • web-app version <= 2.4 use ibm-web-bnd.xmi
  • web-app version >= 2.5 use ibm-web-bnd.xml

Migrating ibm-web-bnd.xmi to ibm-web-bnd.xml

In my case I had a ibm-web-bnd.xmi and I needed to convert it to the xml descriptor. Thus I thought it would be nice if I could do it via XSLT.

Since my application only used ejbRefBindings and resRefBindings I wrote a xslt script that can convert an ibm-web-bnd.xmi to an ibm-web-bnd.xml

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:webappbnd="webappbnd.xmi"
	xmlns:webapp="http://java.sun.com/xml/ns/javaee">


	<xsl:template match="webappbnd:WebAppBinding">
		<xsl:variable name="webAppId" select="substring-after( webapp/@href, '#')" />
		<xsl:variable name="virtualHostName" select="@virtualHostName" />
		<web-bnd xmlns="http://websphere.ibm.com/xml/ns/javaee"
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_0.xsd"
			version="1.0">

			<xsl:attribute name="id"><xsl:value-of select="$webAppId" /></xsl:attribute>

			<virtual-host>
				<xsl:attribute name="name"><xsl:value-of select="$virtualHostName" /></xsl:attribute>
			</virtual-host>

			<xsl:apply-templates select="resRefBindings" />
			<xsl:apply-templates select="ejbRefBindings" />
		</web-bnd>
	</xsl:template>

	<xsl:template match="resRefBindings">
		<xsl:variable name="bindingResourceRef"
			select="substring-after(bindingResourceRef/@href, '#ResourceRef_')" />
		<xsl:variable name="resRefName"
			select="document('web.xml')//webapp:web-app/webapp:resource-ref[@id = concat('ResourceRef_', $bindingResourceRef)]/webapp:res-ref-name" />
		<xsl:variable name="bindingName" select="@jndiName" />


		<xsl:choose>
			<xsl:when test="string-length(normalize-space($resRefName)) = 0">
				<xsl:text disable-output-escaping="yes"><![CDATA[<!-- ibm-web-bnd.xmi to xml transformation exception: Found resRefBindings with id ResourceRef_]]></xsl:text>
				<xsl:value-of select="$bindingResourceRef" />
				<xsl:text disable-output-escaping="yes"><![CDATA[ that has no matching reference in web.xml -->]]></xsl:text>
			</xsl:when>
			<xsl:otherwise>
				<resource-ref>
					<xsl:attribute name="name"><xsl:value-of
						select="$resRefName" /></xsl:attribute>
					<xsl:attribute name="binding-name"><xsl:value-of
						select="$bindingName" /></xsl:attribute>
				</resource-ref>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

	<xsl:template match="ejbRefBindings">
		<xsl:variable name="bindingEjbRef"
			select="substring-after(bindingEjbRef/@href, '#EJBLocalRef_')" />
		<xsl:variable name="ejbRefName"
			select="document('web.xml')//webapp:web-app/webapp:ejb-local-ref[@id = concat('EJBLocalRef_', $bindingEjbRef)]/webapp:ejb-ref-name" />
		<xsl:variable name="bindingName" select="@jndiName" />


		<xsl:choose>
			<xsl:when test="string-length(normalize-space($ejbRefName)) = 0">
				<xsl:text disable-output-escaping="yes"><![CDATA[<!-- ibm-web-bnd.xmi to xml transformation exception: Found ejbRefBindings with id EJBLocalRef_]]></xsl:text>
				<xsl:value-of select="$bindingEjbRef" />
				<xsl:text disable-output-escaping="yes"><![CDATA[ that has no matching reference in web.xml -->]]></xsl:text>
			</xsl:when>
			<xsl:otherwise>
				<ejb-ref>
					<xsl:attribute name="name"><xsl:value-of
						select="$ejbRefName" /></xsl:attribute>
					<xsl:attribute name="binding-name"><xsl:value-of
						select="$bindingName" /></xsl:attribute>
				</ejb-ref>
			</xsl:otherwise>
		</xsl:choose>

	</xsl:template>
</xsl:stylesheet>

Assuming that you have the following folder setup

xmi-to-xml-folder-setup

Here is some java code that can help you to transform the ibm-web-bnd.xmi to xml – or use some xslt processor of your choice.

import java.io.File;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class Transform {

	public static void main(String[] args) throws Exception {
		File inputXmlFile = new File(args[0]);
		File xsltFile = new File(args[1]);

		StreamSource inputXml = new StreamSource(inputXmlFile);
		StreamSource xslt = new StreamSource(xsltFile);

		TransformerFactory transformerFactory = TransformerFactory
				.newInstance();
		Transformer transformer = transformerFactory.newTransformer(xslt);

		Result outputTarget = new StreamResult(new File(args[2]));
		transformer.transform(inputXml, outputTarget);
	}
}

If you use the example java code above you can compile it in the directory shown above and execute it with this command line

> java Transformer ibm-web-bnd.xmi ibm-web-bnd.xmi-to-xml.xslt ibm-web-bnd.xml