|< Free Open Study >|| |
The standard way of working with an external resource in J2EE is to construct a factory object for the resource in question, and bind it to JNDI when the server is initialized. That way, it is made available to all clients through a logical bind name operation. By configuring such a factory at initialization time, we can hide the details of the underlying resource (for example, the user name and password for a relational database) and ensure that each part of our application will access the resource in a uniform manner. This also allows us to optimize access to the resource in question. For example, we could pool database connections or share a mail session between clients.
We will focus on the process of dynamically configuring and binding data source objects. A JDBC data source is a general-use connection factory, and is used to obtain a physical connection to a relational database.
According to the J2EE application server specification, a J2EE-compliant servlet container must provide a default JNDI provider.
The default provider is used only to bind and look up entries local to the servlet container, and cannot be used for more specific protocols such as LDAP.
The initial context set up by the default provider contains entries that are configured in the application's deployment descriptor:
This element is used to add a single-value parameter, of a specified type, to the JNDI context
This element describes a resource reference, which is an object factory for persistent resources (such as a relational database)
This element is a variation of the <resource-ref> element that is simpler to configure for resources that do not require authentication
All entries and resources that are configured in the application's deployment descriptor will be placed by default in the java:comp/env portion of the JNDI namespace (although we can place our own entries in another location).
A namespace is a set of names in which all names are unique. JNDI namespaces can contain other sub-namespaces.
For example, we could add the following entry to an application's deployment descriptor:
<env-entry> <env-entry-name>webmaster</env-entry-name> <env-entry-value>firstname.lastname@example.org</env-entry-value> <env-entry-type>java.lang.String</env-entry-type> </env-entry>
Using the default provider, we could then look up this entry from the local environment context:
InitialContext init = new InitialContext(); Context ctx = (Context) init.lookup("java:comp/env"); String webmaster = (String) ctx.lookup("webmaster");
In the previous code snippet, we had to look up the java:comp/env portion of the JNDI namespace in order to find the entry. Another way of performing this lookup would be to add the specified bind name to the java:/comp/env environment context:
InitialContext ctx = new InitialContext(); String webmaster = (String) ctx.lookup("java:/comp/env/webmaster");
The difference is that we are using a relative reference to look up the specified property in the first example, while we use an absolute reference in the second example.
Although all of the pre-configured entries and resources are placed in the java:comp/env portion of the JNDI namespace, we can place our own entries in another location. For example:
Context customContext = new InitialContext(); customContext.bind("myObject", new Object());
These sort of environment entries can be useful, but we are more interested in seeing how standard resource factories can be configured and bound to the standard JNDI context through the <resource-ref> and <resource-env-ref> elements.
The J2EE 1.3 specification mandates the inclusion of two standard resource factories that can be configured through the application and server deployment descriptors: JDBC data sources and external transaction factories. These are the only resource factories guaranteed to be available on all compliant application servers. Tomcat does support other types of resource factories (such as for JavaMail) but the use of such features compromises the container-independence of web applications, as the features may not be supported on other application servers.
To configure a standard resource factory for an application, we would add a <resource-ref> element to the application deployment descriptor. This element contains a declaration of the application's reference to an external resource. It consists of:
The reference name given to the resource factory - the object used to generate handles to your resource
The type of factory - for the standard factories, this can be one of javax.sql.DataSource and java.transaction.UserTransaction
The type of authentication - Application or Container
A specification for the sharing of connections obtained from the resource - Shareable or Unshareable
An optional description
For example, to configure a database connection factory (a DataSource object) for an application, we would add an entry something like this to our deployment descriptor:
<resource-ref> <res-ref-name>jdbc/ProductionDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref>
No details of the resource in question (for example, the database URL or user credentials) are given in the deployment descriptor. These attributes are specified in the server configuration descriptor and are referenced by a logical name in the deployment descriptor. That is, the value of <res-ref-name> must match a pre-configured entry in the server configuration.
For example, when using Tomcat, we can specify a <Resource> element and a matching <ResourceParams> element in the server.xml deployment descriptor. These elements are either contained within <Context> tags or in the <DefaultContext> tag. For example:
<Resource name="jdbc/ProductionDB" auth="Container" type="javax.sql.DataSource"/> <ResourceParams name="jdbc/ProductionDB"> <parameter> <name>user</name> <value>scott</value> </parameter> <parameter> <name>password</name> <value>tiger</value> </parameter> <parameter> <name>driverClassName</name> <value>org.gjt.mm.msql.Driver</value> </parameter> <parameter> <name>driverName</name> <value>jdbc:mysql://localhost/myDB</value> </parameter> </ResourceParams>
<Resource> elements specify the details of a resource and <res-ref-name> elements specify the use of a resource.
More information on resource configuration with Tomcat can be found at http://jakarta.apache.org/tomcat/tomcat-4.0-doc/jndi-resources-howto.html (it's also included in the documentation that comes with Tomcat).
|< Free Open Study >|| |