Find JSRs
Submit this Search


Ad Banner
 
 
 
 

JSRs: Java Specification Requests
JSR 330: Dependency Injection for Java

Updates to the Original JSR

The following updates have been made to the original proposal.

2015.01.09

Maintenance Lead: Bob Lee

E-Mail Address: crazybob@crazybob.org

Telephone Number: +1 314 537 6570

Fax Number: +1 650 253 0000

2010.03.01

Maintenance Leads: Bob Lee, VMWare

Representatives: Bob Lee, Rod Johnson

E-Mail Address: crazybob@crazybob.org, rod.johnson@vmware.com

Telephone Number: +1 314 537 6570, +1 415 290 0207

Fax Number: +1 650 253 0000, +1 425 944 0045


Original Java Specification Request (JSR)

Identification | Request | Contributions | Additional Information

Section 1. Identification

Submitting Member: Google and SpringSource

Name of Contact Person: Bob Lee and Rod Johnson

E-Mail Address: atinject@googlegroups.com

Telephone Number: +1 650 253 0000

Fax Number: +1 650 253 0000

Specification Leads: Bob Lee (Google), Rod Johnson (SpringSource)

E-Mail Address: atinject@googlegroups.com

Telephone Number: +1 650 253 0000

Fax Number: +1 650 253 0000


Initial Expert Group Membership:

-

Supporting this JSR:

Joshua Bloch
Paul Hammant (ThoughtWorks, PicoContainer founder)
Doug Lea
Tim Peierls
James Strachan
Hani Suleiman
Jason van Zyl (Maven, Plexus)
Thiago H de Paula Figueiredo (Tapestry IoC)



Section 2: Request

2.1 Please describe the proposed Specification:

This JSR will standardize:

  1. A set of annotations for use on injectable classes
  2. A typesafe, user-friendly injector configuration API that provides an integration point for higher level dependency injection configuration approaches
(see section 4.1 for more information)

2.2 What is the target Java platform? (i.e., desktop, server, personal, embedded, card, etc.)

Java SE 5 will be the minimum requirement, but Java SE 6 and 7-specific features will be available on those platforms.

2.3 The Executive Committees would like to ensure JSR submitters think about how their proposed technology relates to all of the Java platform editions. Please provide details here for which platform editions are being targeted by this JSR, and how this JSR has considered the relationship with the other platform editions.

This JSR targets Java SE, and it will lay a foundation for dependency injection in Java EE.

Should this JSR be voted on by both Executive Committees?

No.

2.5 What need of the Java community will be addressed by the proposed specification?

This specification will bring well proven dependency injection concepts to Java SE. It will lay a foundation upon which further innovation can occur.

2.6 Why isn't this need met by existing specifications?

Several existing JSRs specify higher level dependency injection configuration mechanisms but none provide the low level foundation necessary to integrate the higher level approaches. This JSR is unique in that it has a high level of consensus from the majority of the dependency injection community. It has the support of dependency injection pioneers like Rod Johnson, Paul Hammant, and Bob Lee.

2.7 Please give a short description of the underlying technology or technologies:

Existing approaches configure a dependency injector using XML, annotations or plain Java code. That injector is then used to construct objects and inject dependencies into them. This standard will provide a core API that can be driven at build and run time by higher-level configuration mechanisms such as XML and annotations. Objects configured using the various higher-level mechanisms will be able to freely depend on each other since the mechanisms will share a common foundation.

2.8 Is there a proposed package name for the API Specification? (i.e., javapi.something, org.something, etc.)

javax.inject or java.inject

2.9 Does the proposed specification have any dependencies on specific operating systems, CPUs, or I/O devices that you know of?

No.

2.10 Are there any security issues that cannot be addressed by the current security model?

No.

2.11 Are there any internationalization or localization issues?

No.

2.12 Are there any existing specifications that might be rendered obsolete, deprecated, or in need of revision as a result of this work?

Other specifications may want to define how their objects get injected. For example, how do I inject dependencies into a servlet?

2.13 Please describe the anticipated schedule for the development of this specification.

Early Draft Review would occur in Q3 '09. Public Review during Q4 '09, and Proposed Final Draft in Q1 '10.

2.14 Please describe the anticipated working model for the Expert Group working on developing this specification.

All of the work will be done in the open. The mailing list may only allow expert group members to post messages, but anyone will be able to follow and read the archives, and we'll likely have a publicly writable observer mailing list like JSR-294. The specification will be maintained using publicly-accessible source control and the latest snapshot will be available at any time.

2.15 It is important to the success of the community and each JSR that the work of the Expert Group be handled in a manner which provides the community and the public with insight into the work the Expert Group is doing, and the decisions that the Expert Group has made. The Executive Committees would like to ensure Spec Leads understand the value of this transparency and ask that each JSR have an operating plan in place for how their JSR will address the involvement of the community and the public. Please provide your plan here, and refer to the Spec Lead Guide for a more detailed description and a set of example questions you may wish to answer in your plan.

See 2.14

2.16 Please describe how the RI and TCK will de delivered, i.e. as part of a profile or platform edition, or stand-alone, or both. Include version information for the profile or platform in your answer.

The RI will be standalone but may also be included as a module in Java SE 7. The RI and TCK will be Apache-licensed and freely available.

2.17 Please state the rationale if previous versions are available stand-alone and you are now proposing in 2.13 to only deliver RI and TCK as part of a profile or platform edition (See sections 1.1.5 and 1.1.6 of the JCP 2 document).

N/A

2.18 Please provide a description of the business terms for the Specification, RI and TCK that will apply when this JSR is final.

The RI and TCK will be licensed under the Apache 2 license, and the Specification will be licensed under an agreement that satisfies the requirements of the JSPA.





