JBoss.org Community Documentation

12.2. Supply and Demand

Sometimes dependencies may exist between beans that are not wired together using injections. One example would be a bean representing a service that requires a transaction manager to be present in JNDI before it can start. In these situations we can use a @Demand annotation or <demand> element to specify that we need another bean to be deployed before we can reach a certain state.


@Demands(@Demand("TransactionManager"))
public class Example {
    ...
}

<bean name="TransactionManager" class="com.acme.TransactionManager"/>

<bean name="Name2" class="com.acme.Example">
    <demand>TransactionManager</demand>
</bean>

By default the bean declaring the demand will wait until the beans it requires have been deployed before it moves to the INSTANTIATED state. However you can change this using the whenRequired/state attribute to specify a different state that can only be reached once all the beans listed as demands have been deployed.


@Demands(@Demand("TransactionManager", whenRequired="Start"))
public class Example {
    ...
}

<bean name="TransactionManager" class="com.acme.TransactionManager"/>

<bean name="Name2" class="com.acme.Example">
    <demand state="Start">TransactionManager</demand>
</bean>

Here we are stating that the TransactionManager bean must be deployed before the Name2 bean can reach the Start state. To specify multiple dependencies on other beans you simply need to list @Demand annotations or nest <demand> elements:


@Demands(@Demand("TransactionManager", whenRequired="Start"),
         @Demand("OtherBean"))
public class Example {
    ...
}

<bean name="TransactionManager" class="com.acme.SomeSingleton">
    <property name="host">http://www.jboss.org</property>
</bean>

<bean name="Name2" class="com.acme.Example">
    <demand state="Start">TransactionManager</demand>
    <demand>OtherBean</demand>
</bean>

In addition to specifying dependencies on other beans you can also specify dependencies on arbitrary objects that other beans supply. This can be useful if a bean depends on something that is provided by multiple beans but doesn't necessarily care which one provides it. To create these arbitrary objects you need to use the @Supply annotation or <supply> element.


@Supplies(@Supply("SomethingUseful"))
public class Provider {
    ...
}

@Demands(@Demand("SomethingUseful"))
public class Consumer {
    ...
}

<bean name="Provider" class="com.acme.Provider">
    <supply>SomethingUseful</supply>
</bean>

<bean name="Consumer" class="com.acme.Consumer">
    <demand>SomethingUseful</demand>
</bean> 

A bean can also supply multiple objects if necessary:


@Supplies(@Supply("SomethingUseful"),
          @Supply("SomethingElse"))
public class Provider {
    ...
}

@Demands(@Demand("SomethingUseful"))
public class Consumer {
    ...
}

@Demand(@Demand("SomethingElse"))
public class OtherConsumer {
    ...
}

<bean name="Provider" class="com.acme.Provider">
    <supply>SomethingUseful</supply>
    <supply>SomethingElse</supply>
</bean>

<bean name="Consumer" class="com.acme.Consumer">
    <demand>SomethingUseful</demand>
</bean>

<bean name="OtherConsumer" class="com.acme.Consumer">
    <demand>SomethingElse</demand>
</bean> 

Behind the scenes JBoss Microcontainer creates a bean of type java.lang.Object for each @Supply annotation or <supply> element named after its value. These beans are then moved automatically through all of the states to reach the INSTALLED state and become deployed. From this point onwards the @Demand annotation and <demand> element work in exactly the same way as before, checking to see if the named bean has been deployed before allowing the bean declaring the demand/s to move to a certain state.