The Java EE 5 Tutorial

Chapter 34 Resource Connections

Java EE components can access a wide variety of resources, including databases, mail sessions, Java Message Service objects, and URLs. The Java EE 5 platform provides mechanisms that allow you to access all these resources in a similar manner. This chapter describes how to get connections to several types of resources.

Resources and JNDI Naming

In a distributed application, components need to access other components and resources such as databases. For example, a servlet might invoke remote methods on an enterprise bean that retrieves information from a database. In the Java EE platform, the Java Naming and Directory Interface (JNDI) naming service enables components to locate other components and resources.

A resource is a program object that provides connections to systems, such as database servers and messaging systems. (A JDBC resource is sometimes referred to as a data source.) Each resource object is identified by a unique, people-friendly name, called the JNDI name.

For example, the JNDI name of the JDBC resource for the Java DB database that is shipped with the Application Server is jdbc/__default.

An administrator creates resources in a JNDI namespace. In the Application Server, you can use either the Admin Console or the asadmin command to create resources. Applications then use annotations to inject the resources. If an application uses resource injection, the Application Server invokes the JNDI API, and the application is not required to do so. However, it is also possible for an application to locate resources by making direct calls to the JNDI API.

A resource object and its JNDI name are bound together by the naming and directory service. To create a new resource, a new name-object binding is entered into the JNDI namespace.

For information on creating Java Message Service (JMS) resources, see Creating JMS Administered Objects for the Synchronous Receive Example. For an example of creating a JDBC resource, see Creating a Data Source in the Application Server.

You inject resources by using the @Resource annotation in an application. For information on resource injection, see the following sections of this Tutorial:

You can use a deployment descriptor to override the resource mapping that you specify in an annotation. Using a deployment descriptor allows you to change an application by repackaging it, rather than by both recompiling the source files and repackaging. However, for most applications, a deployment descriptor is not necessary.

DataSource Objects and Connection Pools

To store, organize, and retrieve data, most applications use a relational database. Java EE 5 components may access relational databases through the JDBC API. For information on this API, see http://java.sun.com/products/jdbc.

In the JDBC API, databases are accessed by using DataSource objects. A DataSource has a set of properties that identify and describe the real world data source that it represents. These properties include information such as the location of the database server, the name of the database, the network protocol to use to communicate with the server, and so on. In the Application Server, a data source is called a JDBC resource.

Applications access a data source using a connection, and a DataSource object can be thought of as a factory for connections to the particular data source that the DataSource instance represents. In a basic DataSource implementation, a call to the getConnection method returns a connection object that is a physical connection to the data source.

If a DataSource object is registered with a JNDI naming service, an application can use the JNDI API to access that DataSource object, which can then be used to connect to the data source it represents.

DataSource objects that implement connection pooling also produce a connection to the particular data source that the DataSource class represents. The connection object that the getConnection method returns is a handle to a PooledConnection object rather than being a physical connection. An application uses the connection object in the same way that it uses a connection. Connection pooling has no effect on application code except that a pooled connection, like all connections, should always be explicitly closed. When an application closes a connection that is pooled, the connection is returned to a pool of reusable connections. The next time getConnection is called, a handle to one of these pooled connections will be returned if one is available. Because connection pooling avoids creating a new physical connection every time one is requested, applications can run significantly faster.

A JDBC connection pool is a group of reusable connections for a particular database. Because creating each new physical connection is time consuming, the server maintains a pool of available connections to increase performance. When an application requests a connection, it obtains one from the pool. When an application closes a connection, the connection is returned to the pool.

Applications that use the Persistence API specify the DataSource object they are using in the jta-data-source element of the persistence.xml file.

<jta-data-source>jdbc/MyOrderDB</jta-data-source>

This is typically the only reference to a JDBC object for a persistence unit. The application code does not refer to any JDBC objects. For more details, see Persistence Units.

Resource Injection

The javax.annotation.Resource annotation is used to declare a reference to a resource. @Resource can decorate a class, a field, or a method. The container will inject the resource referred to by @Resource into the component either at runtime or when the component is initialized, depending on whether field/method injection or class injection is used. With field and method-based injection, the container will inject the resource when the application is initialized. For class-based injection, the resource is looked up by the application at runtime.