Section 3: Contributions

3.1 Please list any existing documents, specifications, or implementations that describe the technology. Please include links to the documents if they are publicly available.

* Spring's dependency injection API: http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans/factory/annotation/package-summary.html
* A talk given by Bob Lee about DI and Guice specifically: http://crazybob.org/2007/06/introduction-to-guice-video-redux.html
* The Guice user's guide: http://docs.google.com/Doc?id=dd2fhx4z_5df5hw8

3.2 Explanation of how these items might be used as a starting point for the work.

This specification will incorporate lessons learned from pre-existing injector implementations. Benefiting from hindsight, it will be simpler and more toolable.



Section 4: Additional Information (Optional)

4.1 This section contains any additional information that the submitting Member wishes to include in the JSR.

This JSR will specify a means for obtaining objects in such a way as to maximize reusability, testability and maintainability compared to traditional approaches such as constructors, factories, and service locators (e.g., JNDI). This process, known as dependency injection, is beneficial to most nontrivial applications.

Many types depend on other types. For example, a Stopwatch might depend on a TimeSource. The types on which a type depends are known as its dependencies. The process of finding an instance of a dependency to use at run time is known as resolving the dependency. If no such instance can be found, the dependency is said to be unsatisfied, and the application is broken.


In the absence of dependency injection, an object can resolve its dependencies in a few ways. It can invoke a constructor, hard-wiring an object directly to its dependency's implementation and life cycle:

class Stopwatch {
    final TimeSource timeSource;
    Stopwatch () {
        timeSource = new AtomicClock(...);
    }
    void start() { ... }
    long stop() { ... }
}

If more flexibility is needed, the object can call out to a factory or service locator:

class Stopwatch {
    final TimeSource timeSource;
    Stopwatch () {
        timeSource = DefaultTimeSource.getInstance();
    }
    void start() { ... }
    long stop() { ... }
}

In deciding between these traditional approaches to dependency resolution, a programmer must make trade-offs. Constructors are more concise but restrictive. Factories decouple the client and implementation to some extent but require boilerplate code. Service locators decouple even further but reduce compile time type safety. All three approaches inhibit unit testing. For example, if the programmer uses a factory, each test against code that depends on the factory will have to mock out the factory and remember to clean up after itself or else risk side effects:

void testStopwatch() {
    TimeSource original = DefaultTimeSource.getInstance();
    DefaultTimeSource.setInstance(new MockTimeSource());
    try {
        // Now, we can actually test Stopwatch.
        Stopwatch sw = new Stopwatch();
        ...
    } finally {
        DefaultTimeSource.setInstance(original);
    }
}

In practice, supporting this ability to mock out a factory results in even more boilerplate code. Tests that mock out and clean up after multiple dependencies quickly get out of hand. To make matters worse, a programmer must predict accurately how much flexibility will be needed in the future or else suffer the consequences. If a programmer initially elects to use a constructor but later decides that more flexibility is required, the programmer must replace every call to the constructor. If the programmer errs on the side of caution and write factories up front, it may result in a lot of unnecessary boilerplate code, adding noise, complexity, and error-proneness.

Dependency injection addresses all of these issues. Instead of the programmer calling a constructor or factory, a tool called a dependency injector passes dependencies to objects:

class Stopwatch {
    final TimeSource timeSource;
    @Inject Stopwatch(TimeSource TimeSource) {
        this.TimeSource = TimeSource;
    }
    void start() { ... }
    long stop() { ... }
}

The injector further passes dependencies to other dependencies until it constructs the entire object graph. For example, suppose the programmer asked an injector to create a StopwatchWidget instance:

/** GUI for a Stopwatch */
class StopwatchWidget {
    @Inject StopwatchWidget(Stopwatch sw) { ... }
    ...
}

The injector might:

  1. Find a TimeSource
  2. Construct a Stopwatch with the TimeSource
  3. Construct a StopwatchWidget with the Stopwatch

This leaves the programmer's code clean, flexible, and relatively free of dependency-related infrastructure.

In unit tests, the programmer can now construct objects directly (without an injector) and pass in mock dependencies. The programmer no longer needs to set up and tear down factories or service locators in each test. This greatly simplifies our unit test:

void testStopwatch() {
    Stopwatch sw = new Stopwatch(new MockTimeSource());
    ...
}

The total decrease in unit-test complexity is proportional to the product of the number of unit tests and the number of dependencies.

Programmers annotate constructors, methods, and fields to advertise their injectability (constructor injection is demonstrated in the examples above).  A dependency injector identifies a class's dependencies by inspecting these annotations, and injects the dependencies at runtime. Moreover, the injector can verify that all dependencies have been satisfied at build time. A service locator, by contrast, cannot detect unsatisfied dependencies until run time.

A programmer configures a dependency injector so it knows what to inject. Different configuration approaches make sense in different contexts. One approach is to search the classpath for dependency implementations, avoiding the need for the programmer to write explicit code. This approach could be useful in quick-and-dirty prototypes. A programmer working on a large, long-lived application might prefer a more explicit, compartmentalized approach. For example, the programmer could write XML that tells the injector to inject an EJB client proxy named "NetworkTimeSource" when a class needs a TimeSource:

<binding type="TimeSource" ejb="NetworkTimeSource"/>

It often makes sense to use more than one configuration mechanism in the the same application. For example, a quick and dirty prototype might grow into a real application, and the programmer could incrementally migrate to a more maintainable configuration. As another example, a program might configure some resources explicitly, while others are configured automatically based on an external XML file or database.

This JSR will standardize a low-level kernel API that can be used directly by a user or as an integration point for higher level configuration approaches. This approach enables portable Java applications without quashing innovation in dependency injector configuration.