title: JNDI lookup from one server to many configurable servers
body: <p>We have a couple of JBoss servers on different machines with different IPs (not a cluster, single standalone JBoss 7.1.1 instances that belong to different customers). The exact same EAR is deployed on all systems. We try to send a POJO called <em>Group</em> from one system to another system.</p>
  
  <p><strong>The problem</strong></p>
  
  <p>We tried everything but are unable to get the remote methods called. The connection is established but not used (the local bean was used in some cases). What can we do to get the communication to work?</p>
  
  <p>We have tried to follow these manuals (without any luck so far):</p>
  
  <p><strong>EJB invocations from a remote server instance</strong></p>
  
  <p>This manual states:</p>
  
  <blockquote>
    <p>Note that this chapter deals with the case where the bean is deployed
    on the "Destination Server" but <strong>not</strong> on the "Client Server".</p>
  </blockquote>
  
  <p>The bean is deployed on both servers because there is no destination or client server. Both servers can be client or destination, depending on the scenario, e.g. customer A could want to send a <em>Group</em> to customer B today and customer C could want to send a <em>Group</em> to customer A tomorrow. The day after tomorrow, customer A might want to send a <em>Group</em> to customer C.</p>
  
  <p>Source: <a href="https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+server+instance" rel="nofollow">https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+server+instance</a></p>
  
  <p><strong>EJB invocations from a remote client using JNDI</strong></p>
  
  <p>This didn't worked either. This manual uses .properties-files that cannot be changed at runtime which makes this approach unusable, even if it would have worked (which it didn't).</p>
  
  <p>Source: <a href="https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI" rel="nofollow">https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI</a></p>
  
  <p><strong>Remote EJB invocations via JNDI - EJB client API or remote-naming project</strong></p>
  
  <p>This approach sets "jboss.naming.client.ejb.context" to true. This causes a SecurityException because EJBClientContext.setSelector is called.</p>
  
  <p>Source: <a href="https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project" rel="nofollow">https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project</a></p>
  
  <p><strong>Project structure</strong></p>
  
  <p>This is our project structure:</p>
  
  <pre><code>project/
      ear/
          pom.xml
      war/
          pom.xml
          src/main/java/com/acme/ejb/
              DefaultGroupImportBean.java
      ejb/
          pom.xml
          src/main/java/com/acme/ejb/
              DefaultGroupTransferBean.java
      ejb-api/
          pom.xml
          src/main/java/com/acme/ejb
              GroupImportBean.java
              GroupTransferBean.java
              RemoteEjbClient.java
  </code></pre>
  
  <p>This is the class that does the lookup:</p>
  
  <pre><code>public class RemoteEjbClient {
  
      private static final String INITIAL_CONTEXT_FACTORY = "org.jboss.naming.remote.client.InitialContextFactory";
  
      public GroupTransferBean lookupGroupTransferBean(NamingContextConfiguration namingContextConfiguration)
          throws NamingException {
  
          Context context = createInitialContext(namingContextConfiguration);
          return (GroupTransferBean) context.lookup(namingContextConfiguration.getLookupName());
      }
  
      private Context createInitialContext(NamingContextConfiguration namingContextConfiguration) throws NamingException {
          Properties jndiProperties = new Properties();
          jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
          jndiProperties.put(Context.PROVIDER_URL, namingContextConfiguration.getProviderUrl());
          jndiProperties.put(Context.SECURITY_PRINCIPAL, namingContextConfiguration.getPrincipal());
          jndiProperties.put(Context.SECURITY_CREDENTIALS, namingContextConfiguration.getCredentials());
  
          return new InitialContext(jndiProperties);
      }
  }
  </code></pre>
  
  <p><em>NamingContextConfiguration</em> is a POJO that describes another system. We store -_NamingContextConfiguration_s in our database (they must be configurable at runtime!). The principal has been added with <em>add-user.sh</em> (<em>Application User</em>).</p>
  
  <p>GroupTransferBean.java:</p>
  
  <pre><code>public interface GroupTransferBean {
  
      void pushGroup(Group group);
  
      void pushResources(String url, List&lt;String&gt; resources);
  }
  </code></pre>
  
  <p>GroupImportBean.java:</p>
  
  <pre><code>public interface GroupImportBean {
  
      public void importGroup(Group group);
  
      public void importResources(String url, List&lt;String&gt; resources);
  }
  </code></pre>
  
  <p>DefaultGroupTransferBean.java:</p>
  
  <pre><code>@Stateless(mappedName = "GroupTransferBean")
  @Remote(GroupTransferBean.class)
  public class DefaultGroupTransferBean implements GroupTransferBean {
  
      @EJB
      private GroupImportBean groupImportBean;
  
      @Override
      public void pushGroup(Group group) {
          groupImportBean.importGroup(group);
      }
  
      @Override
      public void pushResources(String url, List&lt;String&gt; resources) {
          groupImportBean.importResources(url, resources);
      }
  }
  </code></pre>
  
  <p>DefaultGroupImportBean.java:</p>
  
  <pre><code>@Stateless
  @Remote(GroupImportBean.class)
  @Interceptors(SpringBeanAutowiringInterceptor.class)
  public class DefaultGroupImportBean implements GroupImportBean {
  
      @Autowired
      private GroupRepository groupRepository;
  
      @Override
      public void importGroup(Group group) {
          groupRepository.save(group);
      }
  
      @Override
      public void importResources(String url, List&lt;String&gt; resources) {
          // Do some magic
      }
  }
  </code></pre>
  
  <p>The RemoteEjbClient is called by a Spring controller. </p>