Caucho Technology
  • resin 4.0
  • dependency injection for resources


    The Dependency Injection pattern simplifies application code, and increases configuration flexibility by deferring component configuration and assembly to the container. Resin calls setters on the configured objects to assemble the resource dependencies.

    Demo

    Files in this tutorial

    WEB-INF/resin-web.xmlConfigures the movie application
    WEB-INF/classes/example/Movie.javaThe movie bean.
    WEB-INF/classes/example/MovieFinder.javaThe MovieFinder interface
    WEB-INF/classes/example/MovieFinderImpl.javaA MovieFinder implementation
    WEB-INF/classes/example/MovieLister.javaThe MovieLister to be configured with the finder implementation
    WEB-INF/classes/example/MovieServlet.javaThe MovieServlet to be configured with the finder implementation
    WEB-INF/classes/META-INF/web-beans.xmlweb-beans.xml marks the directory as containing components.

    Dependency Injection

    Dependency injection is a term used to describe a separation between the implementation of an object and the construction of an object it depends on, and the ability for a container like Resin to resolve the dependency.

    Since the container instantiates and assembles the dependencies, the code is simpler and the configuration is more flexible. It's easy to substitute test implementations as the dependent resources, for example.

    The MovieFinder example for this tutorial comes from Martin Fowler's Dependency Injection article.

    More details on Resin's configuration is available at the bean-style configuration page.

    Configuration as Assembly Line

    The Dependency Injector pattern could also be called the Assembly pattern because it resembles an assembly line making cars.

    • Parts are interchangable components like wheels. The parts might also be assembled like an engine in a car.
    • Parts are attached to the Chassis like a car's frame receiving an engine.
    • The Registry is holds partially-completed parts like a factory conveyor belt.
    • The Assembler provides the Registry and assembles the Chassis and Parts into a completed resource.

    Some important points:

    • The application code (Chassis and Parts) is independent of the Assembler.
    • Parts are interchangeable.
    • The code needs to select an assembly pattern, e.g. Setter Injection.

    Because the Assembler is independent of the code, a project could change the Assembler from Spring to Resin with no code changes. So using the Assembler/Dependency Injection pattern reduces dependencies on the framework. Only the configuration changes when changing Assemblers, not the code.

    While testing, the test case or the harness plays the Assembler role, simplifying the test suite and ensuring that the code under test is the production code. A test can create a test implementation of the Part, e.g. TestMovieFinder, for testing.

    In some cases, the application code can provide its own assemble() method for situations where the container is incapabile of assembling the components. For example, the MovieServlet could create an assemble() method that grabbed the MovieLocator from JNDI.

    Code for the Dependency Injection pattern

    The only code specific to the setter-based injection pattern is the addition of a setter method for the dependent resource. In many application, that setter will already be written, so no additional code would be required.

    Either an interface or a class can be used for the dependent resource, depending on the application's architecture. This example uses both: the MovieLister uses a dependent MovieFinder interface, and the MovieServlet uses the dependent MovieListener class.

    Example: finder injection
    import javax.inject.Inject;
    
    public class MovieListener {
      @Inject private MovieFinder _finder;
    
      ...
    }
    

    Configuration

    Example: Configuring the MovieFinder Service
    <web-app xmlns="http://caucho.com/ns/resin">
    
    <example:MovieFinderImpl xmlns:example="urn:java:example">
      <movie director="Jackson" title="Fellowship of the Ring"/>
      <movie director="Jackson" title="The Two Towers"/>
    
      <movie director="Lucas" title="Star Wars"/>
    
      <movie director="Gilliam" title="Brazil"/>
    </example:MovieFinderImpl>
    
    </web-app>
    

    Java Injection for Servlets

    The Dependency Injection pattern is just as useful for servlet configuration as it is for resources. This example makes the MovieLister a parameter of the servlet. The resin-web.xml will configure the servlet with the appropriate MovieLister

    The advantages of using dependency injection for the servlet are the same as for the resource:

    • The servlet code becomes simpler.
    • The servlet is no longer dependent on JNDI.
    • The servlet is more easily testable by configuring it with test versions of the MovieListener.
    Configuring the MovieServlet
    import javax.inject.Inject;
    
    public class MovieServlet extends HttpServlet {
      // Inject the MovieLister service
      @Inject private MovieLister _movieLister;
    
      ...
    }
    

    See also

    Demo


    Copyright © 1998-2011 Caucho Technology, Inc. All rights reserved.
    Resin ® is a registered trademark, and Quercustm, Ambertm, and Hessiantm are trademarks of Caucho Technology.