AgE 2.7 : Components

On this page:

 

Any POJO can be a component in AgE. As such, it has properties and dependencies

 

Properties   

AgE observes the standard Java way to define object properties: the JavaBeans convention for naming accessor and mutator methods. A component can be specified along with initial property values, which will be set by the container after instantiation (see configuration).

public class MyComponent { 
   public void setPropertyA(String someValue){...}
   public String getPropertyA(){...}
} 

 It should be noted that property values should usually be only initialized with value objects, that is object with no identity and which lifecycle is not managed by the container (in contrast to other components). If some class have a writable property which actually should be injected with another component, such a method should not be treated as a property, but as defining a dependency which will be method-injected. There is currently no strong distinction in the platform between these two semantics, but that will probably change in the future.

Dependencies

A component can have dependencies to other components. These dependencies will be satisfied by the container, by injecting appropriate instances into a given component constructor, methods and fields. The resolution of these dependencies can be explicitly provided by the user (see configuration) or be left to the container for implicit autowiring.

Explicit resolution
  • Constructor dependencies: users can provide explicit arguments to any public constructor of a class. Both component instances and value types can be injected this way.

    public class MyComponent {	
       public MyComponent(OtherComponent someInstance, String someValue){...}
    }
  • Method dependencies: users can also explicitly inject dependencies into methods, if these follow the JavaBean naming conventions syntax. The dependency semantic of such a method should not be confused with an actual property (see above).

    public class MyComponent { 
       public void setOtherComponent(OtherComponent someInstance){...}
    } 
Implicit resolution 

The container will identify the injection points of a component with respect to the JSR-330 specification, on the base of @Inject annotations. Constructors are injected first, followed by fields and then methods. Fields and methods in superclasses are injected before those in subclasses 

As of this writing, there is no support yet for JSR-330 @Qualifier and Provider<T> features.

  • Constructor dependencies: only other components can be automatically injected (with constrast to manual constructor injection above). The constructor can have any accessibility modifier.

    public class MyComponent { 
      @Inject
      MyComponent(OtherComponent someInstance){...}
    } 
  • Field dependencies: fields can have any accessibility modifier.

    public class MyComponent { 
      @Inject
      private OtherComponent someInstance;
    
      @Inject
      YetAnotherComponent yetAnotherInstance;
    } 
  • Method dependencies: methods can have any name, accessibility modifier and number of parameters. The return type is ignored.

    public class MyComponent { 
       @Inject 
       void injectSomeComponents(OtherComponent someInstance, YetAnotherComponent yetAnotherInstance ){...} 
    }  

Explicit resolution takes precedence over implicit one. If the user specifies arguments for an explicit constructor, the container will no longer look for an annotated one. If the user specifies explicit arguments for some annotated method, it will no longer be autowired. This can be used to resolve problems with ambiguous dependencies, i.e. when there are many candidate components for some given dependency. Though the container is not able to perform autowiring, this conflict can be manually resolved by the user.

Circular dependencies

Circular dependencies can be broken by acquiring a reference to the container instead (see below), and then retrieving the dependency during an initialization phase (see lifecycle). This will probably be replaced in the future with JSR-330 Provider<T>.

Injecting the container 

The container itself can be injected using Interface Injection. Components simply need to implement the IComponentInstanceProviderAware interface:

public class MyComponent implements  IComponentInstanceProviderAware {
   @Override 
   public void setInstanceProvider(IComponentInstanceProvider provider) {...}
}