Skip Headers
Oracle® Containers for J2EE Servlet Developer's Guide
10g (10.1.3.1.0)

Part Number B28959-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

7 Using Annotations for Services and Resource References

OC4J supports annotations that the servlet 2.5 specification describes, by injecting resource references before a component instance is made available to an application. The following sections describe how to use annotations in OC4J:

Overview of How Annotations Work

In J2SE 5.0 or greater, you can specify configuration data and dependency on external resources in Java code as metadata, also referred to as annotations. You can define such data in configuration files or in annotations for services, such as EJBs or Web services, and for resource references, such as data sources and JMS destinations.

For example, in J2EE 1.4, before a servlet can refer to an EJB, the developer must define an ejb-local-ref element, like this one:

<ejb-local-ref>
 <ejb-ref-name>ejb/HelloWorld</ejb-ref-name>
 <local>oracle.ejb.HelloWorld</local>
</ejb-local-ref>

Then, to refer to the EJB in code, the developer has to use JNDI, as in this code fragment:

Context ic = new InitialContext();   
HelloWorld helloWorld = (HelloWorld)ic.lookup("java:comp/env/ejb/HelloWorld");
helloWorld.greet(ÒHello!Ó);

In servlet 2.5, the client code is simplified and OC4J injects the correct resource or service. The client only needs to specify the resource or service in an annotation, such as this one:

@EJB
private HelloWorld helloWorld;
helloWorld.greet("Hello!");

Annotations and Injection

The metadata-complete attribute of the web-app element in a Web application's deployment descriptor specifies whether the Web descriptor and other related deployment descriptors for this module (such as Web service descriptors) are complete. If the web.xml file uses servlet 2.5 by setting version="2.5" or points to the servlet 2.5 schema namespace, the OC4J servlet container will check the metadata-complete flag to determine whether or not to process annotations. If version is set to 2.4 or an earlier version, the servlet container does not process any annotations.

