13.2. Use CDI

13.2.1. Enable CDI in the Apache Karaf Container

CDI is not enabled by default in the Apache Karaf container. To enable CDI in Karaf, follow the instructions in Section 14.2, “Enabling Pax CDI”.

13.2.2. Use CDI to Develop an Application

Contexts and Dependency Injection (CDI) gives you tremendous flexibility in developing applications, reusing code, adapting your code at deployment or run-time, and unit testing. JBoss Fuse includes Weld, the reference implementation of CDI. These tasks show you how to use CDI in your enterprise applications.

13.2.2.1. Exclude Beans From the Scanning Process

One of the features of Weld, the JBoss Fuse implementation of CDI, is the ability to exclude classes in your archive from scanning, having container lifecycle events fired, and being deployed as beans. This is not part of the JSR-346 specification.

The following example has several <weld:exclude> tags:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:weld="http://jboss.org/schema/weld/beans"
       xsi:schemaLocation="
          http://java.sun.com/xml/ns/javaee http://docs.jboss.org/cdi/beans_1_0.xsd
          http://jboss.org/schema/weld/beans http://jboss.org/schema/weld/beans_1_1.xsd">

    <weld:scan>

        <!-- Don't deploy the classes for the swing app! -->
        <weld:exclude name="com.acme.swing.**" /> 1

        <!-- Don't include GWT support if GWT is not installed -->
        <weld:exclude name="com.acme.gwt.**"> 2
            <weld:if-class-available name="!com.google.GWT"/>
        </weld:exclude>

        <!--
            Exclude classes which end in Blether if the system property verbosity is set to low
            i.e.
              java ... -Dverbosity=low
        -->
        <weld:exclude pattern="^(.*)Blether$"> 3
            <weld:if-system-property name="verbosity" value="low"/>
        </weld:exclude>

       <!--
             Don't include JSF support if Wicket classes are present, and the viewlayer system
             property is not set
        -->
        <weld:exclude name="com.acme.jsf.**"> 4
            <weld:if-class-available name="org.apache.wicket.Wicket"/>
            <weld:if-system-property name="!viewlayer"/>
        </weld:exclude>
    </weld:scan>
</beans>
1
The first one excludes all Swing classes.
2
The second excludes Google Web Toolkit classes if Google Web Toolkit is not installed.
3
The third excludes classes which end in the string Blether (using a regular expression), if the system property verbosity is set to low.
4
The fourth excludes Java Server Faces (JSF) classes if Wicket classes are present and the viewlayer system property is not set.

The formal specification of Weld-specific configuration options can be found at http://jboss.org/schema/weld/beans_1_1.xsd.

13.2.2.2. Use an Injection to Extend an Implementation

You can use an injection to add or change a feature of your existing code.

The following example adds a translation ability to an existing class, and assumes you already have a Welcome class, which has a method buildPhrase. The buildPhrase method takes as an argument the name of a city, and outputs a phrase like "Welcome to Boston!".

Example: Inject a Translator Bean Into the Welcome Class

The following injects a hypothetical Translator object into the Welcome class. The Translator object can be an EJB stateless bean or another type of bean, which can translate sentences from one language to another. In this instance, the Translator is used to translate the entire greeting, without modifying the original Welcome class. The Translator is injected before the buildPhrase method is called.

public class TranslatingWelcome extends Welcome {

    @Inject Translator translator;

    public String buildPhrase(String city) {
        return translator.translate("Welcome to " + city + "!");
    }
    ...
}

13.2.3. Ambiguous or Unsatisfied Dependencies

Ambiguous dependencies exist when the container is unable to resolve an injection to exactly one bean.

Unsatisfied dependencies exist when the container is unable to resolve an injection to any bean at all.

The container takes the following steps to try to resolve dependencies:

  1. It resolves the qualifier annotations on all beans that implement the bean type of an injection point.
  2. It filters out disabled beans. Disabled beans are @Alternative beans which are not explicitly enabled.

In the event of an ambiguous or unsatisfied dependency, the container aborts deployment and throws an exception.

To fix an ambiguous dependency, see Use a Qualifier to Resolve an Ambiguous Injection.

13.2.3.1. Qualifiers

Qualifiers are annotations used to avoid ambiguous dependencies when the container can resolve multiple beans, which fit into an injection point. A qualifier declared at an injection point provides the set of eligible beans, which declare the same Qualifier.