@Resource has the following elements:

The name element is the JNDI name of the resource, and is optional for field- and method-based injection. For field-based injection, the default name is the field name qualified by the class name. For method-based injection, the default name is the JavaBeans property name based on the method qualified by the class name. The name element must be specified for class-based injection.

The type of resource is determined by one of the following:

For class-based injection, the type element is required.

The authenticationType element is used only for connection factory resources, and can be set to one of the javax.annotation.Resource.AuthenticationType enumerated type values: CONTAINER, the default, and APPLICATION.

The shareable element is used only for ORB instance resources or connection factory resource. It indicates whether the resource can be shared between this component and other components, and may be set to true, the default, or false.

The mappedName element is a non-portable, implementation-specific name that the resource should be mapped to. Because the name element, when specified or defaulted, is local only to the application, many Java EE servers provide a way of referring to resources across the application server. This is done by setting the mappedName element. Use of the mappedName element is non-portable across Java EE server implementations.

The description element is the description of the resource, typically in the default language of the system on which the application is deployed. It is used to help identify resources, and to help application developers choose the correct resource.

Field-Based Injection

To use field-based resource injection, declare a field and decorate it with the @Resource annotation. The container will infer the name and type of the resource if the name and type elements are not specified. If you do specify the type element, it must match the field’s type declaration.

package com.example;

public class SomeClass {
    @Resource
    private javax.sql.DataSource myDB;
...
}

In the code above, the container infers the name of the resource based on the class name and the field name: com.example.SomeClass/myDB. The inferred type is javax.sql.DataSource.class.

package com.example;

public class SomeClass {
    @Resource(name="customerDB")
    private javax.sql.DataSource myDB;
...
}

In the code above, the JNDI name is customerDB, and the inferred type is javax.sql.DataSource.class.

Method-Based Injection

To use method-based injection, declare a setter method and decorate it with the @Resource annotation. The container will infer the name and type of the resource if the name and type elements are not specified. The setter method must follow the JavaBeans conventions for property names: the method name must begin with set, have a void return type, and only one parameter. If you do specify the type element, it must match the field’s type declaration.

package com.example;

public class SomeClass {

    private javax.sql.DataSource myDB;
...
    @Resource
    private void setMyDB(javax.sql.DataSource ds) {
        myDB = ds;
    }
...
}

In the code above, the container infers the name of the resource based on the class name and the field name: com.example.SomeClass/myDB. The inferred type is javax.sql.DataSource.class.

package com.example;

public class SomeClass {

    private javax.sql.DataSource myDB;
...
    @Resource(name="customerDB")
    private void setMyDB(javax.sql.DataSource ds) {
        myDB = ds;
    }
...
}

In the code above, the JNDI name is customerDB, and the inferred type is javax.sql.DataSource.class.

Class-Based Injection

To use class-based injection, decorate the class with a @Resource annotation, and set the required name and type elements.

@Resource(name="myMessageQueue",
                type="javax.jms.ConnectionFactory")
public class SomeMessageBean {
...
}

Declaring Multiple Resources

The @Resources annotation is used to group together multiple @Resource declarations for class-based injection.

@Resources({
    @Resource(name="myMessageQueue",
                    type="javax.jms.ConnectionFactory"),
    @Resource(name="myMailSession",
                    type="javax.mail.Session")
})
public class SomeMessageBean {
...
}

The code above shows the @Resources annotation containing two @Resource declarations. One is a JMS message queue, and the other is a JavaMail session.

The confirmer Example Application

The confirmer example application demonstrates how to use an injected JavaMail session to send a confirmation email.

If you’ve ever ordered a product from a web site, you’ve probably received an email confirming your order. The ConfirmerBean class demonstrates how to send email from an enterprise bean.

Like a database connection, a mail session is a resource. In the Application Server, a mail session is called a JavaMail resource. The resource is injected into the class using @Resource and specifying the JNDI name of the resource. The type of the session field is javax.mail.Session.

@Resource(name="mail/myMailSession")
private Session session;

