Cdi Ejb Remote Context

This article shows how ejb remote clients can be configured and connected in a more dynamic way.

Within wildfly (current version 8.0.0.Final) there are several possibilities to connect ejb remote clients. Descriptions can be found on:

The Problem

You have an application for two (or more) tenants which are identical but are deployed on different machines. Customers should be able to switch between those tenants without restarting the application. Additionally the code itself should not depend on tenant specific code.
As far as i know this would be necessary with the standard approach (jboss-ejb-client.properties) given above.

A Solution

After some consideration i have identified the following five components which are needed to implement this feature.
  • Component that creates WildFly ejb remote connections
  • Component that produces the JNDI-Context
  • Component that holds the selected tenant-key for the client
  • Component that maps the tenant-keys to connection properties
  • CDI-Modul Qualifier

Putting them together leads to the following UML:



To keep the example as simple as possible i have decided to use the ejb-remote-quickstart example and extend it with the jndicontext module. The current implementation uses a simple property file which holds the following data.

tenant1.host=localhost
tenant1.port=8080
tenant1.username=test
tenant1.password=test
tenant1.noanonymous=false

tenant2.host=192.168.0.104
tenant2.port=8080
tenant2.username=test
tenant2.password=test
tenant2.noanonymous=false

The Fazit

The resulting service locator just has to use the JndiSession (in this example the RemoteEJBClient) which technically holds the tenant key and can be set from the GUI.
public class RemoteEJBClient {
    @Inject @JndiContextAnno
    Instance<Context> contextInstance;

    @Inject
    JndiSession jndiSession;
    //...snip
    private RemoteCalculator lookupRemoteStatelessCalculator() throws NamingException {
        Context context = contextInstance.get();
        //...snip
    }
}

public class CDIBootStrapper {
    public static void main(String[] args) throws Exception
    {
        WeldContainer weld = new Weld().initialize();
        RemoteEJBClient client = weld.instance().select(RemoteEJBClient.class).get();

        client.getJndiSession().setTenantKey("tenant1");
        client.invokeStatelessBean();

        client.getJndiSession().setTenantKey("tenant2");
        client.invokeStatelessBean();
    }
)
So the code looks very clean and in comparison to jboss-ejb-client.properties way more functional.
The sources can be found on https://bitbucket.org/abischof/injectablejndicontext.
Have fun coding... ;)