Qualifiers have to be declared with a retention and target as shown in the example below.

Example: Define the @Synchronous and @Asynchronous Qualifiers

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface Synchronous {}

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface Asynchronous {}

Example: Use the @Synchronous and @Asynchronous Qualifiers

@Synchronous
public class SynchronousPaymentProcessor implements PaymentProcessor {
   public void process(Payment payment) { ... }
}

@Asynchronous
public class AsynchronousPaymentProcessor implements PaymentProcessor {
   public void process(Payment payment) { ... }
}

13.2.3.2. Use a Qualifier to Resolve an Ambiguous Injection

You can resolve an ambiguous injection using a qualifier. Read more about ambiguous injections at Ambiguous or Unsatisfied Dependencies.

The following example is ambiguous and features two implementations of Welcome, one which translates and one which does not. The injection needs to be specified to use the translating Welcome.

Example: Ambiguous injection

public class Greeter {
  private Welcome welcome;

  @Inject
  void init(Welcome welcome) {
    this.welcome = welcome;
  }
  ...
}

Resolve an Ambiguous Injection with a Qualifier
  1. To resolve the ambiguous injection, create a qualifier annotation called @Translating:

    @Qualifier
    @Retention(RUNTIME)
    @Target({TYPE,METHOD,FIELD,PARAMETERS})
    public @interface Translating{}
  2. Annotate your translating Welcome with the @Translating annotation:

    @Translating
    public class TranslatingWelcome extends Welcome {
        @Inject Translator translator;
        public String buildPhrase(String city) {
            return translator.translate("Welcome to " + city + "!");
        }
        ...
    }
  3. Request the translating Welcome in your injection. You must request a qualified implementation explicitly, similar to the factory method pattern. The ambiguity is resolved at the injection point.

    public class Greeter {
      private Welcome welcome;
      @Inject
      void init(@Translating Welcome welcome) {
        this.welcome = welcome;
      }
      public void welcomeVisitors() {
        System.out.println(welcome.buildPhrase("San Francisco"));
      }
    }

13.2.4. Managed Beans

Managed Beans are defined as container-managed objects with minimal programming restrictions, otherwise known by the acronym POJO (Plain Old Java Object). They support a small set of basic services, such as resource injection, lifecycle callbacks, and interceptors. Companion specifications, such as EJB and CDI, build on this basic model.

With very few exceptions, almost every concrete Java class that has a constructor with no parameters (or a constructor designated with the annotation @Inject) is a bean.

13.2.4.1. Types of Classes That are Beans

A managed bean is a Java class. The basic lifecycle and semantics of a managed bean are defined by the Managed Beans specification. You can explicitly declare a managed bean by annotating the bean class @ManagedBean, but in CDI you do not need to. According to the specification, the CDI container treats any class that satisfies the following conditions as a managed bean:

  • It is not a non-static inner class.
  • It is a concrete class, or is annotated @Decorator.
  • It is not annotated with an EJB component-defining annotation or declared as an EJB bean class in ejb-jar.xml.
  • It does not implement interface javax.enterprise.inject.spi.Extension.
  • It has either a constructor with no parameters, or a constructor annotated with @Inject.

The unrestricted set of bean types for a managed bean contains the bean class, every superclass and all interfaces it implements directly or indirectly.

If a managed bean has a public field, it must have the default scope @Dependent.

13.2.4.2. Use CDI to Inject an Object Into a Bean

CDI is activated automatically if CDI components are detected in an application. If you wish to customize your configuration to differ from the default, you can include META-INF/beans.xml or WEB-INF/beans.xml to your deployment archive.

Inject Objects into Other Objects
  1. To obtain an instance of a class, annotate the field with @Inject within your bean:

    public class TranslateController {
       @Inject TextTranslator textTranslator;
       ...
  2. Use your injected object’s methods directly. Assume that TextTranslator has a method translate:

    // in TranslateController class
    
    public void translate() {
       translation = textTranslator.translate(inputText);
    }
  3. Use an injection in the constructor of a bean. You can inject objects into the constructor of a bean as an alternative to using a factory or service locator to create them:

    public class TextTranslator {
    
       private SentenceParser sentenceParser;
       private Translator sentenceTranslator;
    
       @Inject
       TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {
          this.sentenceParser = sentenceParser;
          this.sentenceTranslator = sentenceTranslator;
       }
    
       // Methods of the TextTranslator class
       ...
    }
  4. Use the Instance(<T>) interface to get instances programatically. The Instance interface can return an instance of TextTranslator when parameterized with the bean type.

    @Inject Instance<TextTranslator> textTranslatorInstance;
    ...
    public void translate() {
       textTranslatorInstance.get().translate(inputText);
    }

When you inject an object into a bean, all of the object’s methods and properties are available to your bean. If you inject into your bean’s constructor, instances of the injected objects are created when your bean’s constructor is called, unless the injection refers to an instance that already exists. For instance, a new instance would not be created if you inject a session-scoped bean during the lifetime of the session.

13.2.5. Contexts and Scopes

A context, in terms of CDI, is a storage area that holds instances of beans associated with a specific scope.

A scope is the link between a bean and a context. A scope/context combination may have a specific lifecycle. Several pre-defined scopes exist, and you can create your own. Examples of pre-defined scopes are @RequestScoped, @SessionScoped, and @ConversationScope.

13.2.5.1. Available Contexts

Table 13.1. Available contexts

ContextDescription

@Dependent

The bean is bound to the lifecycle of the bean holding the reference.

@ApplicationScoped

The bean is bound to the lifecycle of the application.

@RequestScoped

The bean is bound to the lifecycle of the request.

@SessionScoped

The bean is bound to the lifecycle of the session.

@ConversationScoped

The bean is bound to the lifecycle of the conversation. The conversation scope is between the lengths of the request and the session, and is controlled by the application.

Custom scopes

If the above contexts do not meet your needs, you can define custom scopes.

13.2.6. Bean Lifecycle

This task shows you how to save a bean for the life of a request.

The default scope for an injected bean is @Dependent. This means that the bean’s lifecycle is dependent upon the lifecycle of the bean that holds the reference. Several other scopes exist, and you can define your own scopes. For more information, see “Contexts and Scopes”.

Manage Bean Lifecycles

Annotate the bean with the desired scope:

@RequestScoped
@Named("greeter")
public class GreeterBean {
  private Welcome welcome;
  private String city; // getter & setter not shown
  @Inject   void init(Welcome welcome) {
    this.welcome = welcome;
  }
  public void welcomeVisitors() {
    System.out.println(welcome.buildPhrase(city));
  }
}

Your bean is saved in the context relating to the scope that you specify, and lasts as long as the scope applies.

13.2.6.1. Use a Producer Method

This task shows how to use producer methods to produce a variety of different objects that are not beans for injection.

Example: Use a producer method instead of an alternative, to allow polymorphism after deployment

The @Preferred annotation in the example is a qualifier annotation. For more information about qualifiers, see Qualifiers.

@SessionScoped
public class Preferences implements Serializable {
   private PaymentStrategyType paymentStrategy;
   ...
   @Produces @Preferred
   public PaymentStrategy getPaymentStrategy() {
       switch (paymentStrategy) {
           case CREDIT_CARD: return new CreditCardPaymentStrategy();
           case CHECK: return new CheckPaymentStrategy();
           default: return null;
       }
   }
}

The following injection point has the same type and qualifier annotations as the producer method, so it resolves to the producer method using the usual CDI injection rules. The producer method is called by the container to obtain an instance to service this injection point.

@Inject @Preferred PaymentStrategy paymentStrategy;

Example: Assign a scope to a producer method

The default scope of a producer method is @Dependent. If you assign a scope to a bean, it is bound to the appropriate context. The producer method in this example is only called once per session.

@Produces @Preferred @SessionScoped
public PaymentStrategy getPaymentStrategy() {
   ...
}

Example: Use an injection inside a producer method

Objects instantiated directly by an application cannot take advantage of dependency injection and do not have interceptors. However, you can use dependency injection into the producer method to obtain bean instances.

@Produces @Preferred @SessionScoped
public PaymentStrategy getPaymentStrategy(CreditCardPaymentStrategy ccps,
                                          CheckPaymentStrategy cps ) {
   switch (paymentStrategy) {
      case CREDIT_CARD: return ccps;
      case CHEQUE: return cps;
      default: return null;
   }
}

If you inject a request-scoped bean into a session-scoped producer, the producer method promotes the current request-scoped instance into session scope. This is almost certainly not the desired behavior, so use caution when you use a producer method in this way.

Note

The scope of the producer method is not inherited from the bean that declares the producer method.

Producer methods allow you to inject non-bean objects and change your code dynamically.

13.2.7. Named Beans

You can name a bean by using the @Named annotation. Naming a bean allows you to use it directly in Java Server Faces (JSF) and Expression Language (EL).

The @Named annotation takes an optional parameter, which is the bean name. If this parameter is omitted, the bean name defaults to the class name of the bean with its first letter converted to lower-case.

13.2.7.1. Use Named Beans

Configure Bean Names Using the @Named Annotation
  1. Use the @Named annotation to assign a name to a bean.

    @Named("greeter")
    public class GreeterBean {
      private Welcome welcome;
    
      @Inject
      void init (Welcome welcome) {
        this.welcome = welcome;
      }
    
      public void welcomeVisitors() {
        System.out.println(welcome.buildPhrase("San Francisco"));
      }
    }

    In the example above, the default name would be greeterBean if no name had been specified.

  2. In the context of Camel CDI, the named bean is automatically added to the registry and can be accessed from a Camel route, as follows:
    from("direct:inbound").bean("greeter");

13.2.8. Alternative Beans

Alternatives are beans whose implementation is specific to a particular client module or deployment scenario.

By default, @Alternative beans are disabled. They are enabled for a specific bean archive by editing its beans.xml file.

Example: Defining Alternatives

This alternative defines a implementation of both @Synchronous PaymentProcessor and @Asynchronous PaymentProcessor, all in one:

@Alternative @Synchronous @Asynchronous

public class MockPaymentProcessor implements PaymentProcessor {

   public void process(Payment payment) { ... }

}

13.2.8.1. Override an Injection with an Alternative

You can use alternative beans to override existing beans. They can be thought of as a way to plug in a class which fills the same role, but functions differently. They are disabled by default.

This task shows you how to specify and enable an alternative.

Override an Injection

This task assumes that you already have a TranslatingWelcome class in your project, but you want to override it with a "mock" TranslatingWelcome class. This would be the case for a test deployment, where the true Translator bean cannot be used.

  1. Define the alternative.

    @Alternative
    @Translating
    public class MockTranslatingWelcome extends Welcome {
      public String buildPhrase(string city) {
        return "Bienvenue à " + city + "!");
      }
    }
  2. Activate the substitute implementation by adding the fully-qualified class name to your META-INF/beans.xml or WEB-INF/beans.xml file.

    <beans>
      <alternatives>
        <class>com.acme.MockTranslatingWelcome</class>
      </alternatives>
    </beans>