After calling several set methods on the Message object, sendNotice invokes the send method of the javax.mail.Transport class to send the message. The source code for the sendNotice method follows.

public void sendNotice(String recipient) {
    try {
        Message message = new MimeMessage(session);
        message.setFrom();
        message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse(recipient, false));
        message.setSubject("Test Message from ConfirmerBean");
        DateFormat dateFormatter = DateFormat
                .getDateTimeInstance(DateFormat.LONG,
                DateFormat.SHORT);
        Date timeStamp = new Date();

        String messageText = "Thank you for your order." + ’\n’
                + "We received your order on "
                + dateFormatter.format(timeStamp) + ".";
        message.setText(messageText);

        message.setHeader("X-Mailer", mailer);
        message.setSentDate(timeStamp);

        // Send message
        Transport.send(message);
        logger.info("Mail sent to " + recipient + ".");
    } catch (MessagingException ex) {
        ex.printStackTrace();
        logger.info("Error in ConfirmerBean for " + recipient);
    }
}

Running the confirmer Example Application

    To run the confirmer example, follow these steps, as described in the following sections:

  1. Create a mail session in the Admin Console.

  2. Build the example.

  3. Deploy the example.

  4. Retrieve the client JAR.

  5. Run the client JAR.

Creating a Mail Session

  1. To create a mail session in the Application Server using the Admin Console, follow these steps:Open the URL http://localhost:4848/asadmin in a browser.

  2. Select the JavaMail Sessions node.

  3. Click New.

  4. Type mail/myMailSession in the JNDI Name field.

  5. Type the name of the host running your mail server in the Mail Host field.

  6. Type the destination email address in the Default User field.

  7. Type your email address in the Default Return Address field.

  8. Click OK.

    Note that mail/myMailSession is listed under the JavaMail Sessions node.

Building, Packaging, and Deploying confirmer in NetBeans IDE

    Follow these instructions to build, package, and deploy the confirmer example to your Application Server instance using the NetBeans IDE IDE.

  1. In NetBeans IDE, select File->Open Project.

  2. In the Open Project dialog, navigate to tut-install/javaeetutorial5/examples/ejb/.

  3. Select the confirmer folder.

  4. Select the Open as Main Project and Open Required Projects check boxes.

  5. Click Open Project.

  6. In the Projects tab, right-click the confirmer project and select Undeploy and Deploy.

This builds and packages the application into confirmer.ear, located in tut-install/javaeetutorial5/examples/ejb/confirmer/dist, and deploys this EAR file to your Application Server instance.

Building, Packaging, and Deploying confirmer Using Ant

    To build and package the confirmer example, do the following:

  1. In a terminal window, go to tut-install/examples/ejb/confirmer.

  2. Enter the following command:


    ant
    

    This compiles the source code and creates an EAR file, confirmer.ear, in the dist directory.

To deploy confirmer.ear, type the following command in a terminal window:


ant deploy

Running the confirmer Client in NetBeans IDE

    By default, the client sends a message to pig.bodine@example.com, a fictional email address. To change the email address in NetBeans IDE, do the following:

  1. Right-click the confirmer project in the Projects pane and select Properties.

  2. Click the Run category.

  3. In the Client Information area, under Arguments, enter the email address to which you want the message sent.

  4. Click OK.

To run the client in NetBeans IDE, right-click the confirmer project in the Projects pane and select Run. You should see the following line when the client has successfully sent the test message:


...
Message sent to pig.bodine@example.com.
...

Running the confirmer Client Using Ant

By default, the client sends a message to pig.bodine@example.com, a fictional email address. To change the email address, set the app-client.args property in tut-install/examples/ejb/confirmer/nbproject/project.properties to the email address to which you’d like the test message sent. For example:


app-client.args=duke@example.com

To retrieve the client JAR and run the client, enter the following command in a terminal:


ant run

You should see the following line when the client has successfully sent the test message:


[exec] Message sent to pig.bodine@example.com.

If you changed the target email address, the test message should arrive in the user’s inbox in a few moments.

Further Information about Resources

For more information about resources and annotations, see: