title: Standalone JBoss EJB Client application - how to get JNDI connection - "distinct name"
body: <p>There is a plethora of frustratingly incorrect (better description - "close but no cigar") information concerning remote access to JBoss EJBs from a standalone application.  I've been beating my head against this wall for over a day with no success.</p>
  
  <p>I'm trying to port an EJB from WebLogic to JBoss, which is called by a standalone application running on another server.</p>
  
  <p>I've been <a href="https://blog.akquinet.de/2014/09/26/jboss-eap-wildfly-three-ways-to-invoke-remote-ejbs/" rel="nofollow noreferrer">here</a>, <a href="https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI" rel="nofollow noreferrer">here</a>, and several other places chasing down various "solutions" to my problem without success.  I've tried reading the <a href="https://access.redhat.com/webassets/avalon/d/Red_Hat_JBoss_Enterprise_Application_Platform-7.0-Developing_EJB_Applications-en-US/Red_Hat_JBoss_Enterprise_Application_Platform-7.0-Developing_EJB_Applications-en-US.pdf" rel="nofollow noreferrer">official documentation</a> which wants me to install a "quickstart" based on Maven, which may or may not fit my situation, and which so far I have decided not to pursue.  (My project is not built with Maven, it uses Gradle, but I am reasonably certain that I've managed to get all the right dependencies deployed).</p>
  
  <p>I have a stateful EJB deployed in a WAR inside an EAR (previous implementation of deploying it simply in a WAR did not help matters). </p>
  
  <p>I configure the client thusly:</p>
  
  <pre><code>        public InitialContext createInitialContext() throws NamingException {
              Properties prop = new Properties();
              prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
  
              prop.put(Context.INITIAL_CONTEXT_FACTORY,
                      "org.jboss.naming.remote.client.InitialContextFactory");
  
              prop.put(Context.PROVIDER_URL, purl);
              prop.put(Context.SECURITY_PRINCIPAL, "myusername");
              prop.put(Context.SECURITY_CREDENTIALS, "mypassword");
              prop.put("jboss.naming.client.ejb.context", false);
  
              return new InitialContext(prop);            
          }
  
          public void closeContext(Context context) throws NamingException {
              if (context != null) {
                  context.close();
              }
          }
  
          private String getJndiName(
                  String prefix, 
                  String appName,
                  String moduleName,
                  String distinctName,
                  String beanName,
                  Class viewClass, 
                  boolean stateful) 
          {
              StringBuilder builder = new StringBuilder();
              if (prefix != null &amp;&amp; prefix.length() &gt; 0) {
                  builder.append(prefix).append(':');
              }
              builder.append(appName)
                      .append('/')
                      .append(moduleName)
                      .append('/')
                      .append(distinctName)
                      .append('/')
                      .append(beanName).append('!')
                      .append(viewClass.getName());
              if (stateful) {
                  builder.append("?stateful");
              }
              return builder.toString();
          }
          public Object lookup(Context context) throws NamingException {
  
              final String prefix = "ejb"; 
              final String appName = "myearname";
              final String moduleName = "mywarname";
              final String distinctName = "";
              final String beanName = "MyBean";
              final Class viewClass = MyBeanInterface.class;
  
  
              String jndi = getJndiName(prefix, appName, moduleName, distinctName, beanName, viewClass, true);
  
  
              return context.lookup(jndi);
          }
  </code></pre>
  
  <p>Note that no "distinct name" is provided as none is needed.  "distinct name" is <a href="https://docs.jboss.org/author/display/WFLY10/EJB+invocations+from+a+remote+client+using+JNDI" rel="nofollow noreferrer">supposed to be optional</a>: 
  All of this gets invoked by:</p>
  
  <pre><code>                MyBeanInterface sstatus = null;
                  try {
                      ctx = createInitialContext();
                      sstatus = (MyBeanInterface) lookup(ctx);
  
                  } catch (Exception ex) {
                       ...
                  }
  </code></pre>
  
  <p>When this code is invoked, the following error message is produced:</p>
  
  <pre><code>Caused by: java.lang.IllegalStateException: EJBCLIENT000024: No EJB receiver available for handling [appName:SockTransport, moduleName:SockTransport, distinctName:] combination
          at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:873) ~[ttjd.jar:?]
          at org.jboss.ejb.client.EJBClient.createSessionWithPossibleRetries(EJBClient.java:222) ~[ttjd.jar:?]
          at org.jboss.ejb.client.EJBClient.createSession(EJBClient.java:202) ~[ttjd.jar:?]
          at org.jboss.ejb.client.naming.ejb.EjbNamingContext.doCreateProxy(EjbNamingContext.java:227) ~[ttjd.jar:?]
          at org.jboss.ejb.client.naming.ejb.EjbNamingContext.createEjbProxy(EjbNamingContext.java:204) ~[ttjd.jar:?]
  </code></pre>
  
  <p>Using the above code, the JNDI name I am supplying is 
  <code>ejb:myearname/mywarname//MyBean!com.whatever.my.package.MyBeanInterface</code>. Note the double slash caused by the missing distinctName.  I can and have rejiggered this code to produce instead <code>ejb:myearname/mywarname/MyBean!com.whatever.my.package.MyBeanInterface</code> and this makes no difference.</p>
  
  <p><strong>Frankly, I think this error message is a red herring.</strong>  I suspect that there is some other problem with my setup that is not being caught and breaking on this interface.  I don't think the distinct name or lack thereof has anything to do with the problem.  I think that's simply how they log the object that can't be looked up.</p>
  
  <p>Before I go down the path of figuring out how to add a useless "distinct name" in a probably vain attempt to keep JBOSS happy, can someone venture a guess as to what the real problem may be?</p>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>The suggestions of @Steve_C are quite illuminating but I still have not gotten them to work.  He left a few points out of the initial context creation: </p>
  
  <ul>
  <li>Context.URL_PKG_PREFIXES</li>
  <li>Context.INITIAL_CONTEXT_FACTORY</li>
  <li>"jboss.naming.client.ejb.context"</li>
  </ul>
  
  <p>but these were mentioned in <a href="https://docs.jboss.org/author/display/WFLY8/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project" rel="nofollow noreferrer">the resource he cited</a> - very handy by the way. </p>
  
  <p>So I added these and my createInitialContext method now looks like this:</p>
  
  <pre><code>    public InitialContext createInitialContext() throws NamingException {
          Properties prop = new Properties();
          prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
          prop.put(Context.INITIAL_CONTEXT_FACTORY,
                  "org.jboss.naming.remote.client.InitialContextFactory");
          prop.put(Context.PROVIDER_URL, "http-remoting://{server-ip}:{server-port});
          prop.put("jboss.naming.client.ejb.context", true);
          return new InitialContext(prop);            
      }
  </code></pre>
  
  <p><strong>Why PROVIDER_URL is necessary when I've already supplied server-ip and server-port in the jboss-ejb-client.properties file remains mysterious, but it makes a difference.</strong></p>
  
  <p>With these three items added to my initial context environment, now I get a different error message (EJBCLIENT000025 instead of EJBCLIENT000024):</p>
  
  <pre><code>java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:SockTransport, moduleName:SockTransport, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@67f639d3
          at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:798) ~[ttjd.jar:?]
          at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:128) ~[ttjd.jar:?]
          at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186) ~[ttjd.jar:?]
          at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255) ~[ttjd.jar:?]
          at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200) ~[ttjd.jar:?]
          at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183) ~[ttjd.jar:?]
      at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146) ~[ttjd.jar:?]
      at com.sun.proxy.$Proxy20.create(Unknown Source) ~[?:?]
  </code></pre>
  
  <p>I suppose this counts as progress, but I'm finding this more difficult than it needs to be.  I wonder if these new properties need to be in the properties file, but the official documentation pretty clearly says they don't.</p>