JNDI can also be used to access an EJB but using this technique is not as easy as DI. The Salutation
EJB from the first recipe and the servlet from the second recipe are used to illustrate this technique.
To use JNDI in a client:
A portable JNDI name syntax has been added to EJB 3.1. We will use this syntax as it makes the use of JNDI less dependent on the deployment server.
The modification of the SalutationServlet
involves removing the @EJB annotation and adding code to perform the JNDI look up. This code is placed immediately before the servlet's try
block.
... Context context = null; try { context = new InitialContext(); salutation = (Salutation) context.lookup( "java:global/SalutationApplication/ SalutationApplication-ejb/Salutation"); } catch (Exception e) { e.printStackTrace(); } ...
In order to initialize and assign an instance of the bean to the salutation
variable, the bean needed to be looked up using an object implementing the Context
interface. The Context
interface provided the information necessary to locate the server and to create a reference to a Salutation
object. First, we needed to create an InitialContext
object. This class implemented the Context
interface. Exceptions resulting from the creation of the InitialContext
object and the subsequent lookup
method were caught.
Once the Context
has been established, the Context
object's lookup
method was invoked and a reference to the Salutation
EJB was provided. The lookup
method used a portable JNDI name to identify the EJB. In this case, a global name was used.
The syntax starts with one of three different prefixes. In this example the prefix was java:global
specifying a global name. Following the prefix is a series of names separated by forward slashes. The first name was the name of the application, SalutationApplication
. The second name was the name of the JAR file where the bean is held, SalutationApplication-ejb
. The name of the bean was the last name. Names are automatically generated for EJBs.
Prior to EJB 3.1, a JNDI name was server-specific and limited the portability of EJBS. With EJB 3.1 this problem goes away and we can create more portable and maintainable applications.
There are two features of JNDI needing further scrutiny.
JNDI is used to look up resources such as session beans within an application and across the network. A JNDI server allows resources to be registered and then clients can look up and use these resources. Each EJB is automatically assigned a unique name by the server though it is possible to assign a specific name if desired. This name is then combined with one of three JNDI namespace prefixes to form a complete portable JNDI name.
The following table details the string prefixes and implications.
String prefix |
Visibility of the resulting name |
---|---|
"java:global/" |
A globally accessible name |
"java:app/" |
Can only be seen by code in the same application |
"java:module/" |
Can only be seen by code in the same module |
A Java EE application is organized around a series of JAR files. An EJB may be packaged in either an application-ejb.jar
or an application-war.war
file. The application-ejb.jar
can also be packaged within the application.ear
file.
Let's look at the syntax for portable global session beans in more detail.
java:global[/<app-name>]/<module-name>/<bean-name>
There are three sections that follow the java:global
prefix:
<app-name>—This
name is optional and is only used if the bean is packaged in an .ear
file. The<app-name>
is the name of the .ear
file minus the file extension. The<app-name>
can also be specified in the application.xml
file.<module-name>—This
is the name of the ejb-jar
file or the .war
file containing the bean excluding its extension. An explicit name can be specified for the<module-name>
using either the ejb-jar.xml
or web.xml
files.<bean-name>—This
is the name of the bean. As mentioned earlier, this name is automatically generated but can be given an alias.The JNDI name used is dependent on the location of the client in relationship to the EJB module. For example, the module namespace can be used for looking up names within the same module.
java:module/<bean-name>
The application namespace can be used for looking up names within the same application.
java:app[/<module-name>]/<bean-name>
Using more than one namespace can make our code more stable and less susceptible to breaking when code changes. For example, we could use a global namespace for a client and a bean within the same module.
java:global/app1/module1/bean1
If the client and bean are moved into a different module then this lookup will fail. However, if we had used the module namespace, the lookup would not fail.
java:module/bean1
Each of the JNDI names may be terminated with [/interface-name]
and are only required if the EJB implements more than one business interface. For example, a session bean may implement a local interface and a remote interface.
public class Salutation implements SalutationLocalInterface, SalutationRemoteInterface { }
Either of these two names could then be used:
java:global[/<app-name>]/<module-name>/Salutation/ SalutationLocalInterface java:global[/<app-name>]/<module-name>/Salutation/ SalutationRemoteInterface
3.137.174.23