How to get rid of version number in JNDI names, Jboss EAP 6, EJB 3.1

Viewed 2072

I have EJBs in EJB 3.1 which I am trying to deploy in JBoss EAP 6, but when I start the server. It appends version no in JNDI names as shown below.

18:27:57,068 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-6) JNDI bindings for session bean named TestService in deployment unit subdeployment "TestGroup-war-3_0_0-SNAPSHOT.war" of deployment "TestGroup-ear-3_0_0-SNAPSHOT.ear" are as follows:

java:global/TestGroup-ear-3_0_0-SNAPSHOT/TestGroup-war-3_0_0-SNAPSHOT/TestService!org.pkg.ejb.local.CRMDataServiceLocal
java:app/TestGroup-war-3_0_0-SNAPSHOT/TestService!org.pkg.ejb.local.CRMDataServiceLocal
java:module/TestService!org.pkg.ejb.local.CRMDataServiceLocal
java:global/TestGroup-ear-3_0_0-SNAPSHOT/TestGroup-war-3_0_0-SNAPSHOT/TestService
java:app/TestGroup-war-3_0_0-SNAPSHOT/TestService
java:module/TestService

How do I remove version number "-3_0_0-SNAPSHOT" from my JNDI names ? I have ejb-jar.xml which is placed in ejb jar file when I deploy the ear.

3 Answers

You don't have to delete the version information. You can get the correct application and module name via JNDI by self! See also this answer here: https://stackoverflow.com/a/7066600/1465758

If you are already inside the EJB container you can use the @Resource annotation:

@Resource(lookup = "java:app/AppName")
private String appName;

@Resource(lookup = "java:module/ModuleName")
private String moduleName;

If you are outside the EJB container you must use a JNDI lookup, like:

Context jndiCtxt = new InitialContext();
String appName = (String) jndiCtxt.lookup("java:app/AppName");
String moduleName = (String) jndiCtxt.lookup("java:module/ModuleName");

You can then access your TestService via:

Context jndiCtxt = new InitialContext();
TestService testSvc = (TestService) jndiCtxt.lookup(
                          "java:global/" + appName + "/" + moduleName + "/TestService");

EDIT:

If you have more as one module, may be a JNDI lookup on java:module/ModuleName returns the wrong module name. You can also get all available modules by calling

NamingEnumeration<NameClassPair> list = 
     jndiCtxt.list("java:global/" + appName + "/");

Or even better: While starting your application you can load all known Entities / Classes and the corrosponding JNDI URI in a static Map. At example:

public final class EJBUtil<T> {
  private static final Logger log = PSLogger.getLogger(EJBUtil.class);

  /** list of all known JNDI entities sort by the class: {Class; JNDI URI} */
  private final static Map<Class<?>, String> jndiEntities = new HashMap<>();
  /** synchronisation object for filling jndiEntities */
  private final static ReentrantLock jndiEntitiesLock = new ReentrantLock();

  /** the initial context */
  private static Context jndiCtxt = null;

  /**
   * class of the bean to get
   */
  private final Class<T> beanClass;

  /**
   * Constructs a new EJBUtil for the specified simple bean class name.
   * @param beanClass bean class for which this EJBUtil is
   */
  public EJBUtil(Class<T> beanClass) {
    this.beanClass = beanClass;
  }

  /**
   * Creates and returns a bean object from the EJB container.
   * @return the bean instance or null
   */
  @SuppressWarnings("unchecked")
  public final T getBean() {
    String jndiURI = null;

    try {
      if (jndiEntities.isEmpty()) {
        try {
          loadEntityMap();
        } catch (NamingException exc) {
          exc.printStackTrace();

          log.error(null, "! ! ! ! !   C A N N O T   L O A D   T H E   J N D I   E N T I T I E S  ! ! ! ! !",
              exc);

          return null;
        }
      }

      jndiURI = jndiEntities.get(beanClass);

      if (jndiURI == null) {
        log.error(null, "! ! ! ! !   C A N N O T   L O A D   T H E   \"" + beanClass.getSimpleName()
                + "\"   B E A N  (Entity not found in Naming Directory  ! ! ! ! !");
        return null;
      }

      Object obj = jndiLookup(jndiURI);
      return (T) obj;

    } catch (NamingException exc) {
      exc.printStackTrace();

      log.error(null, "! ! ! ! !   C A N N O T   L O A D   T H E   \"" + beanClass.getSimpleName()
              + "\"   B E A N  (JNDI URI: \"" + jndiURI + "\")  ! ! ! ! !",
          exc);

      return null;
    }
  }

  /**
   * Creates and returns a bean object from the EJB container.
   * @param name JNDI name of the resource to return
   * @return the resource object or null
   * @throws NamingException if the bean could not be created
   */
  public static final Object jndiLookup(String name) throws NamingException {
    try {
      if (jndiCtxt == null) {
        jndiCtxt = new InitialContext();
      }

      return jndiCtxt.lookup(name);
    } catch (NamingException exc) {
      exc.printStackTrace();

      log.error(null, "! ! ! ! !   C A N N O T   L O A D   T H E   J N D I   R E S O U R C E   \"" + name +
          "\"  (JNDI: \"" + name + "\")  ! ! ! ! !", exc);

      throw exc;
    }
  }

  private void loadEntityMap() throws NamingException {
    jndiEntitiesLock.lock();

    try {
      if (!jndiEntities.isEmpty()) {
        // map already filled
        return;
      }

      loadEntityMap("java:global/");
    } finally {
      jndiEntitiesLock.unlock();
    }

  }

  private void loadEntityMap(String jndiBaseURI) throws NamingException {
    if (jndiCtxt == null) {
      jndiCtxt = new InitialContext();
    }

    NamingEnumeration<NameClassPair> list = jndiCtxt.list(jndiBaseURI);

    while (list.hasMore()) {
      NameClassPair nameClassPair = list.next();

      if (nameClassPair.getClassName() != null &&
          !nameClassPair.getClassName().equals(Context.class.getName())) {

        try {
          jndiEntities.put(
              Class.forName(nameClassPair.getClassName()), jndiBaseURI + "/" + nameClassPair.getName());
        } catch (ClassNotFoundException e) {
          log.error(null, "Cannot load JNDI entity class " + nameClassPair.getClassName(), e);
        }
      }

      if (nameClassPair.getClassName() == null ||
          nameClassPair.getClassName().equals(Context.class.getName())) {

        loadEntityMap(jndiBaseURI + nameClassPair.getName() + "/");
      }
    }
  }
}

You can load then the EJB TestService by calling:

TestService testSvc = new EJBUtil<TestService>(TestService.class).getBean();
Related