The alternative implementation is now used instead of the original one.

13.2.9. Stereotypes

In many systems, use of architectural patterns produces a set of recurring bean roles. A stereotype allows you to identify such a role and declare some common metadata for beans with that role in a central place.

A stereotype encapsulates any combination of:

  • Default scope
  • A set of interceptor bindings

A stereotype can also specify either:

  • All beans where the stereotypes are defaulted bean EL names
  • All beans where the stereotypes are alternatives

A bean may declare zero, one, or multiple stereotypes. A stereotype is an @Stereotype annotation that packages several other annotations. Stereotype annotations may be applied to a bean class, producer method, or field.

A class that inherits a scope from a stereotype may override that stereotype and specify a scope directly on the bean.

In addition, if a stereotype has a @Named annotation, any bean it is placed on has a default bean name. The bean may override this name if the @Named annotation is specified directly on the bean. For more information about named beans, see Named Beans.

13.2.9.1. Use Stereotypes

Without stereotypes, annotations can become cluttered. This task shows you how to use stereotypes to reduce the clutter and streamline your code.

Example: Annotation clutter

@Secure
@Transactional
@RequestScoped
@Named
public class AccountManager {
  public boolean transfer(Account a, Account b) {
    ...
  }
}

Define and Use Stereotypes
  1. Define the stereotype.

    @Secure
    @Transactional
    @RequestScoped
    @Named
    @Stereotype
    @Retention(RUNTIME)
    @Target(TYPE)
    public @interface BusinessComponent {
     ...
    }
  2. Use the stereotype.

    @BusinessComponent
    public class AccountManager {
      public boolean transfer(Account a, Account b) {
        ...
      }
    }

13.2.10. Observer Methods

Observer methods receive notifications when events occur.

CDI also provides transactional observer methods, which receive event notifications during the before completion or after completion phase of the transaction in which the event was fired.

13.2.10.1. Transactional Observers

