|
Return to article.
To determine what steps are needed to make independent deployment work, we must first consider the implementation of a subset of these steps. In particular, we need to examine how local references work and how they are bound at deployment time to a global JNDI name. We'll begin by examining the code that would reside in both the Timesheet servlet and the Vacation servlet example -- the piece of code that actually retrieves the reference to the EmployeeManagementFacade EJB component:
Listing 1. Obtaining an EJB component from a local reference
EmployeeManagementFacade facade = null;
try {
InitialContext initCtx = new InitialContext();
Object obj =
initCtx.lookup("java:comp/env/ejb/EmployeeManagementFacade");
EmployeeManagementFacadeHome facadeHome =
(EmployeeManagementFacadeHome)
javax.rmi.PortableRemoteObject.narrow
(obj,EmployeeManagementFacadeHome.class);
facade = facadeHome.create();
} catch (Exception e) {
System.out.println("Exception caught " + e);
// handle the error in whichever way is appropriate...
}
|
First, note what is used as the parameter to the lookup method of the InitialContext class. Here we are using a local JNDI reference -- indicated by the fact that it is retrieving the reference from the context java:comp/env. A global JNDI reference does not begin with this naming convention. Global JNDI references
are common in older code examples developed prior to the development of local JNDI references in the EJB 1.1 specification, but most books on EJB technology have been updated to reflect the fact that using local references is a best practice (see Resources for more information).
The local reference is declared in either the web.xml file or the ejb-jar.xml file, depending upon whether this piece of code is located within a servlet or JSP page (indicating that it should be part of the web.xml file) or another EJB component (indicating that it should be located within the ejb-jar.xml file). In our case, because this code is being used within a servlet, it is within the web.xml file. Listing 2 shows the specific section of the web.xml file for the Benefits application:
Listing 2. Sample web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app id="WebApp">
<display-name>BenefitsWeb</display-name>
<servlet>
<servlet-name>VacationServlet</servlet-name>
<display-name>VacationServlet</display-name>
<servlet-class>com.ibm.servlets.VacationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>VacationServlet</servlet-name>
<url-pattern>/VacationServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<ejb-ref id="EjbRef_1036619390589">
<description>EmployeeFacade</description>
<ejb-ref-name>ejb/EmployeeManagementFacade</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>com.ibm.ejbs.EmployeeManagementFacadeHome</home>
<remote>com.ibm.ejbs.EmployeeManagementFacade</remote>
<ejb-link>DeploymentExampleEJB.jar#EmployeeManagementFacade</ejb-link>
</ejb-ref>
</web-app>
|
This code includes the declaration of the portion of the EJB name used after java:comp/env -- in particular, the <ejb-ref-name> tag makes up this second part
of the total JNDI name. However, it simply says that there is an EJB component of this type (as referenced by the
home and remote type and the ejb-link to the EJB-JAR file that contains the definition of the EJB component) available under this name -- it doesn't actually give any indication of what particular EJB component this reference refers to. To understand how that works, we need to examine a few additional files and the relationships between them. In particular, look at Listing 3 to see what is in the ejb-jar.xml file for the Timesheet example:
Listing 3. Sample ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.
//DTD Enterprise JavaBeans 2.0//EN"
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar id="ejb-jar_ID">
<display-name>DeploymentExampleEJB</display-name>
<enterprise-beans>
<session id="EmployeeManagementFacade">
<ejb-name>EmployeeManagementFacade</ejb-name>
<home>com.ibm.ejbs.EmployeeManagementFacadeHome</home>
<remote>com.ibm.ejbs.EmployeeManagementFacade</remote>
<ejb-class>com.ibm.ejbs.EmployeeManagementFacadeBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
|
Note that nowhere in this file is the JNDI name of the EJB component declared. This is something that often confuses people. They look at the ejb-name of the enterprise bean and assume that it is the same as the JNDI name of the EJB component. In fact, these two things are not related -- the EJB-JAR file does not even address the JNDI names of EJB components. The ejb-name element is only meant to be a unique name for this EJB component within an EJB-JAR file. It is used (among other things) to establish EJB relationships between entity beans and to declare security and transaction attributes on EJB methods. Setting the JNDI name of a bean is entirely outside the scope of the EJB-JAR file. In fact, page 466 of the EJB 2.0 specification (see Resources) specifically states in the
declaration of the ejb-name element in the EJB-JAR DTD:
There is no architected relationship between the ejb-name in the deployment descriptor and the JNDI name that the deployer will assign to the enterprise bean's home.
It can't get any clearer than that.
So where is the JNDI name assigned? The full answer to this depends on the particular version of WebSphere Application Server you are using. In Application Server, Version 4.0 Advanced Edition, the JNDI names are stored in the shared administrative database, as discussed in the main article. However, in Application Server, Version 4.0 Advanced Single Server Edition, and Application Server, Version 5.0, they are stored in a set of XML files used by the JNDI naming
service of Application Server. These files (called binding files) are created during the deployment process or with tools like
Application Assembly Tool (AAT) or WebSphere Studio Application Developer. As an example, Listing 4 shows the binding file for the EJB-JAR. This particular file is named ibm-ejb-jar-bnd.xmi and can be found in the META-INF directory of the EJB-JAR file. Note that this is an example of the binding file in Application Server 5.0 (as is the second binding file example shown in Listing 5).
Listing 4. IBM EJB-JAR bindings file
<?xml version="1.0" encoding="UTF-8"?>
<ejbbnd:EJBJarBinding xmi:version="2.0"
xmlns:xmi="http://www.omg.org/technology/documents/formal/xmi.htm"
xmlns:ejbbnd="ejbbnd.xmi" xmlns:ejb="ejb.xmi"
xmi:id="EJBJarBinding_1036618719334">
<ejbJar href="META-INF/ejb-jar.xml#ejb-jar_ID"/>
<ejbBindings xmi:id="EmployeeManagementFacade_Bnd"
jndiName="ejb/EmployeeManagementFacade">
<enterpriseBean xmi:type="ejb:Session"
href="META-INF/ejb-jar.xml#EmployeeManagementFacade"/>
</ejbBindings>
</ejbbnd:EJBJarBinding>
|
We're only going to point out a few features of this file (which is far too complicated to cover in depth here). Note in particular that this file declares a reference to a particular EJB component within the corresponding EJB-JAR file (note the HREF inside the enterpriseBean element to EmployeeManagementFacade). That reference then is connected to a particular JNDI name (declared in the jndiName attribute of the ejbBindings element) in the global JNDI namespace. So, what we have is the connection shown in Figure 1:
Figure 1. Mapping EJB names to JNDI names

