Web Tier to Go With Java EE 5: A Look at Resource Injection

 
By Ryan Lubke, June 2006  

Articles Index

The focus of the Java Platform, Enterprise Edition (Java EE) 5 is ease of development, with the goal of making typical application tasks simpler. An important new feature that helps fulfill this goal is support for annotations. Annotations enable injecting dependencies, resources, services, and life-cycle notifications into a Java EE 5 platform application.

This fourth article of the series describes how the platform's web-tier technologies support injection through Java technology annotations to simplify access to resources, environment data, and life-cycle control.

A Look at Resource Injection

To understand how resource injection makes life easier for developers, let's look at how applications accessed resources prior to support for resource injection and how the Java EE 5 platform has simplified this access. In the past, accessing data sources, web services, environment entries, and EJB software references required the use of boilerplate code. For example, the code required to access the container-managed data source javax.sql.DataSource would look like this:

public javax.sql.DataSource getCatalogDS() {
try {
// Obtain the initial Java Naming and Directory Interface
// (JNDI) context.
InitialContext initCtx = new InitialContext();
// Perform JNDI lookup to obtain the resource.
catalogDS = (DataSource)
initCtx.lookup("java:comp/env/jdbc/catalogDS");
} catch (NamingException ex) {
// Handle failure.
}
}

...

public getProductsByCategory() {
// Get the DataSource.
DataSource catalogDS = getCatalogDS();
// Get a connection and execute the query.
Connection conn = catalogDS.getConnection();
...

}
 

In order to look up a data source, a developer had to deal with the following:

  • Java Naming and Directory Interface (JNDI) API. The application looked up the resource by way of the JNDI API.
  • Casting. The look-up result had to be cast to the correct type.
  • Exception handling. The software had to handle the exceptions exposed by the JNDI API.

Moreover, the developer had to define the resource to acess in the deployment descriptor, web.xml, associated with the web application:

<resource-ref>
<description>Catalog DataSource</description>
<res-ref-name>jdbc/catalogDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
 

The Java EE 5 platform defines annotations to support a variety of injections. We can now reduce the code in the example above to the following:

private @Resource DataSource catalogDS;

public getProductsByCategory() {
// Get a connection and execute the query.
Connection conn = catalogDS.getConnection();
...
}
 

Because of the @Resource annotation, the developer does not need to worry about the boilerplate code that is normally required to get access to the resource. The catalogDS field of the javax.sql.DataSource type is annotated with @Resource and injected by the container prior to the component -- for example, a Servlet -- being made available to the application. The data source JNDI mapping is inferred from the catalogDS field name and javax.sql.DataSource type. Moreover, the catalogDS resource no longer needs to be defined in the deployment descriptor. Slick!

What Can Be Injected?

The support for injection is pervasive throughout the Java EE 5 platform. Many Java Community Process (JCP) program specifications have collaborated to define the various types of injections that the platform supports.

Chapter 5 of JSR 244, the Java platform specification, describes how applications declare dependencies on external resources and configuration parameters, how those items are represented in the Java EE 5 platform naming system, and how they can be injected into application components. This chapter puts in perspective everything related to the platform's resource access.

Further, Section 14.5 of the Servlet specification discusses the injection annotations that are supported in the Java EE 5 platform's web technologies. Table 1 lists the supported annotations.

Table 1: Annotations and Their Uses
 
 
Type of AnnotationAnnotation NameAction or Definition
Common annotations 1
@Resource
Declares a reference to a resource such as a data source, Java Messaging Service (JMS) destination, or environment entry. This annotation is equivalent to declaring a resource-ref, message-destination-ref, env-ref, or resource-env-ref element in the deployment descriptor.
 
@Resources
A collection of sorts to allow the declaration of multiple @Resource annotations.
 
@DeclaresRoles
Specifies security roles that the application uses.
 
@RunAs
Specifies the application's role during execution within a Java EE technology environment. Within the scope of the web tier, this annotation can be declared only on a Servlet and is the equivalent of declaring a run-as element on a Servlet in the deployment descriptor.
 
@PostConstruct
Specifies a method that the container will invoke after resource injection is complete but before any of the component's life-cycle methods are called.
 
@PreDestroy
Specifies a method that the container will invoke before removing the component from service.
EJB beans 2
@PersistenceContext
Specifies the container-managed entity context.
 
@PersistenceContexts
A collection of sorts to allow the declaration of multiple @PersistenceContext annotations.
 
@PersistenceUnit
Specifies a reference to an entity manager factory for use with EJB beans specified in a component.
 
