7.3.2 Bootstrapping outside of a J2EE container
Applications running outside of a container cannot use a naming reference like java:comp/env to look up names because only a J2EE container can configure the java:name space for an application. Instead, an application of this type must look up the object directly from the name server. Also, the stand-alone client cannot rely on a container to resolve the location of the name server as it is running outside of a container. Therefore, stand-alone Java clients have specific bootstrapping requirements; normally, the bootstrap server location needs to be specified in the application code programmatically.
Because the location of the name server and the JNDI name of the EJB are environment-specific, the stand-alone client should obtain the necessary values to pass to the InitialContext from an external resource, like a properties file.
In the following sections, we show three examples of JNDI lookups to appservers running the target EJB. These examples do not use a properties file. The samples demonstrate three scenarios where a stand-alone Java client bootstraps to a:
Single server
Server cluster
Server cluster with fault-tolerant initial context Single server
Example 7-2 shows the lookup of an EJB home that is running in the single server, Server1, configured in the node app1. In this example, there is only one server so there is no possibility of specifying multiple bootstrap servers. The name server is running on the same appserver as the target EJB, so the JNDI name does not need to be fully qualified.
Example 7-2 Single server - lookup EJB home
// Get the initial context Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"); env.put(Context.PROVIDER_URL, "corbaloc::app1:2809"); Context initialContext = new InitialContext(env); // Look up the home interface using the JNDI name try { java.lang.Object ejbHome = initialContext.lookup("BeenThere"); beenThereHome = (BeenThereHome)javax.rmi.PortableRemoteObject.narrow( (org.omg.CORBA.Object) ejbHome, BeenThereHome.class); } catch (NamingException ne) { // Error getting the home interface ... }Server cluster
Example 7-3 shows the lookup of an EJB home that is running in a cluster called EJBcluster. The name can be resolved if any one of the cluster members is running. As this is a stand-alone client, the location of the name service still needs to be specified.
Example 7-3 Server cluster - lookup EJB home
// Get the initial context Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"); env.put(Context.PROVIDER_URL, "corbaloc::app1:2809"); Context initialContext = new InitialContext(env); // Look up the home interface using the JNDI name try { java.lang.Object ejbHome = initialContext.lookup( "cell/clusters/EJBcluster/BeenThere"); beenThereHome = (BeenThereHome)javax.rmi.PortableRemoteObject.narrow( (org.omg.CORBA.Object) ejbHome, BeenThereHome.class); } catch (NamingException e) { // Error getting the home interface ...Server cluster with fault-tolerant initial context
In the previous example, the EJB is running on clustered servers but still relies on one server for the bootstrapping process. Example 7-4 shows how to obtain the initial context via a fault-tolerant provider URL which has boostrapping information for two server cluster members:
Example 7-4 Cluster - lookup EJB home via fault-tolerant provider URL & specify path
// Get the initial context Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"); env.put(Context.PROVIDER_URL, "corbaloc::app1:9811,:app2:9812"); Context initialContext = new InitialContext(env);
// Look up the home interface using the JNDI name try { java.lang.Object ejbHome = initialContext.lookup("cell/clusters/EJBcluster/BeenThere");This is fault tolerant, so if one process goes down, another can be used as the naming provider, and the cluster can be accessed via the appropriate cell-based path in the lookup.
In the real world, application developers can further improve high availability and the workload management service for the stand-alone EJB client by adding HA and WLM logic to the above sample code. For example, developers can provide the code to dynamically control which bootstrap server should be used for the current client thread, controlling when to use the second bootstrap server, either through a round robin or random algorithm.