Transactional observers receive the event notifications before or after the completion phase of the transaction in which the event was raised. Transactional observers are important in a stateful object model because state is often held for longer than a single atomic transaction.

There are five kinds of transactional observers:

  • IN_PROGRESS: By default, observers are invoked immediately.
  • AFTER_SUCCESS: Observers are invoked after the completion phase of the transaction, but only if the transaction completes successfully.
  • AFTER_FAILURE: Observers are invoked after the completion phase of the transaction, but only if the transaction fails to complete successfully.
  • AFTER_COMPLETION: Observers are invoked after the completion phase of the transaction.
  • BEFORE_COMPLETION: Observers are invoked before the completion phase of the transaction.

The following observer method refreshes a query result set cached in the application context, but only when transactions that update the Category tree are successful:

public void refreshCategoryTree(@Observes(during = AFTER_SUCCESS) CategoryUpdateEvent event) { ... }

Assume we have cached a JPA query result set in the application scope:

import javax.ejb.Singleton;
import javax.enterprise.inject.Produces;

@ApplicationScoped @Singleton

public class Catalog {
   @PersistenceContext EntityManager em;
   List<Product> products;
   @Produces @Catalog
   List<Product> getCatalog() {
      if (products==null) {
         products = em.createQuery("select p from Product p where p.deleted = false")
            .getResultList();
      }
      return products;
   }
}

Occasionally a Product is created or deleted. When this occurs, we need to refresh the Product catalog. But we have to wait for the transaction to complete successfully before performing this refresh.

The bean that creates and deletes Products triggers events, for example:

import javax.enterprise.event.Event;

@Stateless

public class ProductManager {
   @PersistenceContext EntityManager em;
   @Inject @Any Event<Product> productEvent;
   public void delete(Product product) {
      em.delete(product);
      productEvent.select(new AnnotationLiteral<Deleted>(){}).fire(product);
   }

   public void persist(Product product) {
      em.persist(product);
      productEvent.select(new AnnotationLiteral<Created>(){}).fire(product);
   }
   ...
}

The Catalog can now observe the events after successful completion of the transaction:

import javax.ejb.Singleton;

@ApplicationScoped @Singleton
public class Catalog {
   ...
   void addProduct(@Observes(during = AFTER_SUCCESS) @Created Product product) {
      products.add(product);
   }

   void removeProduct(@Observes(during = AFTER_SUCCESS) @Deleted Product product) {
      products.remove(product);
   }

}

13.2.10.2. Fire and Observe Events

Example: Fire an event

The following code shows an event being injected and used in a method.

public class AccountManager {
  @Inject Event<Withdrawal> event;

  public boolean transfer(Account a, Account b) {
    ...
    event.fire(new Withdrawal(a));
  }
}

Example: Fire an event with a qualifier

You can annotate your event injection with a qualifier, to make it more specific. For more information about qualifiers, see Qualifiers.

public class AccountManager {
  @Inject @Suspicious Event <Withdrawal> event;

  public boolean transfer(Account a, Account b) {
    ...
    event.fire(new Withdrawal(a));
  }
}

Example: Observe an event

To observe an event, use the @Observes annotation.

public class AccountObserver {
  void checkTran(@Observes Withdrawal w) {
    ...
  }
}

You can use qualifiers to observe only specific types of events.

public class AccountObserver {
  void checkTran(@Observes @Suspicious Withdrawal w) {
    ...
  }
}

13.2.11. Interceptors

Interceptors allow you to add functionality to the business methods of a bean without modifying the bean’s method directly. The interceptor is executed before any of the business methods of the bean. Interceptors are defined as part of the Enterprise JavaBeans specification, which can be found at https://jcp.org/aboutJava/communityprocess/final/jsr318/index.html.

CDI enhances this functionality by allowing you to use annotations to bind interceptors to beans.

Interception points

  • Business method interception: A business method interceptor applies to invocations of methods of the bean by clients of the bean.
  • Lifecycle callback interception: A lifecycle callback interceptor applies to invocations of lifecycle callbacks by the container.
  • Timeout method interception: A timeout method interceptor applies to invocations of the EJB timeout methods by the container.

13.2.11.1. Use Interceptors with CDI

CDI can simplify your interceptor code and make it easier to apply to your business code.

Without CDI, interceptors have two problems:

  • The bean must specify the interceptor implementation directly.
  • Every bean in the application must specify the full set of interceptors in the correct order. This makes adding or removing interceptors on an application-wide basis time-consuming and error-prone.

