Troubleshoot contexts and dependency injection
Troubleshoot errors related to Contexts and Dependency Injection (CDI) for the Java EE applications.
When we use a CDI implementation, we might experience errors during application deployment or when CDI interacts with other Java EE components. We might also experience problems with producers, interceptors, and decorators or diagnostic trace. Use this task to fix these errors that might occur.
Tasks
- Troubleshoot application deployment problems. At application deployment time, the container must validate each injection point in the application and is satisfied by only one source of that dependency.
Hot deployment is not supported in CDI applications. To make the update available, we must restart the application.
- Resolve an ambiguous dependency.
An ambiguous dependency, or javax.enterprise.inject.AmbiguousResolutionException exception, occurs when the container resolves an injection points type and qualifiers to more than one managed bean, producer method, or producer field.
The exception reveals the injection point that was being processed, and the candidate beans that remained at the end of the type-safe resolution process. Anything other than a single bean is an application error:
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type OtherBean with qualifiers @Default at injection point [BackedAnnotatedField] @Inject private basic.injection.SimpleBean.bean at basic.injection.SimpleBean.bean(SimpleBean.java:0) Possible dependencies: - Managed Bean [class basic.injection.OtherBean] with qualifiers [@Any @Default], - Producer Method [OtherBean] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces basic.injection.OtherBeanProducer.produceOtherBean()]To resolve the error complete one of the following actions:
- Disambiguate the injection point by adding a qualifier to the injection point and if necessary, one source of the dependency.
- If necessary, annotate one of the sources of contextual instances with @Alternative or @Specializes, if some of the dependencies should not be considered for injection.
- Resolve an undesirable dependency.
An undesirable dependency, or javax.enterprise.inject.UnsatisfiedResolutionException, occurs when no source corresponds with objects that match an injection point in the application. The API type of the field, along with the optional set of qualifier annotations, dictates the set of beans that are valid to satisfy the dependency. Causes of undesirable dependency are as follows:
- No managed bean is assignable to the type on the injection point.
- No producer method of any managed bean whose return type is assignable to the injection point.
- No producer field in any managed bean whose type is assignable to the injection point.
- One of the previous scenarios are valid, but the Qualifier annotations on the injection point are not present on the bean or producer.
- The CDI container does not scan shared libraries for CDI managed beans.
Resolve the error by making a dependency with the API type and qualifiers available by introducing a new bean, removing qualifiers, or adding producers fields or methods. Section 5.2 of the Contexts and Dependency Injection for Java specification describes the type-safe resolution in detail.
org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type OtherBean with qualifiers @British at injection point [BackedAnnotatedField] @Inject @British private basic.injection.SimpleBean.bean at basic.injection.SimpleBean.bean(SimpleBean.java:0) WELD-001475: The following beans match by type, but none have matching qualifiers: - Managed Bean [class basic.injection.OtherBean] with qualifiers [@Any @Default], - Producer Method [OtherBean] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces basic.injection.OtherBeanProducer.produceOtherBean()]- Resolve passivating scope dependencies.
Passivation is the act of moving an idle object that is held in memory auxiliary storage. A passivating scope, such as the built-in scopes, @SessionScoped, and @ConversationScoped, requires any bean that uses the scope be passivation-capable. A bean is passivation-capable if it is either a stateful session bean or any other managed bean that is both serializable and has no non-serializable interceptors and decorators. Causes of passivating scope dependencies include the following:
- Change the scope of an existing bean to a passivating scope, such as @SessionScoped or @ConversationScoped.
- Add non-serializable decorators or interceptors to an existing passivation capable bean.
Resolve the error as follows:
- Ensure that the bean in question is serializable.
- Ensure all interceptors and decorators of the bean implement serializable.
- Change the scope of the managed bean to a non-passivating scope.
- Troubleshoot errors that result from CDI interacting with other Java EE components.
The @Inject annotation provides an additional type of Java EE dependency injection. Its relation to injection defined in Java EE 5 is as follows:
- Injection that use annotations other than the @Inject annotation behave as in previous releases, and only dependencies injected using the @Inject annotation are contextual instances as defined by Contexts and Dependency Injection for Java (JSR299).
- Use producer fields and producer methods to provide limited CDI features (such as type-safe injection) of Java EE dependencies obtained using the @Resource, @PersistenceContext, @PersistenceUnit, and @WebServiceRef annotations.
If we cannot obtain a value for an Expression Language (EL) reference to a managed bean for JSP and JavaServer Faces (JSF) components, consider the following approaches:
- Ensure that the bean class is annotated using the @Named annotation or is annotated with a stereotype that defines the @Named annotation.
- Ensure that the EL expression matches the class name of the bean class after you convert the first character to lowercase. When we use the @Named annotation qualifier with a value member (for example, @Named("myName")), this specifies the bean name (a special case qualifier) but does not change the EL name of that bean.
For EJB components:
- We can inject session beans with the @Inject and @EJB annotations. When we inject stateful session beans with the @Inject annotation, the session beans can take advantage of type-safe injection using qualifiers, and can have their lifecycle by their CDI scope.
- Session beans are eligible for interception and decoration even when they are not obtained with the @Inject annotation, unlike other managed beans.
For web service components:
- To develop a JAX-WS client from a WSDL file, follow the steps that are outlined in the topic, Developing a JAX-WS client from a WSDL file.
Tip: Use the wsimport tool to generate portable Java artifacts, including a service class.
- To inject the generated service class into a CDI-managed bean using the @WebServiceRef annotation, we must invoke the wsimport tool using the -wsdllocation argument. As a result, the generated service class is portable to other systems because the service class references the WSDL file using a relative URI, instead of an absolute path.
- Troubleshoot producer errors.
- Looping in producer methods
When we use a producer method, each parameter is treated as an injection point in which the container provides the dependency. Therefore, the source of contextual objects that fulfill those parameter injection points must not be the same class containing the producer method.
- Duplicate producer methods (two @Produces annotations with same qualifiers in the same class).
If an application has multiple producer fields, these fields cannot have the same API type and an identical set of qualifiers. If both the API type and the qualifiers are identical, it is ambiguous which producer is used to satisfy an injection point.
Producer fields and methods on a session bean
According to the CDI specification, if the bean is a session bean, the producer method must be either a business method of the EJB or a static method of the bean class. Similarly, a session bean's producer field must be a static field of the bean class.
The following error message displays if a producer field on a session bean is not declared as static:
java.lang.RuntimeException: com.ibm.ws.cdi.CDIRuntimeException: com.ibm.ws.cdi.CDIException: org.jboss.weld.exceptions.DefinitionException: WELD-000096: Producer fields on session beans must be static.
- Troubleshoot interceptor and decorator errors.
- Enable interceptor, decorator enablement interceptors, and decorators in the beans.xml file or through @Priority. All except EJB session beans apply only to contextual instances of beans. Contextual instances are instances that are obtained using the @Inject annotation or by calling methods on the BeanManager interface.
- Interceptors and decorators in multiple bean deployment archives (BDA). If the interceptors or decorators are enabled through the beans.xml file, these interceptors or decorators are enabled for that archive only. If the interceptors or decorators are enabled through @Priority, the interceptors or decorators are enabled for the whole application.
- Use diagnostic trace to help determine why an error occurred.
- Obtain a trace for CDI by specifying JCDI=all:com.ibm.ws.cdi*=all:org.jboss.weld*=all.
- Obtain an additional trace for interacting with Java EE injection and the EJB container by specifying EJBContainer=all:MetaData=all:Injection=all.
- Obtain an additional trace for interacting with web-related scopes and lifecycles by specifying all:com.ibm.ws.wswebcontainer*=all.
- Avoid heavyweight operations in default constructors of managed beans.
Each injection point for a given managed bean receives a new client proxy that calls the default constructor of the underlying bean class, in addition to the actual bean instance that might be created when using the proxy. Additionally, because dependency injections occur after the constructor completes, constructors cannot use injected dependencies. See the @PostConstruct annotation lifecycle callback for a place to put post-injection logic that runs in the underlying instance only.
Related:
Contexts and Dependency Injection (CDI) Developing a JAX-WS client from a WSDL file JSR 299: Contexts and Dependency Injection for the Java EE platform