Enterprise Servlets and J2EE
Example 12-1 shows a servlet that displays all its environment entries, using the JNDI API to browse the java:comp/env context.
Example 12-1: Snooping the java:comp/env Context
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.naming.*;
public class EnvEntrySnoop extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter( );
try {
Context initCtx = new InitialContext( );
NamingEnumeration enum = initCtx.listBindings("java:comp/env");
// We're using JDK 1.2 methods; that's OK since J2EE requires JDK 1.2
while (enum.hasMore( )) {
Binding binding = (Binding) enum.next( );
out.println("Name: " + binding.getName( ));
out.println("Type: " + binding.getClassName( ));
out.println("Value: " + binding.getObject( ));
out.println( );
}
}
catch (NamingException e) {
e.printStackTrace(out);
}
}
}
Assuming the previous web.xml entry, the servlet would generate:
Name: mailPincode
Type: java.lang.Boolean
Value: false
Remember, a server that does not support J2EE is not required to support these tags or any of the tags we talk about in this section.
References to EJB Components
When the environment entry object is an EJB component, there's a special <ejb-ref> tag that must be used. It provides a way for servlets to get a handle to an EJB using an abstract name. The deployer ensures the availability of an appropriate bean at runtime based on the constraints given by the <ejb-ref> tag. The tag may contain a <description>, <ejb-ref-name>, <ejb-ref-type>, <home>, <remote>, and <ejb-link>. Here's a typical <ejb-ref>:
<ejb-ref>
<description>Cruise ship cabin</description>
<ejb-ref-name>ejb/CabinHome</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>com.titan.cabin.CabinHome</home>
<remote>com.titan.cabin.Cabin</remote>
</ejb-ref>
These tags also have similar counterparts in EJB, and in fact this example is borrowed from the book Enterprise JavaBeans by Richard Monson-Haefel (O'Reilly). The <description> supports the deployer and is optional but recommended. The <ejb-ref-name> dictates the JNDI lookup name. It's recommended (but not required) that the name be placed within the ejb/ subcontext, making the full path to the bean java:comp/env/ejb/CabinHome. The <ejb-ref-type> must have a value of either Entity or Session, the two types of EJB components (see sidebar).
Finally, the <home> element specifies the fully qualified class name of the EJB's home interface, while the <remote> element specifies the FQCN of the EJB's remote interface.
A servlet would obtain a reference to the Cabin bean with the following code:
InitialContext initCtx = new InitialContext( );
Object ref = initCtx.lookup("java:comp/env/ejb/CabinHome");
CabinHome home =
(CabinHome) PortableRemoteObject.narrow(ref, CabinHome.class);
If the assembler writing the web.xml file has a specific EJB component in mind for an EJB reference, that information can be conveyed to the deployer with the addition of the optional <ejb-link> element. The <ejb-link> element should refer to the <ejb-name> of an EJB component registered in an EJB deployment descriptor within the same J2EE application. The deployer has the option to use the suggestion or override it. Here's an updated web.xml entry:
<ejb-ref>
<description>Cruise ship cabin</description>
<ejb-ref-name>ejb/CabinHome</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>com.titan.cabin.CabinHome</home>
<remote>com.titan.cabin.Cabin</remote>
<ejb-link>CabinBean</ejb-link>
</ejb-ref>
References to External Resource Factories
Finally, for those times when the environment entry is a resource factory, there's a <resource-ref> tag to use. A factory is an object that creates other objects on demand. A resource factory creates resource objects, such as database connections or message queues.
The <resource-ref> tag may contain a <description>, <res-ref-name>, <res-type>, and <res-auth>. Here's a typical <resource-ref>:
<resource-ref>
<description>Primary database</description>
<res-ref-name>jdbc/primaryDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>CONTAINER</res-auth>
</resource-ref>
The <description> again supports the deployer and is optional but recommended. The <res-ref-name> dictates the JNDI lookup name. It's recommended but not required to place the resource factories under a subcontext that describes the resource type:
jdbc/ for a JDBC javax.sql.DataSource factory
jms/ for a JMS javax.jms.QueueConnectionFactory or javax.jms.TopicConnectionFactory
mail/ for a JavaMail javax.mail.Session factory
url/ for a java.net.URL factory
The <res-type> element specifies the FQCN of the resource factory (not the created resource). The factory types in the preceding list are the standard types. A server has the option to support additional types; user factories cannot be used. The upcoming J2EE 1.3 specification proposes a "connector" mechanism to extend this model for user-defined factories.