Example: Interceptors without CDI

@Interceptors({
  SecurityInterceptor.class,
  TransactionInterceptor.class,
  LoggingInterceptor.class
})
@Stateful public class BusinessComponent {
  ...
}

Use interceptors with CDI
  1. Define the interceptor binding type:

    @InterceptorBinding
    @Retention(RUNTIME)
    @Target({TYPE, METHOD})
    public @interface Secure {}
  2. Mark the interceptor implementation:

    @Secure
    @Interceptor
    public class SecurityInterceptor {
      @AroundInvoke
      public Object aroundInvoke(InvocationContext ctx) throws Exception {
        // enforce security ...
        return ctx.proceed();
        }
    }
  3. Use the interceptor in your business code:

    @Secure
    public class AccountManager {
      public boolean transfer(Account a, Account b) {
        ...
      }
    }
  4. Enable the interceptor in your deployment, by adding it to META-INF/beans.xml or WEB-INF/beans.xml:

    <beans>
      <interceptors>
        <class>com.acme.SecurityInterceptor</class>
        <class>com.acme.TransactionInterceptor</class>
      </interceptors>
    </beans>

The interceptors are applied in the order listed.

13.2.12. Decorators

A decorator intercepts invocations from a specific Java interface, and is aware of all the semantics attached to that interface. Decorators are useful for modeling some kinds of business concerns, but do not have the generality of interceptors. A decorator is a bean, or even an abstract class, that implements the type it decorates, and is annotated with @Decorator. To invoke a decorator in a CDI application, it must be specified in the beans.xml file.

A decorator must have exactly one @Delegate injection point to obtain a reference to the decorated object.

Example: Example Decorator

@Decorator
public abstract class LargeTransactionDecorator implements Account {

   @Inject @Delegate @Any Account account;
   @PersistenceContext EntityManager em;

   public void withdraw(BigDecimal amount) {
      ...
   }

   public void deposit(BigDecimal amount);
      ...
   }
}

13.2.13. Portable Extensions

CDI is intended to be a foundation for frameworks, extensions, and for integration with other technologies. Therefore, CDI exposes a set of SPIs for the use of developers of portable extensions to CDI.

Extensions can provide the following types of functionality:

  • Integration with Business Process Management engines
  • Integration with third-party frameworks, such as Spring, Seam, GWT, or Wicket
  • New technology based upon the CDI programming model

According to the JSR-346 specification, a portable extension can integrate with the container in the following ways:

  • Providing its own beans, interceptors, and decorators to the container
  • Injecting dependencies into its own objects using the dependency injection service
  • Providing a context implementation for a custom scope
  • Augmenting or overriding the annotation-based metadata with metadata from another source

13.2.14. Bean Proxies

Clients of an injected bean do not usually hold a direct reference to a bean instance. Unless the bean is a dependent object (scope @Dependent), the container must redirect all injected references to the bean using a proxy object.

A bean proxy, which can be referred to as client proxy, is responsible for ensuring the bean instance that receives a method invocation is the instance associated with the current context. The client proxy also allows beans bound to contexts, such as the session context, to be serialized to disk without recursively serializing other injected beans.

Due to Java limitations, some Java types cannot be proxied by the container. If an injection point declared with one of these types resolves to a bean with a scope other than @Dependent, the container aborts the deployment.

Certain Java types cannot be proxied by the container. These include:

  • Classes that do not have a non-private constructor with no parameters
  • Classes that are declared final or have a final method
  • Arrays and primitive types

13.2.15. Use a Proxy in an Injection

A proxy is used for injection when the lifecycles of the beans are different from each other. The proxy is a subclass of the bean that is created at run-time, and overrides all the non-private methods of the bean class. The proxy forwards the invocation onto the actual bean instance.

In this example, the PaymentProcessor instance is not injected directly into Shop. Instead, a proxy is injected, and when the processPayment() method is called, the proxy looks up the current PaymentProcessor bean instance and calls the processPayment() method on it.

Example: Proxy Injection

@ConversationScoped
class PaymentProcessor
{
  public void processPayment(int amount)
  {
    System.out.println("I'm taking $" + amount);
  }
}

@ApplicationScoped
public class Shop
{

  @Inject
  PaymentProcessor paymentProcessor;

  public void buyStuff()
  {
    paymentProcessor.processPayment(100);
  }
}