[ Team LiB ] |
![]() ![]() |
Recipe 25.8 Accessing an EJB Using the WebLogic JNDI TreeProblemYou want to access an Enterprise JavaBean (EJB) from a servlet on WebLogic. SolutionFind out the EJB's JNDI name and use the javax.naming package to get a reference to the EJBObject or remote interface so that you can call the EJB's methods. DiscussionA servlet accesses an EJB by using a specified JNDI name. The process is therefore transparent to the servlet developer. Any EJBs an application uses comprise the business tier of an application. The servlets and JSPs represent the web tier within the multi-tiered distributed architecture of a typical Java 2 Enterprise Edition (J2EE) application. All you need to know is the JNDI name associated with the EJB in order to use the EJB in your programs.
You should be aware of the EJB's business methods, but do not have to be an expert on the javax.ejb package to use the EJB. Example 25-13 shows the source code for a stateless session EJB that is managed by BEA WebLogic 7.0 application server. Example 25-13 provides a java.util.Map that links U.S. state names with their postal abbreviations. The session bean includes one business method, getAbbreviation( ), which receives a state name as a parameter and returns its postal abbreviation. Example 25-13. The stateless session EJBpackage com.jspservletcookbook; import javax.ejb.*; import java.util.Map; import java.util.HashMap; public class AbbrevBean implements SessionBean{ private SessionContext context; private Map abbrevMap; public AbbrevBean( ){ //the bean's no-arguments constructor //A Map containing the names of states and abbreviations abbrevMap = new HashMap( ); abbrevMap.put("ALABAMA","AL"); abbrevMap.put("ALASKA","AK"); abbrevMap.put("AMERICAN SAMOA","AS"); abbrevMap.put("ARIZONA","AZ"); abbrevMap.put("ARKANSAS","AR"); abbrevMap.put("CALIFORNIA","CA"); abbrevMap.put("COLORADO","CO"); abbrevMap.put("CONNECTICUTT","CT"); abbrevMap.put("DELAWARE","DE"); abbrevMap.put("DISTRICT OF COLUMBIA","DC"); abbrevMap.put("FEDERATED STATES OF MICRONESIA","FM"); abbrevMap.put("FLORIDA","FL"); abbrevMap.put("GEORGIA","GA"); abbrevMap.put("GUAM","GU"); abbrevMap.put("HAWAII","HI"); abbrevMap.put("IDAHO","ID"); abbrevMap.put("ILLINOIS","IL"); abbrevMap.put("INDIANA","IN"); abbrevMap.put("IOWA","IA"); abbrevMap.put("KANSAS","KS"); abbrevMap.put("KENTUCKY","KY"); abbrevMap.put("LOUISIANA","LA"); abbrevMap.put("MAINE","ME"); abbrevMap.put("MARSHALL ISLANDS","MH"); abbrevMap.put("MARYLAND","MD"); abbrevMap.put("MASSACHUSETTS","MA"); abbrevMap.put("MICHIGAN","MI"); abbrevMap.put("MINNESOTA","MN"); abbrevMap.put("MISSISSIPPI","MS"); abbrevMap.put("MISSOURI","MO"); abbrevMap.put("MONTANA","MT"); abbrevMap.put("NEBRASKA","NE"); abbrevMap.put("NEVADA","NV"); abbrevMap.put("NEW HAMPSHIRE","NH"); abbrevMap.put("NEW JERSEY","NJ"); abbrevMap.put("NEW MEXICO","NM"); abbrevMap.put("NEW YORK","NY"); abbrevMap.put("NORTH CAROLINA","NC"); abbrevMap.put("NORTH DAKOTA","ND"); abbrevMap.put("NORTHERN MARIANA ISLANDS","MP"); abbrevMap.put("OKLAHOMA","OK"); abbrevMap.put("OREGON","OR"); abbrevMap.put("PALAU","PW"); abbrevMap.put("PENNSYLVANIA","PA"); abbrevMap.put("PUERTO RICO","PR"); abbrevMap.put("RHODE ISLAND","RI"); abbrevMap.put("SOUTH CAROLINA","SC"); abbrevMap.put("SOUTH DAKOTA","SD"); abbrevMap.put("TENNESSEE","TN"); abbrevMap.put("TEXAS","TX"); abbrevMap.put("UTAH","UT"); abbrevMap.put("VERMONT","VT"); abbrevMap.put("VIRGIN ISLANDS","VI"); abbrevMap.put("VIRGINIA","VA"); abbrevMap.put("WASHINGTON","WA"); abbrevMap.put("WEST VIRGINIA","WV"); abbrevMap.put("WISCONSIN","WI"); abbrevMap.put("WYOMING","WY"); }//constructor public void setSessionContext(SessionContext ctx) throws EJBException { context = ctx; }//setSessionContext public Map getAbbrevMap( ){ return abbrevMap; } //The bean's business method public String getAbbreviation(String state){ return (String) abbrevMap.get(state); } //javax.ejb.SessionBean method; it has to be implemented in a session //bean, but is not relevant to Stateless session beans. public void ejbActivate( ){} //javax.ejb.SessionBean method; it has to be implemented in a Session //bean, but is not relevant to stateless session beans. public void ejbPassivate( ){} //javax.ejb.SessionBean method; public void ejbRemove( ) {} } Example 25-13 could easily be implemented as an ordinary Java helper or utility class. However, I show a simple example of an EJB so that the recipe can focus on how a servlet connects to these objects. EJBs have a deployment descriptor, similar to the web.xml file that web applications use. The EJB deployment descriptor must be named ejb-jar.xml . When you package the EJB(s) before they are deployed on an application server, include this deployment descriptor as part of the archive. The ejb-jar.xml file describes the related EJB component(s); the application server uses this descriptive information in order to properly deploy the EJB. For example, the ejb-jar.xml file in Example 25-14 specifies the type of EJB (e.g., stateless session bean) and the fully qualified class names of its related Java classes, such as its remote interface. Example 25-14. The ejb-jar.xml file<?xml version="1.0"?>
<!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>
<enterprise-beans>
<session>
<ejb-name>AbbreviationEjb</ejb-name>
<home>com.jspservletcookbook.AbbrevHome</home>
<remote>com.jspservletcookbook.Abbrev</remote>
<local-home>com.jspservletcookbook.AbbrevLocalHome</local-home>
<local>com.jspservletcookbook.AbbrevLocal</local>
<ejb-class>com.jspservletcookbook.AbbrevBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
The package that contains this EJB, and with which the EJB is deployed on the application server, is a JAR file named myejb.jar (just a name I concocted; you do not have to use the same name). Since this stateless session bean is deployed on BEA WebLogic Server, the JAR file must include a vendor-specific deployment descriptor named weblogic-ejb-jar.xml. This deployment descriptor gives the deployer the opportunity to configure several aspects of how the EJB is deployed on WebLogic, such as the JNDI names of its home and local home interfaces.
You will encounter the home object's JNDI name in the servlet depicted later on in this recipe.
Example 25-15 shows the weblogic-ejb-jar.xml deployment descriptor for our stateless session bean. Example 25-15. The weblogic-ejb-jar.xml file<!DOCTYPE weblogic-ejb-jar PUBLIC
'-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN'
'http://www.bea.com/servers/wls700/dtd/weblogic-ejb-jar.dtd'>
<weblogic-ejb-jar>
<weblogic-enterprise-bean>
<ejb-name>AbbreviationEjb</ejb-name>
<stateless-session-descriptor>
<pool>
<initial-beans-in-free-pool>1</initial-beans-in-free-pool>
</pool>
</stateless-session-descriptor>
<jndi-name>AbbrevHome</jndi-name>
<local-jndi-name>AbbrevLocalHome</local-jndi-name>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
An EJB module is a complicated package that includes bean classes, remote interfaces, and two different deployment descriptors. Example 25-16 shows the contents of the myejb.jar file. I use the jar tvf myejb.jar. command in a command-line window to display the contents of the specified JAR file (it works in both Unix and Windows). Example 25-16. The contents of the ejb-jar.xml fileH:\book\cookbook\code\chap27\src\ejbs\ejbjar>jar tvf myejb.jar META-INF/ META-INF/MANIFEST.MF com/ com/jspservletcookbook/ com/jspservletcookbook/Abbrev.class com/jspservletcookbook/AbbrevBean.class com/jspservletcookbook/AbbrevHome.class com/jspservletcookbook/AbbrevLocal.class com/jspservletcookbook/AbbrevLocalHome.class META-INF/ejb-jar.xml META-INF/weblogic-ejb-jar.xml In Example 25-16, the session bean is AbbrevBean.class, the remote interface is Abbrev.class, and the home object (the factory for EJB objects that implement the Abbrev interface) is AbbrevHome.class. Finally, Example 25-17 shows the servlet that uses the session bean from Example 25-13. The code is self-explanatory. The important thing to remember is that the servlet receivese a reference to the AbbrevHome object from the WebLogic JNDI tree. Then the servlet, in its doGet( ) method, calls the AbbrevHome object's create( ) method to get an instance of the session bean's remote interface (in this example, it's an Abbrev type ). Example 25-17. A servlet that accesses the EJB on WebLogic using JNDIpackage com.jspservletcookbook; import java.io.IOException; import java.io.PrintWriter; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; import javax.servlet.*; import javax.servlet.http.*; public class WebJndiServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { //The request parameter looks like 'state=Massachusetts' String state = request.getParameter("state"); Context env = null; Abbrev abbrev = null; AbbrevHome home = null; try{ env = (Context) new InitialContext( ); //Look up the home or factory object on the WebLogic JNDI tree Object localH = env.lookup("AbbrevHome"); //This method call is necessary for EJB code that uses a //technology called RMI-IIOP home = (AbbrevHome) PortableRemoteObject.narrow(localH, AbbrevHome.class); //close the InitialContext env.close( ); if (home == null) throw new ServletException( "AbbrevHome is an unknown JNDI object"); //Get the remote interface by calling the home object's create( ) //method abbrev = (Abbrev) PortableRemoteObject.narrow(home.create( ), Abbrev.class); } catch (NamingException ne) { try{ env.close( );} catch (NamingException nex) { } throw new ServletException(ne); } catch (javax.ejb.CreateException ce) { throw new ServletException(ce); } //set the MIME type of the response, "text/html" response.setContentType("text/html"); java.io.PrintWriter out = response.getWriter( ); out.println("<html><head>"); out.println("<title>State abbreviations</title></head><body>"); out.println("<h2>Here is the state's abbreviation</h2>"); //Call the EJBObject's getAbbreviation( ) method; the EJBObject //delegates this method call to the session bean. Put the request //parameter in all upper-case, because this is how the session bean's //java.util.Map stores the state names, which are the Map's keys if (state != null) out.println( abbrev.getAbbreviation(state.toUpperCase( )) ); try{ //The servlet is through with the EJBObject; call its remove( ) //method abbrev.remove( ); } catch (javax.ejb.RemoveException re){} out.println("</body></html>"); }//doGet public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { doGet(request, response); }//doPost }//WebJndiServlet The value of the abbreviation for a state such as "Oregon" is ultimately retrieved on the server side by calling the session bean's getAbbreviation( ) method. Figure 25-8 shows a web browser window after a user has requested the servlet. The URL looks something like http://localhost:7001/webjndi?state=Oregon. The URL pattern /webjndi is mapped in web.xml to the servlet of Example 25-17. Figure 25-8. An EJB-accessing servlet's web browser display![]() See AlsoRecipe 25.4 on configuring a JNDI object with WebLogic; Recipe 25.6 on accessing a JNDI object with a servlet on WebLogic; Chapter 2 on deploying web components with WebLogic; a web link for the javax.ejb API: http://java.sun.com/j2ee/1.4/docs/api/javax/ejb/package-summary.html; the documentation page for WebLogic Server 7.0: http://edocs.bea.com/wls/docs70/index.html; a link to J2EE tutorials, including an Enterprise JavaBean tutorial: http://java.sun.com/j2ee/tutorial/index.html; Enterprise JavaBeans, Third Edition (O'Reilly); J2EE Design Patterns (O'Reilly). |
[ Team LiB ] |
![]() ![]() |