| <?xml version="1.0"?> |
| <!DOCTYPE document [ |
| <!ENTITY project SYSTEM "project.xml"> |
| ]> |
| <document url="jndi-resources-howto.html"> |
| |
| &project; |
| |
| <properties> |
| <author email="craigmcc@apache.org">Craig R. McClanahan</author> |
| <author email="yoavs@apache.org">Yoav Shapira</author> |
| <title>JNDI Resources HOW-TO</title> |
| </properties> |
| |
| <body> |
| |
| |
| <section name="Introduction"> |
| |
| <p>Tomcat 5 provides a JNDI <strong>InitialContext</strong> implementation |
| instance for each web application running under it, in a manner that is |
| compatible with those provided by a |
| <a href="http://java.sun.com/j2ee">Java2 Enterprise Edition</a> application |
| server. |
| |
| The J2EE standard provides a standard set of elements in |
| the <code>/WEB-INF/web.xml</code> file to reference resources; resources |
| referenced in these elements must be defined in an application-server-specific configuration. |
| </p> |
| |
| <p>For Tomcat 5, these entries in per-web-application |
| <code>InitialContext</code> are configured in the |
| <code><strong><Context></strong></code> elements that can be specified |
| in either <code>$CATALINA_HOME/conf/server.xml</code> or, preferably, |
| the per-web-application context XML file (either <code>META-INF/context.xml</code>). |
| </p> |
| |
| <p>Tomcat 5 maintains a separate namespace of global resources for the |
| entire server. These are configured in the |
| <a href="config/globalresources.html"> |
| <code><strong><GlobalNameingResources></strong></code></a> element of |
| <code>$CATALINA_HOME/conf/server.xml</code>. You may expose these resources to |
| web applications by using |
| <code><strong><ResourceLink></strong></code> elements. |
| </p> |
| |
| <p>The resources defined in these elements |
| may be referenced by the following elements in the web application deployment |
| descriptor (<code>/WEB-INF/web.xml</code>) of your web application:</p> |
| <ul> |
| <li><code><strong><env-entry></strong></code> - Environment entry, a |
| single-value parameter that can be used to configure how the application |
| will operate.</li> |
| <li><code><strong><resource-ref></strong></code> - Resource reference, |
| which is typically to an object factory for resources such as a JDBC |
| <code>DataSource</code>, a JavaMail <code>Session</code>, or custom |
| object factories configured into Tomcat 5.</li> |
| <li><code><strong><resource-env-ref></strong></code> - Resource |
| environment reference, a new variation of <code>resource-ref</code> |
| added in Servlet 2.4 that is simpler to configure for resources |
| that do not require authentication information.</li> |
| </ul> |
| |
| <p>The <code>InitialContext</code> is configured as a web application is |
| initially deployed, and is made available to web application components (for |
| read-only access). All configured entries and resources are placed in |
| the <code>java:comp/env</code> portion of the JNDI namespace, so a typical |
| access to a resource - in this case, to a JDBC <code>DataSource</code> - |
| would look something like this:</p> |
| |
| <source> |
| // Obtain our environment naming context |
| Context initCtx = new InitialContext(); |
| Context envCtx = (Context) initCtx.lookup("java:comp/env"); |
| |
| // Look up our data source |
| DataSource ds = (DataSource) |
| envCtx.lookup("jdbc/EmployeeDB"); |
| |
| // Allocate and use a connection from the pool |
| Connection conn = ds.getConnection(); |
| ... use this connection to access the database ... |
| conn.close(); |
| </source> |
| |
| <p>See the following Specifications for more information about programming APIs |
| for JNDI, and for the features supported by Java2 Enterprise Edition (J2EE) |
| servers, which Tomcat emulates for the services that it provides:</p> |
| <ul> |
| <li><a href="http://java.sun.com/products/jndi/#download">Java Naming and |
| Directory Interface</a> (included in JDK 1.4, available separately for |
| prior JDK versions)</li> |
| <li><a href="http://java.sun.com/j2ee/download.html">J2EE Platform |
| Specification</a> (in particular, see Chapter 5 on <em>Naming</em>)</li> |
| </ul> |
| |
| </section> |
| |
| |
| <section name="Configuring JNDI Resources"> |
| |
| <p>Each available JNDI Resource is configured based on inclusion of the |
| following elements in the <code><strong><Context></strong></code> or |
| <code><strong><DefaultContext></strong></code> elements:</p> |
| |
| <ul> |
| <li><a href="config/context.html#Environment Entries"><Environment></a> - |
| Configure names and values for scalar environment entries that will be |
| exposed to the web application through the JNDI |
| <code>InitialContext</code> (equivalent to the inclusion of an |
| <code><env-entry></code> element in the web application |
| deployment descriptor).</li> |
| <li><a href="config/context.html#Resource Definitions"><Resource></a> - |
| Configure the name and data type of a resource made available to the |
| application (equivalent to the inclusion of a |
| <code><resource-ref></code> element in the web application |
| deployment descriptor).</li> |
| <li><a href="config/context.html#Resource Links"><ResourceLink></a> - |
| Add a link to a resource defined in the global JNDI context. Use resource |
| links to give a web application access to a resource defined in |
| the<a href="config/globalresources.html"><GlobalNamingResources></a> |
| child element of the <a href="config/server.html"><Server></a> |
| element.</li> |
| |
| </ul> |
| |
| <p>Any number of these elements may be nested inside a |
| <a href="config/context.html"><Context></a> element (to be associated |
| only with that particular web application).</p> |
| |
| <p>In addition, the names and values of all <code><env-entry></code> |
| elements included in the web application deployment descriptor |
| (<code>/WEB-INF/web.xml</code>) are configured into the initial context as |
| well, overriding corresponding values from <code>conf/server.xml</code> |
| <strong>only</strong> if allowed by the corresponding |
| <code><Environment></code> element (by setting the |
| <code>override</code> attribute to "true").</p> |
| |
| <p>Global resources can be defined in the server-wide JNDI context, by adding |
| the resource elements described above to the |
| <a href="config/globalresources.html"><GlobalNamingResources></a> |
| child element of the <a href="config/server.html"><Server></a> |
| element and using a |
| <a href="config/context.html#Resource Links"><ResourceLink></a> to |
| include it in the per-web-application context.</p> |
| |
| </section> |
| |
| |
| <section name="Tomcat Standard Resource Factories"> |
| |
| <p>Tomcat 5 includes a series of standard resource factories that can |
| provide services to your web applications, but give you configuration |
| flexibility (in <code>$CATALINA_HOME/conf/server.xml</code>) without |
| modifying the web application or the deployment descriptor. Each |
| subsection below details the configuration and usage of the standard |
| resource factories.</p> |
| |
| <p>See <a href="#Adding Custom Resource Factories">Adding Custom |
| Resource Factories</a> for information about how to create, install, |
| configure, and use your own custom resource factory classes with |
| Tomcat 5.</p> |
| |
| <p><em>NOTE</em> - Of the standard resource factories, only the |
| "JDBC Data Source" and "User Transaction" factories are mandated to |
| be available on other platforms, and then they are required only if |
| the platform implements the Java2 Enterprise Edition (J2EE) specs. |
| All other standard resource factories, plus custom resource factories |
| that you write yourself, are specific to Tomcat and cannot be assumed |
| to be available on other containers.</p> |
| |
| <subsection name="Generic JavaBean Resources"> |
| |
| <h3>0. Introduction</h3> |
| |
| <p>This resource factory can be used to create objects of <em>any</em> |
| Java class that conforms to standard JavaBeans naming conventions (i.e. |
| it has a zero-arguments constructor, and has property setters that |
| conform to the setFoo() naming pattern. The resource factory will |
| create a new instance of the appropriate bean class every time a |
| <code>lookup()</code> for this entry is made.</p> |
| |
| <p>The steps required to use this facility are described below.</p> |
| |
| <h3>1. Create Your JavaBean Class</h3> |
| |
| <p>Create the JavaBean class which will be instantiated each time |
| that the resource factory is looked up. For this example, assume |
| you create a class <code>com.mycompany.MyBean</code>, which looks |
| like this:</p> |
| |
| <source> |
| package com.mycompany; |
| |
| public class MyBean { |
| |
| private String foo = "Default Foo"; |
| |
| public String getFoo() { |
| return (this.foo); |
| } |
| |
| public void setFoo(String foo) { |
| this.foo = foo; |
| } |
| |
| private int bar = 0; |
| |
| public int getBar() { |
| return (this.bar); |
| } |
| |
| public void setBar(int bar) { |
| this.bar = bar; |
| } |
| |
| |
| } |
| </source> |
| |
| <h3>2. Declare Your Resource Requirements</h3> |
| |
| <p>Next, modify your web application deployment descriptor |
| (<code>/WEB-INF/web.xml</code>) to declare the JNDI name under which |
| you will request new instances of this bean. The simplest approach is |
| to use a <code><resource-env-ref></code> element, like this:</p> |
| |
| <source> |
| <resource-env-ref> |
| <description> |
| Object factory for MyBean instances. |
| </description> |
| <resource-env-ref-name> |
| bean/MyBeanFactory |
| </resource-env-ref-name> |
| <resource-env-ref-type> |
| com.mycompany.MyBean |
| </resource-env-ref-type> |
| </resource-env-ref> |
| </source> |
| |
| <p><strong>WARNING</strong> - Be sure you respect the element ordering |
| that is required by the DTD for web application deployment descriptors! |
| See the |
| <a href="http://java.sun.com/products/servlet/download.html">Servlet |
| Specification</a> for details.</p> |
| |
| <h3>3. Code Your Application's Use Of This Resource</h3> |
| |
| <p>A typical use of this resource environment reference might look |
| like this:</p> |
| |
| <source> |
| Context initCtx = new InitialContext(); |
| Context envCtx = (Context) initCtx.lookup("java:comp/env"); |
| MyBean bean = (MyBean) envCtx.lookup("bean/MyBeanFactory"); |
| |
| writer.println("foo = " + bean.getFoo() + ", bar = " + |
| bean.getBar()); |
| </source> |
| |
| <h3>4. Configure Tomcat's Resource Factory</h3> |
| |
| <p>To configure Tomcat's resource factory, add an elements like this to the |
| <code>$CATALINA_HOME/conf/server.xml</code> file, nested inside the |
| <code>Context</code> element for this web application.</p> |
| <source> |
| <Context ...> |
| ... |
| <Resource name="bean/MyBeanFactory" auth="Container" |
| type="com.mycompany.MyBean" |
| factory="org.apache.naming.factory.BeanFactory" |
| bar="23"/> |
| ... |
| </Context> |
| </source> |
| |
| <p>Note that the resource name (here, <code>bean/MyBeanFactory</code> |
| must match the value specified in the web application deployment |
| descriptor. We are also initializing the value of the <code>bar</code> |
| property, which will cause <code>setBar(23)</code> to be called before |
| the new bean is returned. Because we are not initializing the |
| <code>foo</code> property (although we could have), the bean will |
| contain whatever default value is set up by its constructor.</p> |
| |
| </subsection> |
| |
| |
| <subsection name="JavaMail Sessions"> |
| |
| <h3>0. Introduction</h3> |
| |
| <p>In many web applications, sending electronic mail messages is a |
| required part of the system's functionality. The |
| <a href="http://java.sun.com/products/javamail">Java Mail</a> API |
| makes this process relatively straightforward, but requires many |
| configuration details that the client application must be aware of |
| (including the name of the SMTP host to be used for message sending).</p> |
| |
| <p>Tomcat 5 includes a standard resource factory that will create |
| <code>javax.mail.Session</code> session instances for you, already |
| connected to the SMTP server that is configured in <code>server.xml</code>. |
| In this way, the application is totally insulated from changes in the |
| email server configuration environment - it simply asks for, and receives, |
| a preconfigured session whenever needed.</p> |
| |
| <p>The steps required for this are outlined below.</p> |
| |
| <h3>1. Declare Your Resource Requirements</h3> |
| |
| <p>The first thing you should do is modify the web application deployment |
| descriptor (<code>/WEB-INF/web.xml</code>) to declare the JNDI name under |
| which you will look up preconfigured sessions. By convention, all such |
| names should resolve to the <code>mail</code> subcontext (relative to the |
| standard <code>java:comp/env</code> naming context that is the root of |
| all provided resource factories. A typical <code>web.xml</code> entry |
| might look like this:</p> |
| <source> |
| <resource-ref> |
| <description> |
| Resource reference to a factory for javax.mail.Session |
| instances that may be used for sending electronic mail |
| messages, preconfigured to connect to the appropriate |
| SMTP server. |
| </description> |
| <res-ref-name> |
| mail/Session |
| </res-ref-name> |
| <res-type> |
| javax.mail.Session |
| </res-type> |
| <res-auth> |
| Container |
| </res-auth> |
| </resource-ref> |
| </source> |
| |
| <p><strong>WARNING</strong> - Be sure you respect the element ordering |
| that is required by the DTD for web application deployment descriptors! |
| See the |
| <a href="http://java.sun.com/products/servlet/download.html">Servlet |
| Specification</a> for details.</p> |
| |
| <h3>2. Code Your Application's Use Of This Resource</h3> |
| |
| <p>A typical use of this resource reference might look like this:</p> |
| <source> |
| Context initCtx = new InitialContext(); |
| Context envCtx = (Context) initCtx.lookup("java:comp/env"); |
| Session session = (Session) envCtx.lookup("mail/Session"); |
| |
| Message message = new MimeMessage(session); |
| message.setFrom(new InternetAddress(request.getParameter("from")); |
| InternetAddress to[] = new InternetAddress[1]; |
| to[0] = new InternetAddress(request.getParameter("to")); |
| message.setRecipients(Message.RecipientType.TO, to); |
| message.setSubject(request.getParameter("subject")); |
| message.setContent(request.getParameter("content"), "text/plain"); |
| Transport.send(message); |
| </source> |
| |
| <p>Note that the application uses the same resource reference name |
| that was declared in the web application deployment descriptor. This |
| is matched up against the resource factory that is configured in |
| <code>$CATALINA_HOME/conf/server.xml</code>, as described below.</p> |
| |
| <h3>3. Configure Tomcat's Resource Factory</h3> |
| |
| <p>To configure Tomcat's resource factory, add an elements like this to the |
| <code>$CATALINA_HOME/conf/server.xml</code> file, nested inside the |
| <code>Context</code> element for this web application.</p> |
| <source> |
| <Context ...> |
| ... |
| <Resource name="mail/Session" auth="Container" |
| type="javax.mail.Session" |
| mail.smtp.host="localhost"/> |
| ... |
| </Context> |
| </source> |
| |
| <p>Note that the resource name (here, <code>mail/Session</code>) must |
| match the value specified in the web application deployment descriptor. |
| Customize the value of the <code>mail.smtp.host</code> parameter to |
| point at the server that provides SMTP service for your network.</p> |
| |
| <h3>4. Install the JavaMail libraries</h3> |
| |
| <p><a href="http://java.sun.com/products/javamail/downloads/index.html" target="_blank"> |
| Download the JavaMail API</a>.</p> |
| |
| <p>This download includes 2 vital libraries for the configuration; |
| activation.jar and mail.jar. Unpackage the JavaMail distribution and place |
| them into $CATALINA_HOME/common/lib so that they are available to |
| Tomcat during the initialization of the mail Session Resource. |
| <strong>Note:</strong> placing these jars in both common/lib and a |
| web application's lib folder will cause an error, so ensure you have |
| them in the $CATALINA_HOME/common/lib location only. |
| </p> |
| |
| <h3>Example Application</h3> |
| |
| <p>The <code>/examples</code> application included with Tomcat contains |
| an example of utilizing this resource factory. It is accessed via the |
| "JSP Examples" link. The source code for the servlet that actually |
| sends the mail message is in |
| <code>/WEB-INF/classes/SendMailServlet.java</code>.</p> |
| |
| <p><strong>WARNING</strong> - The default configuration assumes that |
| there is an SMTP server listing on port 25 on <code>localhost</code>. |
| If this is not the case, edit the |
| <code>$CATALINA_HOME/conf/server.xml</code> file, and modify the |
| parameter value for the <code>mail.smtp.host</code> parameter to be |
| the host name of an SMTP server on your network.</p> |
| |
| </subsection> |
| |
| <subsection name="JDBC Data Sources"> |
| |
| <h3>0. Introduction</h3> |
| |
| <p>Many web applications need to access a database via a JDBC driver, |
| to support the functionality required by that application. The J2EE |
| Platform Specification requires J2EE Application Servers to make |
| available a <em>DataSource</em> implementation (that is, a connection |
| pool for JDBC connections) for this purpose. Tomcat 5 offers exactly |
| the same support, so that database-based applications you develop on |
| Tomcat using this service will run unchanged on any J2EE server.</p> |
| |
| <p>For information about JDBC, you should consult the following:</p> |
| <ul> |
| <li><a href="http://java.sun.com/products/jdbc/">http://java.sun.com/products/jdbc/</a> - |
| Home page for information about Java Database Connectivity.</li> |
| <li><a href="http://java.sun.com/j2se/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame.html">http://java.sun.com/j2se/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame.html</a> - |
| The JDBC 2.1 API Specification.</li> |
| <li><a href="http://java.sun.com/products/jdbc/jdbc20.stdext.pdf">http://java.sun.com/products/jdbc/jdbc20.stdext.pdf</a> - |
| The JDBC 2.0 Standard Extension API (including the |
| <code>javax.sql.DataSource</code> API). This package is now known |
| as the "JDBC Optional Package".</li> |
| <li><a href="http://java.sun.com/j2ee/download.html">http://java.sun.com/j2ee/download.html</a> - |
| The J2EE Platform Specification (covers the JDBC facilities that |
| all J2EE platforms must provide to applications).</li> |
| </ul> |
| |
| <p><strong>NOTE</strong> - The default data source support in Tomcat |
| is based on the <strong>DBCP</strong> connection pool from the |
| <a href="http://jakarta.apache.org/commons">Jakarta Commons</a> |
| subproject. However, it is possible to use any other connection pool |
| that implements <code>javax.sql.DataSource</code>, by writing your |
| own custom resource factory, as described |
| <a href="#Adding Custom Resource Factories">below</a>.</p> |
| |
| <h3>1. Install Your JDBC Driver</h3> |
| |
| <p>Use of the <em>JDBC Data Sources</em> JNDI Resource Factory requires |
| that you make an appropriate JDBC driver available to both Tomcat internal |
| classes and to your web application. This is most easily accomplished by |
| installing the driver's JAR file(s) into the |
| <code>$CATALINA_HOME/common/lib</code> directory, which makes the driver |
| available both to the resource factory and to your application.</p> |
| |
| <h3>2. Declare Your Resource Requirements</h3> |
| |
| <p>Next, modify the web application deployment descriptor |
| (<code>/WEB-INF/web.xml</code>) to declare the JNDI name under |
| which you will look up preconfigured data source. By convention, all such |
| names should resolve to the <code>jdbc</code> subcontext (relative to the |
| standard <code>java:comp/env</code> naming context that is the root of |
| all provided resource factories. A typical <code>web.xml</code> entry |
| might look like this:</p> |
| <source> |
| <resource-ref> |
| <description> |
| Resource reference to a factory for java.sql.Connection |
| instances that may be used for talking to a particular |
| database that is configured in the server.xml file. |
| </description> |
| <res-ref-name> |
| jdbc/EmployeeDB |
| </res-ref-name> |
| <res-type> |
| javax.sql.DataSource |
| </res-type> |
| <res-auth> |
| Container |
| </res-auth> |
| </resource-ref> |
| </source> |
| |
| <p><strong>WARNING</strong> - Be sure you respect the element ordering |
| that is required by the DTD for web application deployment descriptors! |
| See the |
| <a href="http://java.sun.com/products/servlet/download.html">Servlet |
| Specification</a> for details.</p> |
| |
| <h3>3. Code Your Application's Use Of This Resource</h3> |
| |
| <p>A typical use of this resource reference might look like this:</p> |
| <source> |
| Context initCtx = new InitialContext(); |
| Context envCtx = (Context) initCtx.lookup("java:comp/env"); |
| DataSource ds = (DataSource) |
| envCtx.lookup("jdbc/EmployeeDB"); |
| |
| Connection conn = ds.getConnection(); |
| ... use this connection to access the database ... |
| conn.close(); |
| </source> |
| |
| <p>Note that the application uses the same resource reference name |
| that was declared in the web application deployment descriptor. This |
| is matched up against the resource factory that is configured in |
| <code>$CATALINA_HOME/conf/server.xml</code>, as described below.</p> |
| |
| <h3>4. Configure Tomcat's Resource Factory</h3> |
| |
| <p>To configure Tomcat's resource factory, add an element like this to the |
| <code>/META-INF/context.xml</code> file in the web application.</p> |
| <source> |
| <Context ...> |
| ... |
| <Resource name="jdbc/EmployeeDB" auth="Container" |
| type="javax.sql.DataSource" username="dbusername" password="dbpassword" |
| driverClassName="org.hsql.jdbcDriver" url="jdbc:HypersonicSQL:database" |
| maxActive="8" maxIdle="4"/> |
| ... |
| </Context> |
| </source> |
| |
| <p>Note that the resource name (here, <code>jdbc/EmployeeDB</code>) must |
| match the value specified in the web application deployment descriptor.</p> |
| |
| <p>This example assumes that you are using the HypersonicSQL database |
| JDBC driver. Customize the <code>driverClassName</code> and |
| <code>driverName</code> parameters to match your actual database's |
| JDBC driver and connection URL.</p> |
| |
| <p>The configuration properties for Tomcat's standard data source |
| resource factory |
| (<code>org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory</code>) are |
| as follows:</p> |
| <ul> |
| <li><strong>driverClassName</strong> - Fully qualified Java class name |
| of the JDBC driver to be used.</li> |
| <li><strong>maxActive</strong> - The maximum number of active instances |
| that can be allocated from this pool at the same time.</li> |
| <li><strong>maxIdle</strong> - The maximum number of connections that |
| can sit idle in this pool at the same time.</li> |
| <li><strong>maxWait</strong> - The maximum number of milliseconds that the |
| pool will wait (when there are no available connections) for a |
| connection to be returned before throwing an exception.</li> |
| <li><strong>password</strong> - Database password to be passed to our |
| JDBC driver.</li> |
| <li><strong>url</strong> - Connection URL to be passed to our JDBC driver. |
| (For backwards compatibility, the property <code>driverName</code> |
| is also recognized.)</li> |
| <li><strong>user</strong> - Database username to be passed to our |
| JDBC driver.</li> |
| <li><strong>validationQuery</strong> - SQL query that can be used by the |
| pool to validate connections before they are returned to the |
| application. If specified, this query MUST be an SQL SELECT |
| statement that returns at least one row.</li> |
| </ul> |
| <p>For more details, please refer to the commons-dbcp documentation.</p> |
| |
| </subsection> |
| |
| </section> |
| |
| |
| <section name="Adding Custom Resource Factories"> |
| |
| <p>If none of the standard resource factories meet your needs, you can |
| write your own factory and integrate it into Tomcat 5, and then configure |
| the use of this factory in the <code>conf/server.xml</code> configuration |
| file. In the example below, we will create a factory that only knows how |
| to create <code>com.mycompany.MyBean</code> beans, from the |
| <a href="#Generic JavaBean Resources">Generic JavaBean Resources</a> |
| example, above.</p> |
| |
| <h3>1. Write A Resource Factory Class</h3> |
| |
| <p>You must write a class that implements the JNDI service provider |
| <code>javax.naming.spi.ObjectFactory</code> inteface. Every time your |
| web application calls <code>lookup()</code> on a context entry that is |
| bound to this factory, the <code>getObjectInstance()</code> method is |
| called, with the following arguments:</p> |
| <ul> |
| <li><strong>Object obj</strong> - The (possibly null) object containing |
| location or reference information that can be used in creating an |
| object. For Tomcat, this will always be an object of type |
| <code>javax.naming.Reference</code>, which contains the class name |
| of this factory class, as well as the configuration properties |
| (from <code>conf/server.xml</code>) to use in creating objects |
| to be returned.</li> |
| <li><strong>Name name</strong> - The name to which this factory is bound |
| relative to <code>nameCtx</code>, or <code>null</code> if no name |
| is specified.</li> |
| <li><strong>Context nameCtx</strong> - The context relative to which the |
| <code>name</code> parameter is specified, or <code>null</code> if |
| <code>name</code> is relative to the default initial context.</li> |
| <li><strong>Hashtable environment</strong> - The (possibly null) |
| environment that is used in creating this object. This is generally |
| ignored in Tomcat object factories.</li> |
| </ul> |
| |
| <p>To create a resource factory that knows how to produce <code>MyBean</code> |
| instances, you might create a class like this:</p> |
| |
| <source> |
| package com.mycompany; |
| |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| import javax.naming.Context; |
| import javax.naming.Name; |
| import javax.naming.NamingException; |
| import javax.naming.RefAddr; |
| import javax.naming.Reference; |
| import javax.naming.spi.ObjectFactory; |
| |
| public class MyBeanFactory implements ObjectFactory { |
| |
| public Object getObjectInstance(Object obj, |
| Name name, Context nameCtx, Hashtable environment) |
| throws NamingException { |
| |
| // Acquire an instance of our specified bean class |
| MyBean bean = new MyBean(); |
| |
| // Customize the bean properties from our attributes |
| Reference ref = (Reference) obj; |
| Enumeration addrs = ref.getAll(); |
| while (addrs.hasMoreElements()) { |
| RefAddr addr = (RefAddr) addrs.nextElement(); |
| String name = addr.getType(); |
| String value = (String) addr.getContent(); |
| if (name.equals("foo")) { |
| bean.setFoo(value); |
| } else if (name.equals("bar")) { |
| try { |
| bean.setBar(Integer.parseInt(value)); |
| } catch (NumberFormatException e) { |
| throw new NamingException("Invalid 'bar' value " + value); |
| } |
| } |
| } |
| |
| // Return the customized instance |
| return (bean); |
| |
| } |
| |
| } |
| </source> |
| |
| <p>In this example, we are unconditionally creating a new instance of |
| the <code>com.mycompany.MyBean</code> class, and populating its properties |
| based on the parameters included in the <code><ResourceParams></code> |
| element that configures this factory (see below). You should note that any |
| parameter named <code>factory</code> should be skipped - that parameter is |
| used to specify the name of the factory class itself (in this case, |
| <code>com.mycompany.MyBeanFactory</code>) rather than a property of the |
| bean being configured.</p> |
| |
| <p>For more information about <code>ObjectFactory</code>, see the |
| <a href="http://java.sun.com/products/jndi/docs.html">JNDI 1.2 Service |
| Provider Interface (SPI) Specification</a>.</p> |
| |
| <p>You will need to compile this class against a class path that includes |
| all of the JAR files in the <code>$CATALINA_HOME/common/lib</code> and |
| <code>$CATALINA_HOME/server/lib</code> directories. When you are through, |
| place the factory class (and the corresponding bean class) unpacked under |
| <code>$CATALINA_HOME/common/classes</code>, or in a JAR file inside |
| <code>$CATALINA_HOME/common/lib</code>. In this way, the required class |
| files are visible to both Catalina internal resources and your web |
| application.</p> |
| |
| <h3>2. Declare Your Resource Requirements</h3> |
| |
| <p>Next, modify your web application deployment descriptor |
| (<code>/WEB-INF/web.xml</code>) to declare the JNDI name under which |
| you will request new instances of this bean. The simplest approach is |
| to use a <code><resource-env-ref></code> element, like this:</p> |
| |
| <source> |
| <resource-env-ref> |
| <description> |
| Object factory for MyBean instances. |
| </description> |
| <resource-env-ref-name> |
| bean/MyBeanFactory |
| </resource-env-ref-name> |
| <resource-env-ref-type> |
| com.mycompany.MyBean |
| </resource-env-ref-type> |
| <resource-env-ref> |
| </source> |
| |
| <p><strong>WARNING</strong> - Be sure you respect the element ordering |
| that is required by the DTD for web application deployment descriptors! |
| See the |
| <a href="http://java.sun.com/products/servlet/download.html">Servlet |
| Specification</a> for details.</p> |
| |
| <h3>3. Code Your Application's Use Of This Resource</h3> |
| |
| <p>A typical use of this resource environment reference might look |
| like this:</p> |
| |
| <source> |
| Context initCtx = new InitialContext(); |
| Context envCtx = (Context) initCtx.lookup("java:comp/env"); |
| MyBean bean = (MyBean) envCtx.lookup("bean/MyBeanFactory"); |
| |
| writer.println("foo = " + bean.getFoo() + ", bar = " + |
| bean.getBar()); |
| </source> |
| |
| <h3>4. Configure Tomcat's Resource Factory</h3> |
| |
| <p>To configure Tomcat's resource factory, add an elements like this to the |
| <code>$CATALINA_HOME/conf/server.xml</code> file, nested inside the |
| <code>Context</code> element for this web application.</p> |
| <source> |
| <Context ...> |
| ... |
| <Resource name="bean/MyBeanFactory" auth="Container" |
| type="com.mycompany.MyBean" |
| factory="com.mycompany.MyBeanFactory" |
| bar="23"/> |
| ... |
| </Context> |
| </source> |
| |
| <p>Note that the resource name (here, <code>bean/MyBeanFactory</code> |
| must match the value specified in the web application deployment |
| descriptor. We are also initializing the value of the <code>bar</code> |
| property, which will cause <code>setBar(23)</code> to be called before |
| the new bean is returned. Because we are not initializing the |
| <code>foo</code> property (although we could have), the bean will |
| contain whatever default value is set up by its constructor.</p> |
| |
| <p>You will also note that, from the application developer's perspective, |
| the declaration of the resource environment reference, and the programming |
| used to request new instances, is identical to the approach used for the |
| <em>Generic JavaBean Resources</em> example. This illustrates one of the |
| advantages of using JNDI resources to encapsulate functionality - you can |
| change the underlying implementation without necessarily having to |
| modify applications using the resources, as long as you maintain |
| compatible APIs.</p> |
| |
| </section> |
| |
| |
| |
| </body> |
| |
| </document> |