Search code examples
ejbwildfly

NoInitialContextException in simple EJB Project on Wildfly 8


I am trying to write a client for a simple EJB Project that I have deployed locally on my Wildfly 8 running in Eclipse.

My Interface:

package com.jwt.ejb.business;

import javax.ejb.Remote;

@Remote
public interface Hello {

    public String sayHello();
}

My Implementation:

package com.jwt.ejb.businesslogic;

import javax.ejb.Stateless;

import com.jwt.ejb.business.Hello;

@Stateless
public class HelloBean implements Hello {

    public HelloBean() { 
    }

    public String sayHello() { 
        return "Hello Boss Welcome to EJB";
    } 
}

My client:

package com.jwt.ejb.test;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.jwt.ejb.business.Hello;
import com.jwt.ejb.businesslogic.HelloBean;

public class Client {
    public static void main(String[] args) {
        Hello bean = doLookup();
        if (bean != null)
            System.out.println(bean.sayHello());
    }

    private static Hello doLookup() {
        Context context = null;
        Hello bean = null;
        try {
            final Hashtable jndiProperties = new Hashtable();
            jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
            context = new InitialContext(jndiProperties);
            bean = (Hello) context.lookup(getLookupString());

        } catch (NamingException e) {
            e.printStackTrace();
        }
        return bean;
    }

    private static String getLookupString() throws NamingException {
        final String appName = "";
        final String moduleName = "EJBTest";
        final String distinctName = "";
        final String beanName = HelloBean.class.getSimpleName();
        final String viewClassName = Hello.class.getName();
        return "ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName;
    }
}

When I run it, I get this Exception:

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
    at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
    at javax.naming.InitialContext.getURLOrDefaultInitCtx(Unknown Source)
    at javax.naming.InitialContext.lookup(Unknown Source)
    at com.jwt.ejb.test.Client.doLookup(Client.java:26)
    at com.jwt.ejb.test.Client.main(Client.java:15)
Exception in thread "main" java.lang.NullPointerException
    at com.jwt.ejb.test.Client.main(Client.java:16)

The official documentation does it like this too: https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI

Where is the problem ?

I came accross posts talking about boss-ejb-client.properties, but I am not sure what to put in it. As I understood it, I could either have this properties file, or declare the porperties programmatically, like I did.


Solution

  • Besides the fact that you are using Wildfly 8 and referencing JBoss AS 7.1's documentation, you're missing the InitialContextFactory on your JNDI properties.

    Wildfly's documentation on EJB invocations via JNDI is here. Therefore you should do the following:

    void doBeanLookup() {
        Properties jndiProperties = new Properties();
        jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
        jndiProperties.put(Context.PROVIDER_URL, "http-remoting://localhost:8080");
    
        // This is an important property to set if you want to do EJB invocations via the remote-naming project
        jndiProps.put("jboss.naming.client.ejb.context", true);
        // create a context passing these properties
        Context ctx = new InitialContext(jndiProps);
    
        // lookup the bean Hello
        Hello bean = (Hello) ctx.lookup(getLookupString());
    }
    

    In your pom.xml you should have the following:

    <dependency>
        <groupId>org.wildfly</groupId>
        <artifactId>wildfly-ejb-client-bom</artifactId>
        <version>8.0.0.Final</version>
        <type>pom</type>
    </dependency>
    

    If you want to use the http-remoting protocol, on your getLookupString method, you should remove the ejb: and have present that

    http-remoting client assumes JNDI names in remote lookups are relative to java:jboss/exported namespace, a lookup of an absolute JNDI name will fail.

    Further information can be found on Wildfly 8 Remote JNDI Reference Update Draft.