Dependency injection

The basic idea behind dependency injection with VRaptor is to inject objects in your business components.

  1. A simple example would be a DaoFactory, a factory capable of instantiating daos in some uniform way... the following example is a quite simplistic implementation:
    public class DaoFactory {
    
            public PersonDao getPersonDao() {
                    return new PersonDao();
            }
    
            public StudentDao getStudentDao() {
                    return new StudentDao();
            }
    
    }
  2. Now let's create a simple interceptor that instantiates this factory:

    Note: The @Out annotation is used to outject the factory field to the request scope...

    public class DaoInterceptor implements Interceptor {
    
            @Out
            private DaoFactory factory = new DaoFactory();
    
            public void intercept(LogicFlow flow) throws LogicException,
                            ViewException {
                    // executes the next interceptor or business logic
                    flow.execute();
            }
    
    }
  3. And finally, lets create a component which gets this factory injected:
    @Component("injection")
    @InterceptedBy(DaoInterceptor.class)
    public class InjectionExample {
    
            @In
            private DaoFactory factory;
    
            public void test() {
                    // do something with the injected factory
            }
    
    }

    If you call injection.test.logic the following flow gets executed:

    Instantiate Interceptor --> Calls intercept method -->
    
    Interceptor calls flow.execute --> Outjects the dao factory -->
    
    Instantiate Bussiness Component --> Injects the dao factory -->
    
    Read parameters --> Call Logic method --> Redirects to view page
    
    Finishes the intercept method
    

Injection Scope

The injection uses by default the request scope. You can use the same scopes as the @Out annotation: see ScopeType.

Dependency Injection through a Constructor

VRaptor supports constructor injection by looking for objects in all scopes. For example:

public class InjectionExample {

        private DaoFactory factory;

        public InjectionExample(DaoFactory factory) {
                this.factory = factory;
        }

        public void test() {
                // do something with the injected factory
        }

}

If DaoFactory is contained in the package org.vraptor.dao, then VRaptor looks for the key org.vraptor.dao.DaoFactory in all scopes: logic, request, session and application, in this order.

If it does not find this key in any scope, its unable to instantiate your component and will throw an Exception.

Otherwise it uses the key value to pass as an argument to the constructor.

No component can have more than one constructor available, otherwise you would be able to create complex and strange components with potential bugs.

In order to make the above example with constructor injection to work, simply use the following interceptor:

public class DaoInterceptor implements Interceptor {

        @Out(key="org.vraptor.dao.DaoFactory")
        private DaoFactory factory = new DaoFactory();

        public void intercept(LogicFlow flow) throws LogicException,
                        ViewException {
                // executes the next interceptor or business logic
                flow.execute();
        }

}

Direct access the request/response/session/servlet context?

You can get direct access to the four basic contexts through constructor injection. Simply add your constructor as:

public MyLogicConstructor(HttpServletRequest request) {
        this.request = request;
}

And leave the request as a member variable. Do whatever you want with it!

You can also grab it through the usual @In annotation:

          @In
          private HttpServletRequest request;

          @In
          private HttpServletResponse response;

          @In
          private HttpSession session;

          @In
                  private ServletContext servletContext;