Injecting arbitrary objects using Producers

What happens if we want to inject an object or type at runtime, dynamically? CDI allows us to do this with the concept of productions. Producer methods are the way to inject arbitrary objects into the container, which are not registered as beans through the annotations. Typically, this is the way to get dynamic behavior.

Let us suppose we have a payment system for checking credit worthiness with some financial service legal entity. It is a very simple credit model-you only need an account number - and we can define a contract for this service as a Java interface.

public interface CreditProcessor {
  public void check(String account);
}

We will reuse the annotations from the standalone travel service example, @Premium and @Economy. We are given the business requirement for the economy as a high volume and high turnover, and the model leverages lots of promotional workers who act on behalf of the businesses to find and locate customers. There are a lot of dynamics and so it can be modeled as a production using the following HouseholdCredit class:

public class HouseholdCredit {
  private static AtomicInteger counter = new AtomicInteger(1000);
  
  @Produces
  @Economy
  public CreditProcessor createCreditProcessor() {
    return new StreetCreditProcessor("promoter"+counter.getAndIncrement());
  }
  
  public static class StreetCreditProcessor
  implements CreditProcessor {
    private final String workerId;
  
    public StreetCreditProcessor(String workerId) {
      this.workerId = workerId;
    }
  
    @Override
    public void check(String account) {/*...*/}
  
    @Override
    public String toString() {
      return "StreetCreditProcessor{" +
        "workerId='" + workerId + ''' +
        '}';
    }
  }
}

The key annotation is @javax.enterprise.inject. Produces, which informs the CDI container that the application is responsible for creating a particular bean type. The @Produces annotation designates a POJO application bean as producer of a CDI managed beans.

Tip

Do not confuse CDI's @Produces with another Java EE 7 annotation @javax.ws.rs.Produces, which is part of JAX-RS. See Chapter 8, RESTful Services JAX-RS 2.0.

The class HouseholdCredit declares to CDI that it can generate a CreditProcessor with the qualifier @Economy. It does this by instantiating a static inner class called StreetCreditProcessor, but also notice that this type is not annotated explicitly. The CDI container will locate this particular bean type and create it by instantiating a Household object for the lifetime of the container, and then invoking the production method, when required by the injection point. The conversation context of the supplied bean is decided at the injection point, as you can see in the following unit test:

package je7hb.standalone;

import je7hb.travelfunk.AbstractCdiContainerTest;
import org.junit.Test;
import javax.inject.Inject;
import static org.junit.Assert.*;

public class CreditProcessorTest extends AbstractCdiContainerTest {
  private @Inject @Economy CreditProcessor agent;

  @Test
  public void shouldInjectStreetCredit() {
    assertNotNull(agent);
    agent.check("12354678");
    System.out.printf("agent=%s
", agent );
  }
}

It is instructive to examine the following output from the program with the CDI container test debugging switched on.

The output from the program is as follows:

AbstractCdiContainerTest#startUpContainer() cdiContainer=null
29 [main] INFO org.jboss.weld.Version - WELD-000900 1.1.9 (Final)
117 [main] INFO org.jboss.weld.Bootstrap - WELD-000101 ...
Initialization from CDI
Complete.
AbstractCdiContainerTest#setUp() containerRefCount=1, cdiContainer=org.apache.deltaspike.cdise.weld.WeldContainerControl@49b35574
agent = StreetCreditProcessor{workerId = 'promoter1000'}
AbstractCdiContainerTest#tearDown() containerRefCount = 1, cdiContainer = org.apache.deltaspike.cdise.weld.WeldContainerControl@49b35574
AbstractCdiContainerTest#shutdownContainer() cdiContainer = org.apache.deltaspike.cdise.weld.WeldContainerControl@49b35574

Process finished with exit code 0
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.186.219