I just submitted the Proposed Final Draft of JSR-299, Contexts and Dependency Injection, to the JCP. Download it here[1]. We're gearing up for a final release in August, in time for the Java EE 6 release in September. Thanks to everyone who put so much effort into this!
If you have not being paying attention to 299, now is a great time to get up to date. This is arguably the most significant enhancement in EE 6, providing the following suite of functionality:
- a completely general typesafe dependency injection model,
- contextual lifecycle management for injectable objects,
- an event notification model,
- interceptor bindings via user-defined annotations,
- typesafe decorators,
- a complete SPI for integration of third-party web or component frameworks, and
- integration with JSF, servlets and JSP, including
- a conversation context for JSF
Best of all, this functionality is provided with a clean, simple, uniform programming model that emphasizes two primary values: typesafety, and loose coupling. JSR-299 doesn't use strings or XML to wire together beans, events, interceptors and decorators. Instead, it uses the Java type system and user defined binding annotations
to discover the relationships between loosely coupled components.
Now is a good time to clear up some misconceptions I've seen floating about.
JSR-299 is just for EJBs
This isn't true at all.
Out of the box you can inject into just about any kind of thing in the Java EE environment, including servlets, servlet filters, servlet event listeners, JAX-WS web service endpoints and JAX-RS resources. Even better, there's an SPI so that any third-party framework (for example, a web framework like Wicket) can easily ask the 299 implementation to perform injection upon objects managed by the framework.
The kinds of objects you can inject include:
- managed beans (plain Java classes),
- local EJB session beans,
- objects obtained from a producer method or producer field, and
- Java EE component environment resources (datasources, connectors, persistence contexts, JMS message destinations, web services, remote EJBs, etc.)
In case you're trying to not believe me (you know who you are), here is a class that can be injected:
final class Head {}
Here's a class that uses injection:
final class Person { private Head head; @Initializer Person(Head head) { this.head=head; } }
There's also a simple SPI to allow third-party frameworks (including other container like Spring) to offer their own objects up for injection via the 299 container.
JSR-299 is tied to JSF
Also not true. In an EE 6 environment, JSR-299 comes pre-integrated with Java Servlets, JSP and JAX-RS, in addition to JSF. And 299 provides SPIs to enable integration with your favorite web framework. These SPIs make it easier than ever before to integrate third-party web frameworks with the rest of the EE environment.
JSR-299 is tied to heavyweight
Java EE containers
Obviously, integration with the Java EE environment was an extremely high priority for the expert group, so you'll come across lots of information about Java EE integration when you read the specification. Certain functionality defined by JSR-299 is specific to certain other EE technologies. For example, if there's no EJB container, we can't inject EJBs! But this doesn't mean that JSR-299 is only available in a traditional Java EE container like JBoss or GlassFish.
Instead, 299 was designed to be suitable for inclusion in a variety of execution environments, for example:
- Java EE 6 defines a web profile for servlet containers along the lines of Caucho Resin, JBoss Web Platform or SpringSource dm server that don't want to support the full set of legacy EE 5 technologies. It is proposed that the web profile will require support for JSR-299.
- EJB 3.1 defines an embeddable container that runs in the Java SE environment. The embeddable container will also support JSR-299.
However, JSR-299 does not currently define a bootstrap API for starting and running the container standalone in the SE environment. Instead, this API is being defined by JSR-330. Unlike JSR-299, JSR-330 is not defining everything that is needed in order to write portable applications. So you'll still need JSR-299 if you want your application to be portable to other container implementations. Therefore, we plan a maintenance release of JSR-299 that includes support for the JSR-330 bootstrap API. For now, if you want to run JSR-299 in the SE environment, you'll need to use a vendor-specific bootstrap API.
JSR-299 uses a lot of annotations
We've been very careful to not require the use of many annotations in simple usecases. Let's take dependency injection as an example of this.
Almost any Java class may be injected by the container without the need for any annotation on the class. Most injection points require a single annotation to indicate to the container that injection should be performed. The container uses the Java type of the injection point to decide what object should be injected.
Then, in more complex cases where knowledge of the type system alone is not sufficient to unambiguously express a dependency, the container can use additional user-defined annotations to resolve the ambiguity. The good news is that the user-defined annotation usually expresses something meaningful in terms of the application business logic. They therefore improve code readability.
For example, this is neither typesafe, nor very readable:
@PersistenceContext(unitName="userDB") EntityManager em;
So in JSR-299, you can write this instead:
@UserDatabase EntityManager em;
A very similar model is followed for interceptor bindings and event observation, and for decorator bindings, which are just a special case of dependency injection.