@PersistenceUnits
A collection of sorts to allow the declaration of multiple @PersistenceUnit annotations.
Web services 3
@WebServiceRef
Specifies a reference to a web service within a web component.
 
@WebServicesRefs
A collection of sorts to allow the declaration of multiple @WebServiceRef annotations.
 

1Common annotations: JSR 250, Common Annotations for the Java Platform Specification, provides the semantics of the platform's common annotations.
2EJB beans: See JSR 220, the Enterprise JavaBeans 3.0 Specification, Section 8.1, Annotation of Context Dependencies.
3Web services: See JSR 224, the Java API for XML-Based Web Services (JAX-WS) 2.0 Specification, Section 7.9, javax.xml.ws.WebServiceRef.

What Components Can Accept Resource Injections?

Keep in mind that a Java EE 5 platform container can handle the injections transparently only when they are used on container-managed components, such as EJB beans, Servlets, and JavaServer Pages (JSP) technology tag handlers.

This is for two reasons. First, for performance considerations, a container can restrict its search of annotations only to the components it manages, which are defined in a deployment descriptor or are accessible in specific classpath locations. Second, the container must have control over the creation of the component to be able to transparently perform the injection into the component.

Although resource injection would be most useful in the web tier if it were applicable to any Plain Old Java Object (POJO), this will have to wait for a future release. Table 2 lists the web-tier-managed components that support resource injection in applications based on the Java EE 5 platform.

Table 2: Components That Support Resource Injection
 
 
NameInterface or Class
Servlets
javax.servlet.Servlet
 
 
Servlet filters
javax.servlet.ServletFilter
 
 
Event listeners
javax.servlet.ServletContextListener
javax.servlet.ServletContextAttributeListener
javax.servlet.ServletRequestListener
javax.servlet.ServletRequestAttributeListener
javax.servlet.http.HttpSessionListener
javax.servlet.http.HttpSessionAttributeListener
javax.servlet.http.HttpSessionBindingListener
 
 
Taglib tag handlers
javax.servlet.jsp.tagext.JspTag
 
 
JavaServer Faces technology-managed beans
Plain Old Java Objects (POJOs)
 

JSP technology pages and tag files cannot accept resource injections either.  Because such pages are usually compiled only after receiving a request, an annotation included in a JSP technology page would not be available to the container at deployment time when resource injection occurs.

Tag library validators (TLVs) and TagExtraInfo (TEI) are other classes that the JSP technology container manages, but because their life cycle is limited to the compilation of the JSP technology pages, they are not valid candidates for injection.

Supporting resource injection on JavaServer Faces technology renderers, converters, or validators is not desirable because that would violate Model-View-Controller (MVC) separation of these presentation objects.  If these classes need to get access to resources, they should do so through a managed bean.

Sample Code

A Simple Servlet

The classic first Servlet can now do more than just display the usual Hello World! message. It can easily display an entry from its Java EE 5 platform environment.

private @Resource String welcomeMessage;

public class HelloWorld extends HttpServlet {

public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println(welcomeMessage);
}

<env-entry>
<env-entry-name>welcomeMessage</env-entry-name>
<env-entry-type>java.lang.String</env-entry-name>
<env-entry-value>Hello World from env-entry!</env-entry-value>
</env-entry>
 

A JavaServer Faces Technology-Managed Bean

The following example demonstrates the use of the @Resource annotation along with the life-cycle annotations @PostConstruct and @PreDestroy to simulate, in a simplified way, an EJB bean.

The managed bean has access to a DataSource object through the presence of the @Resource annotation. Next, it uses that DataSource to initialize itself with the annotated initBean() method before the managed bean is put into scope. The managed bean then uses the DataSource once again in the annotated flush() method to flush the data back to the database when the bean is removed from scope, that is, when the user has logged or timed out.

private @Resource javax.sql.DataSource userDS ;

public class UserDataBean {

// Ivars pertaining to the user

@PostConstruct
public void initBean() {
Connection conn = userDS.getConnection();
// Use the connection to populate UserDataBean ivars.
}

@PreDestroy
public void flush() {
Connection conn = userDS.getConnection();
// Use the connection to flush any modified ivars
// to the back end.
}

}

<managed-bean>
<managed-bean-name>userdata</managed-bean-name>
<managed-bean-class>somepkg.UserDataBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-bean>
 
Conclusion

As this article demonstrates, the support for resource injection in the web tier makes accessing resources from web applications significantly easier. Try it out. You'll probably be pleased with the amount of time and the number of lines of code you save. Meanwhile, watch for the next article in the "Web Tier to Go With Java EE 5" series, which will describe the new pound syntax introduced in the Unified Expression Language (UEL).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值