JBoss.org Community Documentation

12.1. POJO dependencies

Dependencies between beans (POJO instances) are created when they are wired together through the use of the @Inject annotation or <inject> element. Specifically a bean which has another bean injected into it is said to be dependent on the other bean. For example here we have a Person bean that is dependent on an Address bean.


public class Person {
    @Inject(bean="AddressBean")
    public void setAddress(Address address) {
        ...
    }
}

<bean name="Person" class="org.jboss.test.Person">
    <property name="address">
        <inject bean="AddressBean"/>
    </property>
</bean>

The reason for the dependency is because the address property of the Person bean cannot be configured until the Address bean has been deployed. Internally JBoss Microcontainer enforces this by moving each bean through a series of states during deployment. Consequently the Person bean will be prevented from moving to the CONFIGURED state until the Address bean has reached the INSTALLED state representing a deployed bean.

By default there are 8 states that a bean can be in during deployment and undeployment:

  • NOT_INSTALLED - Metadata describing the bean has been parsed from annotations or a deployment descriptor.

  • PRE_INSTALL - the scope of the bean within the microcontainer has been discovered and classloading dependencies have been resolved.

  • DESCRIBED - Any AOP dependencies have been added.

  • INSTANTIATED -All dependencies have been resolved to construct the bean. These include; a classloader exists, the class can be found, a constructor or factory method can be found and any parameter injections can be resolved.

  • CONFIGURED - All the property injections can be resolved. This includes any injections within collections.

  • CREATE - All the beans metioned in the @Depends annotation or <depends> element have reached the CREATE state including any parameter injections in the create method.

  • START - All the beans metioned in the @Depends annotation or <depends> element have reached the START state including any parameter injections in the start method.

  • INSTALLED - Any deployment actions have been processed and the bean has been added to the list of items that the controller supplies.

You may notice that we refer to injections being resolved in the above list. This is a shorthand way of saying that an injected bean has reached a certain state. In our simple example we can say that the injected Address bean has been resolved when it reaches the INSTALLED state. If necessary you can change the state that an injected bean must reach before being considered resolved by using the dependentState/state attribute.


public class Person {
    @Inject(bean="OtherBean",
            dependentState="Instantiated")
    public void setAddress(Address address) {
        ...
    }
}

<bean name="Person" class="org.jboss.test.Person">
    <property name="address">
        <inject bean="Address" state="Instantiated"/>
    </property>
</bean>

Here we are saying the Address bean needs to reach the INSTANTIATED state before the Person bean can use it to configure the address property and thus move to the CONFIGURED state. Be aware that setting the state value to Described in this case would not be appropriate since we must first have an instance of the Address bean before we can inject a reference to it into another bean.

Note

The following six values can be used for the dependentState/state attribute to control injection. If no value is specified then by default the Installed state is used.

  • Described

  • Instantiated

  • Configured

  • Create

  • Start

  • Installed

The ability to control when injection occurs is especially useful when dealing with circular dependencies. A circular dependency happens when one bean depends on another which in turn depends on the first bean:


<bean name="Circular1" class="org.jboss.example.InjectionBean">
    <constructor>
        <parameter>Circular1</parameter>
    </constructor>

    <property name="other">
        <inject bean="Circular2"/>
    </property>
</bean>

<bean name="Circular2" class="org.jboss.example.InjectionBean">
    <constructor>
        <parameter>Circular2</parameter>
    </constructor>

    <property name="other">
        <inject bean="Circular1"/>
    </property>
</bean> 

In this configuration the microcontainer is unable to deploy either bean since each one is waiting in the INSTANTIATED state waiting for the other to reach the INSTALLED state. To solve this we can use the state attribute to specify that Circular1 can be injected into Circular2 as soon as it reaches the INSTANTIATED state.


<bean name="Circular1" class="org.jboss.example.InjectionBean">
    <constructor>
        <parameter>Circular1</parameter>
    </constructor>

    <property name="other">
        <inject bean="Circular2"/>
    </property>
</bean>

<bean name="Circular2" class="org.jboss.example.InjectionBean">
    <constructor>
        <parameter>Circular2</parameter>
    </constructor>

    <property name="other">
        <inject bean="Circular1" state="Instantiated"/>
    </property>
</bean>

Circular2 can thus progress to the INSTALLED state whereupon Circular1 will inject it into its other property and continue deploying.