Section 4.4. JNDI References in web.xml


4.4. JNDI References in web.xml

In previous chapters, we used the web.xml file to describe and deploy servlets. This same file describes and deploys JNDI resources. The new web.xml looks like Example 4-4.

Example 4-4. 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>     <servlet>         <servlet-name>Controller</servlet-name>         <servlet-class>com.jbossatwork.ControllerServlet</servlet-class>     </servlet>     <servlet-mapping>         <servlet-name>Controller</servlet-name>         <url-pattern>/controller/*</url-pattern>     </servlet-mapping>     <resource-ref>         <res-ref-name>jdbc/JBossAtWorkDS</res-ref-name>         <res-type>javax.sql.DataSource</res-type>         <res-auth>Container</res-auth>     </resource-ref> </web-app> 

Let's examine each new element:

  • <res-ref-name> is the JNDI resource name. Notice that you don't have to specify "java:comp/env/"it is assumed, just like "http://" is commonly left out of web URLs.

  • <res-type> in our case is a DataSource. This must be the fully qualified classname.

  • <res-auth> can be either Container or Servlet. Since we use JBoss' DataSource pooling, Container is the appropriate choice here.

OK, so here's where it gets interesting. At first glance, it appears that JBoss doesn't adhere to the ENC naming style when it comes to DataSources. Instead of java:comp/env/jdbc/JBossAtWorkDS, its DataSources are referenced as simply java:/JBossAtWorkDS. So we need a way to map the JBoss name to the ENC name.

The real reason for the mismatch is that JBoss creates a global binding for the DataSource, and we need to create a local reference to it. We mentioned earlier in the chapter that all JNDI references are local to the EAR. Out of courtesy, JBoss doesn't automatically expose global references to us. We need to map the global name to a local name so that we can work with it.

Luckily, a straightforward way to do the cross mapping is available. You can include a JBoss specific deployment descriptor in your WAR named jboss-web.xml. Example 4-5 shows what ours should look like.

Example 4-5. jboss-web.xml
 <?xml version="1.0" encoding="UTF-8"?> <jboss-web>     <resource-ref>         <res-ref-name>jdbc/JBossAtWorkDS</res-ref-name>         <jndi-name>java:/JBossAtWorkDS </jndi-name>     </resource-ref> </jboss-web> 

Since we're already using XDoclet to generate our web.xml file, there is no reason not to continue letting it do its thing. Example 4-6 shows the new XDoclet code in ControllerServlet.

Example 4-6. ControllerServlet.java
 /**  * @web.servlet  *    name="Controller"  *  * @web.servlet-mapping  *    url-pattern="/controller/*"  *  * @web.resource-ref  *    name="jdbc/JBossAtWorkDS"  *    type="javax.sql.DataSource"  *    auth="Container"  *  * @jboss.resource-ref  *    res-ref-name="jdbc/JBossAtWorkDS"  *    jndi-name="java:/JBossAtWorkDS"  */ public class ControllerServlet extends HttpServlet 

Chances are good that more than one servlet will end up using the same JNDI resource. While the servlet tags need to be defined in each servlet, the JNDI tags should be specified only once. It doesn't matter which servlet you define them in, but you should come up with a strategy early in the development process for managing it. If you have a central Controller servlet like we do, it is usually a pretty logical candidate for this. (You can also have XDoclet include an XML fragment stored in a file instead of using JavaDoc comments. The choice is yours.)

To generate the jboss-web.xml file, we need to add a new XDoclet directive to our build process in Example 4-7aptly named <jbosswebxml>.

Example 4-7. Adding the <jbosswebxml> directive
 <!-- ====================================== -->     <target name="generate-web" description="Generate web.xml">         <taskdef name="webdoclet"                  classname="xdoclet.modules.web.WebDocletTask"                  classpathref="xdoclet.lib.path" />         <mkdir dir="${gen.source.dir}" />         <webdoclet destdir="${gen.source.dir}">             <fileset dir="${source.dir}">                 <include name="**/*Servlet.java" />             </fileset>             <deploymentdescriptor destdir="${gen.source.dir}"                                   distributable="false"                                   servletspec="2.4" />             <jbosswebxml destdir="${gen.source.dir}" />         </webdoclet>     </target> 

We'll also need to change your <war> task in Example 4-8 to include the newly generated JBoss-specific deployment descriptor.

Example 4-8. Including jboss-web.xml in the WAR
 <!-- ====================================== -->     <target name="war" depends="generate-web,compile"              description="Packages the Web files into a WAR file">         <mkdir dir="${distribution.dir}" />         <war destFile="${distribution.dir}/${war.name}"               webxml="${gen.source.dir}/web.xml">             <!-- files to be included in / -->             <fileset dir="${web.dir}"  exclude="WEB-INF/web.xml" />             <!-- files to be included in /WEB-INF/classes -->             <classes dir="${classes.dir}" />             <!-- files to be included in /WEB-INF/lib -->             <lib dir="${lib.dir}" />             <!-- files to be included in /WEB-INF -->             <webinf dir="${web.inf.dir}" excludes="web.xml" />             <webinf dir="${gen.source.dir}" >                     <include name="jboss-web.xml" />             </webinf>         </war>     </target> 

OK, so now we know that the JNDI resources are defined in the deployment descriptors . But where do we configure the DataSource itself?



JBoss at Work. A Practical Guide
JBoss at Work: A Practical Guide
ISBN: 0596007345
EAN: 2147483647
Year: 2004
Pages: 197

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net