If metadata-complete is set to true, the default value for Servlet 2.4, the servlet container ignores any servlet annotations that are in the class files of the application. If the metadata-complete attribute is missing or is set to false, the default value for Servlet 2.5, and version is set to 2.5, the servlet container examines the class files of the application for servlet annotations and supports the annotations as follows:

  1. The OC4J servlet container inspects resource or service references for annotation references for classes of a Web application that are located in the WEB-INF/ directory or in a JAR file under the WEB-INF/lib/ directory.

    The servlet container also provides annotation support for jar files listed in MANIFEST.MF.

  2. The OC4J servlet container provides annotation support for managed component classes that are declared in the Web application deployment descriptor and that implement the following interfaces:

    • javax.servlet.Servlet

    • javax.servlet.Filter

    • javax.servlet.ServletContextListener

    • javax.servlet.ServletContextAttributeListencer

    • javax.servlet.ServletRequestListener

    • javax.servlet.ServletRequestAttributeListener

    • javax.servlet.http.HttpSessionListener

    • javax.servlet.http.HttpSessionAttributeListener

  3. The OC4J servlet container injects resource or service references before any lifecycle methods are called on the instance.

    • (init() for javax.servlet.Servlet and javax.servlet.Filter

    • contextInitialized() for javax.servlet.ServletContextListener

    • requestInitialized() for javax.servlet.ServletRequestListener

  4. If both an annotation and a deployment descriptor entry declare an environment entry, information in the deployment descriptor entry can override some of the information in a Resource, EJB, or WebServiceRef annotation.

    The following specifications describe the rules for using a deployment descriptor entry to override annotation information:

    • For rules to override Resource annotations, see the Java EE 5 specification.

    • For rules to override EJB annotations, see the EJB specification.

    • For rules to override WebServiceRef annotations, see the Web Services specification.

  5. If the OC4J servlet container cannot find a resource or service that it needs to inject for a class, the initialization of the class fails and OC4J issues this warning message:

    Some resource(s) and/or service(s) to be injected cannot be found for class name. class name will not be put to service.
    
    
  6. After all the resource or service references have been injected, and before any lifecycle methods are called on the instance, the method marked with the PostConstruct annotation, if any, must be invoked to give the servlet a chance to initialize the injected resources. See "PostConstruct Annotation".

  7. Before the servlet is taken out of service, the method marked with a PreDestroy annotation, if any, must be invoked to give the servlet a chance to release the injected resources. See "PreDestroy Annotation".

Annotations in OC4J

This section describes the annotations that OC4J supports:

EJB Annotation

Resource Annotation

Resources Annotation

PostConstruct Annotation

PreDestroy Annotation

PersistenceUnit(s) Annotation

PersistenceContext(s) Annotation

WebServiceRef Annotation

DeclaresRoles Annotation

RunAs Annotation

EJB Annotation

An EJB annotation on a field or method of an application component is equivalent to an ejb-ref or ejb-local-ref element in the deployment descriptor. If a field has an EJB annotation, OC4J injects the field with a reference to the corresponding EJB component.

In an EJB annotation, you can refer to the local or remote home interface of the bean or to the business interface of an EJB 3 bean. If the reference is to the EJB 3 business interface, OC4J injects a reference to an instance of the enterprise bean.

The following example shows a short EJB annotation:

@EJB private ShoppingCart myCart;

The next example shows a longer EJB annotation, which uses all of the annotation fields:

@EJB(
      name = "ejb/shopping-cart",
      beanName = "Cart1",
      beanInterface = ShoppingCart.class,
      description = "Items for purchase"
   )
   private ShoppingCart myCart;

For more details about the EJB annotation, see the EJB specification.

The example set in the "Annotation Example" section includes EJB annotation.

Resource Annotation

Use the Resource annotation to declare a reference to a resource such as a data source, JMS destination, or environment entry. If you use this annotation, you do not need to declare the reference in a <resource-ref>, <message-destination-ref>, <env-ref>, or <resource-env-ref> element in the deployment descriptor.

When a Resource annotation is applied on a field or a setter method, OC4J injects a reference to the resource declared by the annotation and maps the references to the JNDI name for the resource. When the annotation is applied to a class, the annotation declares a resource that the application will look up at runtime.

Each injection corresponds to a JNDI lookup. If the annotation does not explicitly specify the JNDI name, the name of the field combined with the fully qualified name of the class is used as the JNDI name. For example, the default JNDI name of a field named myDb in a class MyApp in the package com.example would be java:comp/env/com.example.MyApp/myDb. All JNDI names are relative to java:comp/env/. If the annotation is applied on a setter method, the default is the JavaBeans property name corresponding to the method qualified by the class name. When the annotation is applied to a class, there is no default and the name must be specified.

The following example does not specify the JNDI name, so OC4J would use the default JNDI name:

@Resource
   private DataSource myDB;

The next example explicitly specifies the JNDI name:

@Resource(name="customerDB")
   private DataSource myDB;

For general information about annotations, see the Java EE 5 specification.

The example set in the "Annotation Example" section includes resource annotation.

Resources Annotation

Repeated annotations are not allowed, so the Resources annotation acts as a container for multiple Resource annotations, in this format:

public @interface Resources {
      Resource[] value;
  }
  // value – Array of multiple resources.

The following example shows a Resources annotation that contains two Resource annotations on a class, for a data source and a connection factory:

@Resources ({
      @Resource (name = "myDB", type=javax.sql.DataSource),
      @Resource (name = "myCF", type=javax.jms.ConnectionFactory)
   )
   public class MulResClass {
      //...
   }

PostConstruct Annotation

OC4J invokes the method with the PostConstruct annotation after all other resource injections have been completed and before any lifecycle methods on a component is called. This allows the component to do post-create processing. OC4J invokes this method even if the class has no other annotations.

The following example shows a PostConstruct annotation:

@PostConstruct
   void doPostInjectionProcessing {
      //...


Note:

The PostConstruct annotation lets an arbitrary method of a servlet act as the init() method.

PreDestroy Annotation

OC4J invokes the method with the PreDestroy annotation before taking the servlet out of service. This allows the servlet to release the injected resources. OC4J invokes this method even if the class has no other annotations.

The following example shows a PreDestroy annotation:

@PreDestroy
   void doPreDestroyProcessing {
      //...
      }


Note:

The PreDestroy annotation lets an arbitrary method of a servlet act as the destroy() method.

PersistenceUnit(s) Annotation

A PersistenceUnit annotation is required for using EJB 3.0 persistence. A persistence unit has configuration details about entity managers (persistence contexts) that manage a set of related entity beans. "PersistenceContext(s) Annotation" describes the annotation for persistence contexts.

You can annotate a field or a method of a servlet with a PersistenceUnit annotation. A logical persistent unit reference refers to an entity manager factory for a persistence unit.

The following example declares a single persistence unit:

@PersistenceUnit
   EntityManagerFactory emf;

If you declare multiple persistence units in a servlet, you must specify an explicit unitName for each unit, as follows:

@PersistenceUnit(unitName=ÓInventoryManagementÓ)
      EntityManagerFactory emf;

A PersistenceUnit annotation is equivalent to a persistence-unit-ref element in persistence.xml.

For more information about persistence unit references, see the Java EE 5 specification.

PersistenceContext(s) Annotation

A PersistenceContext annotation is required for using EJB 3.0 persistence. A persistence context is an entity manager that manages a set of related entity beans. A persistence unit has configuration details about a persistence context. "PersistenceUnit(s) Annotation" describes the annotation for persistence units. An example of a PersistenceContext annotation follows:

@PersistenceContext
   EntityManager em;

If multiple persistence units are declared in the servlet, an explicit unit name must be specified in the unitName attribute, as follows:

@PersistenceContext(unitName=ÓInventoryManagementÓ)
   EntityManager em;

This annotation is equivalent to a persistence-context-ref element in persistence.xml.

For more information about persistence context references, see the Java EE 5 specification.

WebServiceRef Annotation

Annotating with the WebServiceRef annotation is equivalent to declaring a <resource-ref> element in the deployment descriptor that would provide a reference to a Web service.

This annotation has two main uses:

  • Define a reference whose type is a generated service interface

  • Define a reference whose type is a service endpoint interface (SEI)

An example of a WebServiceRef annotation follows:

// Generated Service Interface
   @WebServiceRef
   private StockQuoteService stockQuoteService;

   // SEI
   @WebServiceRef(StockQuoteService.class)
   private StockQuoteProvider stockQuoteProvider;

For more details about the WebServiceRef annotation, see Java API for XML-Based Web Services, 2.0 (JSR 224).

DeclaresRoles Annotation

The DeclaresRoles annotation defines all the security roles that compose the security model of an application. You can specify this annotation on a class, defining roles that you can test from within the methods of the annotated class, by calling isCallerInRole.

The following example shows a DeclaresRoles annotation:

@DeclaresRoles("Manager")
   public class CorporationServlet {
      //...
   }

This annotation is equivalent to the following code in a web.xml file:

<web-app>
      <security-role>
         <role-name>Manager</role-name>
      </security-role>
   </web-app>

For more details about the DeclaresRoles annotation, see Common Annotations for the JavaTM Platform (JSR 250)

RunAs Annotation

The RunAs annotation is equivalent to the <run-as> element in the deployment descriptor. This annotation can only be used in classes that implement the javax.servlet.Servlet interface or a subclass of it.

The following example shows a RunAs annotation:

@RunAs("Admin")
   public class CorporationServlet {
      //...
   }

This annotation is equivalent to the following code in a web.xml file:

<servlet>
      <servlet-name>CorporationServlet</servlet-name>
      <run-as>Admin</run-as>
   </servlet>

For more details about the RunAs annotation, see Common Annotations for the JavaTM Platform (JSR 250)

Annotation Rules and Guidelines

Here are some rules for using annotations. For more information on general annotation guidelines, see the Java EE 5 specification.

How Annotations Affect Performance with Servlet Version 2.5

Whether or not annotations are used for Web applications with servlet version 2.5, if the metadata-complete attribute of <web-app> is missing from the deployment descriptor or is set to false (the servlet 2.5 default value), OC4J needs to load all the classes under WEB-INF/ and WEB-INF/lib to look for annotations. This loading can have some impact on Oracle Application Server performance at startup. When you are not using annotations, you can avoid this performance impact by specifying metadata-complete="true".

This startup performance impact is applicable only for Web applications with servlet version 2.5. For Web applications with servlet version 2.4 or lower, there will be no performance impact.

Annotation Example

This section contains an example of a servlet using annotations and the corresponding web.xml file.

The servlet illustrates the Servlet 2.5 way of doing things and then commented out is the Servlet 2.4 way of doing things as a comparison. The servlet demonstrates one @EJB annotation and two @Resource annotations.

The web.xml file illustrates the version= and metadata-complete settings required to enable annotations to be used:

<web-app version="2.5" metadata-complete="false">
 ...
</web-app>

For additional information, see the document "How-To: Using Dependency Injection In Web Module" on the following site:

http://www.oracle.com/technology/tech/java/oc4j/10131/how_to/index.html

Here is the web.xml file example.

<?xml version="1.0"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
        version="2.5"
        metadata-complete="false"
>

    <display-name>Annotation Example</display-name>
        <description>A few examples of Servlet 2.5 Annotation and Resource Injection</description>

    <servlet>
        <display-name>hello</display-name>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>HelloServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

  <env-entry>
    <env-entry-name>EmpNo</env-entry-name>
    <env-entry-type>java.lang.Integer</env-entry-type>
    <env-entry-value>15</env-entry-value>
  </env-entry>
</web-app>

Here is the HelloServlet.java servlet example.

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.annotation.Resource;
import javax.sql.*;
import java.sql.*;
import javax.naming.*;
import org.acme.*; 
import javax.rmi.*;
import javax.ejb.*;
public class HelloServlet extends HttpServlet {

    @EJB HelloObject bean;
    @Resource(name="EmpNo") int empNo;
    @Resource(name="jdbc/OracleDS") private DataSource db;

    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        res.setContentType("text/html");

        PrintWriter writer = res.getWriter();

        // ejb invocation
        writer.println(bean.sayHello()+"<br>");

        // fetch value set by deployer
        writer.println("EmpNo="+empNo+"<br>");

        // make a db connection
        writer.println("db="+getConnection()+"<br>");
    }

    public Connection getConnection() {
      Connection conn = null; 
  
      try {
          if (db != null) {
              conn = db.getConnection();
          }
      } catch (Exception e) {
          e.printStackTrace();
      }
      return conn;
    }

    // The following is the pre-2.5 way to do it.
/*

   public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        res.setContentType("text/html");

        PrintWriter writer = res.getWriter();

        InitialContext ctx = new InitialContext();
        Object obj = ctx.lookup("java:comp/env/ejb/Hello");

        HelloHome ejbHome = (HelloHome)
                    PortableRemoteObject.narrow(obj,HelloHome.class);
        HelloObject bean = ejbHome.create();

        // ejb invocation
        writer.println(bean.sayHello()+"<br>");

        // fetch value set by deployer
        Context myEnv = (Context) ctx.lookup("java:comp/env");
        Integer empNoInteger = (Integer) myEnv.lookup("EmpNo");
        int empNo = empNoInteger.intValue();

        writer.println("EmpNo="+empNo+"<br>");

        // make a db connection
        writer.println("db="+getConnection()+"<br>");
    }

    public Connection getConnection() {

        Context initCtx = new InitialContext();
        javax.sql.DataSource db = 
           (javax.sql.DataSource) initCtx.lookup("java:comp/env/jdbc/OracleDS");

        Connection conn = null;

        try {
            if (db != null) {
                conn = db.getConnection();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
*/
}