But how is this reference connected to the local JNDI name used in the sample code and declared in the web.xml file? The magic occurs through yet another Bindings file, this one corresponding to the Web application. This bindings file is called ibm-web-bnd.xmi and is located (again) in the META-INF directory of the WAR file. The contents of this file are shown in Listing 5:
Listing 5. IBM Web-XML bindings file
<?xml version="1.0" encoding="UTF-8"?>
<webappbnd:WebAppBinding xmi:version="2.0"
xmlns:xmi="http://www.omg.org/technology/documents/formal/xmi.htm"
xmlns:webappbnd="webappbnd.xmi"
xmlns:webapplication="webapplication.xmi"
xmlns:commonbnd="commonbnd.xmi"
xmlns:common="common.xmi"
xmi:id="WebAppBinding_1" virtualHostName="default_host">
<webapp href="WEB-INF/web.xml#WebApp"/>
<ejbRefBindings
xmi:id="EjbRefBinding_1036619390589"
jndiName="ejb/EmployeeManagementFacade">
<bindingEjbRef href=
"WEB-INF/web.xml#EjbRef_1036619390589"/>
</ejbRefBindings>
</webappbnd:WebAppBinding>
|
Again, we won't go into the details of the format of this file, but we do want to point out one feature. In this case, there is a link established between declaration of the local JNDI name in the web.xml file (evidenced by the bindingEjbRef element in the file shown in Listing 6) and the global JNDI name referenced in the ejbRefBindings element. The final configuration looks something like Figure 2:
Figure 2. Full JNDI name mapping

Here you see that the IBM-EJB-JAR-BND binding files can be used as input to determine what the JNDI names in the global JNDI namespace should be. Likewise the IBM-WEB-BND binding file is used to determine how the local JNDI names referenced in the web.xml file should map to names in the global JNDI namespace. This now demonstrates how independent deployment will work: in order to deploy the same EJB type twice into the same application server or cluster, the only thing that must change is the binding files. As long as the global JNDI names are unique and the binding files point to the correct global names, there is no limit as to how many times a single component can be deployed.
Return to article.

|