Preface
Evaluation license
Specification: JSR 365: Contexts and Dependency Injection for Java 2.0 Version: 2.0 EDR1 Status: Early Draft Specification Lead: Red Hat, Inc. Release: June 25, 2015 Copyright 2015 Red Hat, Inc. 100 East Davie Street, Raleigh, NC 27601, U.S.A. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Foreword
Contexts and Dependency Injection 2.0 (JSR-365) is an update to Contexts and Dependency Injection 1.2 (JSR-346).
Starting with version 2.0 CDI targets Java SE and Java EE platforms. CDI in java SE and CDI in a Java EE container share the features defined in core CDI.
Organisation of this document
This document is organized in 4 parts:
-
An introduction (this part), which is not part of the specification but introduce CDI concepts and give examples.
-
The core CDI specification: Part I - Core CDI.
-
Specific CDI features for Java SE: Part II - CDI in Java SE.
-
Specific CDI features for Java EE: Part III - CDI in Java EE.
Major changes
This Early draft of CDI 2.0 includes important changes for the platform.
-
The spec was split in 3 parts as desibed in Organisation of this document to add the support for Java SE.
-
API to boot CDI in Java SE, described in Bootstrapping a CDI container in Java SE
-
Observer ordering, described in Observer ordering
-
Asynchronous event, descibed in Firing events asynchronously
The full changelog can be found here.
1. Architecture
This specification defines a powerful set of complementary services that help improve the structure of application code.
-
A well-defined lifecycle for stateful objects bound to lifecycle contexts, where the set of contexts is extensible
-
A sophisticated, typesafe dependency injection mechanism, including the ability to select dependencies at either development or deployment time, without verbose configuration
-
Support for Java EE modularity and the Java EE component architecture - the modular structure of a Java EE application is taken into account when resolving dependencies between Java EE components
-
Integration with the Unified Expression Language (EL), allowing any contextual object to be used directly within a JSF or JSP page
-
The ability to decorate injected objects
-
The ability to associate interceptors to objects via typesafe interceptor bindings
-
An event notification model
-
A web conversation context in addition to the three standard web contexts defined by the Java Servlets specification
-
An SPI allowing portable extensions to integrate cleanly with the container
The services defined by this specification allow objects to be bound to lifecycle contexts, to be injected, to be associated with interceptors and decorators, and to interact in a loosely coupled fashion by firing and observing events. Various kinds of objects are injectable, including EJB 3 session beans, managed beans and Java EE resources. We refer to these objects in general terms as beans and to instances of beans that belong to contexts as contextual instances. Contextual instances may be injected into other objects by the dependency injection service.
To take advantage of these facilities, the developer provides additional bean-level metadata in the form of Java annotations and application-level metadata in the form of an XML descriptor.
The use of these services significantly simplifies the task of creating Java EE applications by integrating the Java EE web tier with Java EE enterprise services. In particular, EJB components may be used as JSF managed beans, thus integrating the programming models of EJB and JSF.
It’s even possible to integrate with third-party frameworks. A portable extension may provide objects to be injected or obtain contextual instances using the dependency injection service. The framework may even raise and observe events using the event notification service.
An application that takes advantage of these services may be designed to execute in either the Java EE environment or the Java SE environment. If the application uses Java EE services such as transaction management and persistence in the Java SE environment, the services are usually restricted to, at most, the subset defined for embedded usage by the EJB specification.
1.1. Contracts
This specification defines the responsibilities of:
-
the application developer who uses these services, and
-
the vendor who implements the functionality defined by this specification and provides a runtime environment in which the application executes.
This runtime environment is called the container. For example, the container might be a Java EE container or an embeddable EJB container.
Concepts, Programming model, Inheritance and specialization, Interceptor bindings, Decorator beans and Observer methods define the programming model for Java EE components that take advantage of the services defined by this specification, the responsibilities of the component developer, and the annotations used by the component developer to specify metadata.
Dependency injection and lookup, Scopes and contexts, Lifecycle of contextual instances, Decorators, Events and Interceptor resolution define the semantics and behavior of the services, the responsibilities of the container implementation and the APIs used by the application to interact directly with the container.
Packaging and deployment defines how Java EE applications that use the services defined by this specification must be packaged into bean archives, and the responsibilities of the container implementation at application initialization time.
Portable extensions, The Contextual
interface and The Context
interface define an SPI that allows portable extensions to integrate with the container.
1.2. Relationship to other specifications
An application developer creates container-managed components such as JavaBeans, EJBs or servlets and then provides additional metadata that declares additional behavior defined by this specification. These components may take advantage of the services defined by this specification, together with the enterprise and presentational aspects defined by other Java EE platform technologies.
In addition, this specification defines an SPI that allows alternative, non-platform technologies to integrate with the container and the Java EE environment, for example, alternative web presentation technologies.
1.2.1. Relationship to the Java EE platform specification
In the Java EE environment, all component classes supporting injection, as defined by the Java EE platform specification, may inject beans via the dependency injection service.
The Java EE platform specification defines a facility for injecting resources that exist in the Java EE component environment. Resources are identified by string-based names. This specification bolsters that functionality, adding the ability to inject an open-ended set of object types, including, but not limited to, component environment resources, based upon typesafe qualifiers.
1.2.2. Relationship to EJB
EJB defines a programming model for application components that access transactional resources in a multi-user environment. EJB allows concerns such as role-based security, transaction demarcation, concurrency and scalability to be specified declaratively using annotations and XML deployment descriptors and enforced by the EJB container at runtime.
EJB components may be stateful, but are not by nature contextual. References to stateful component instances must be explicitly passed between clients and stateful instances must be explicitly destroyed by the application.
This specification enhances the EJB component model with contextual lifecycle management.
Any session bean instance obtained via the dependency injection service is a contextual instance. It is bound to a lifecycle context and is available to other objects that execute in that context. The container automatically creates the instance when it is needed by a client. When the context ends, the container automatically destroys the instance.
Message-driven and entity beans are by nature non-contextual objects and may not be injected into other objects.
The container performs dependency injection on all session and message-driven bean instances, even those which are not contextual instances.
1.2.3. Relationship to managed beans
The Managed Beans specification defines the basic programming model for application components managed by the Java EE container.
As defined by this specification, most Java classes, including all JavaBeans, are managed beans.
This specification defines contextual lifecycle management and dependency injection as generic services applicable to all managed beans.
Any managed bean instance obtained via the dependency injection service is a contextual instance. It is bound to a lifecycle context and is available to other objects that execute in that context. The container automatically creates the instance when it is needed by a client. When the context ends, the container automatically destroys the instance.
The container performs dependency injection on all managed bean instances, even those which are not contextual instances.
1.2.4. Relationship to Dependency Injection for Java
The Dependency Injection for Java specification defines a set of annotations for the declaring injected fields, methods and constructors of a bean. The dependency injection service makes use of these annotations.
1.2.5. Relationship to Java Interceptors
The Java Interceptors specification defines the basic programming model and semantics for interceptors. This specification enhances that model by providing the ability to associate interceptors with beans using typesafe interceptor bindings.
1.2.6. Relationship to JSF
JavaServer Faces is a web-tier presentation framework that provides a component model for graphical user interface components and an event-driven interaction model that binds user interface components to objects accessible via Unified EL.
This specification allows any bean to be assigned a name. Thus, a JSF application may take advantage of the sophisticated context and dependency injection model defined by this specification.
1.2.7. Relationship to Bean Validation
Bean Validation provides a unified way of declaring and defining constraints on an object model, defines a runtime engine to validate objects and provides method validation.
The Bean Validation specification defines beans for Bean Validation managed objects including Validator
and ValidatorFactory
. A number of Bean Validation managed instances, including ConstraintValidator
s can take advantage of dependency injection. Bean Validation also provides support for method parameter validation on any bean.
1.3. Introductory examples
The following examples demonstrate the use of lifecycle contexts and dependency injection.
1.3.1. JSF example
The following JSF page defines a login prompt for a web application:
<f:view>
<h:form>
<h:panelGrid columns="2" rendered="#{!login.loggedIn}">
<h:outputLabel for="username">Username:</h:outputLabel>
<h:inputText id="username" value="#{credentials.username}"/>
<h:outputLabel for="password">Password:</h:outputLabel>
<h:inputText id="password" value="#{credentials.password}"/>
</h:panelGrid>
<h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
<h:commandButton value="Logout" action="#{login.logout}" rendered="#{login.loggedIn}"/>
</h:form>
</f:view>
The Unified EL expressions in this page refer to beans named credentials
and login
.
The Credentials
bean has a lifecycle that is bound to the JSF request:
@Model
public class Credentials {
private String username;
private String password;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
The @Model
annotation defined in Built-in stereotypes is a stereotype that identifies the Credentials
bean as a model object in an MVC architecture.
The Login
bean has a lifecycle that is bound to the HTTP session:
@SessionScoped @Model
public class Login implements Serializable {
@Inject Credentials credentials;
@Inject @Users EntityManager userDatabase;
private CriteriaQuery<User> query;
private Parameter<String> usernameParam;
private Parameter<String> passwordParam;
private User user;
@Inject
void initQuery(@Users EntityManagerFactory emf) {
CriteriaBuilder cb = emf.getCriteriaBuilder();
usernameParam = cb.parameter(String.class);
passwordParam = cb.parameter(String.class);
query = cb.createQuery(User.class);
Root<User> u = query.from(User.class);
query.select(u);
query.where( cb.equal(u.get(User_.username), usernameParam),
cb.equal(u.get(User_.password), passwordParam) );
}
public void login() {
List<User> results = userDatabase.createQuery(query)
.setParameter(usernameParam, credentials.getUsername())
.setParameter(passwordParam, credentials.getPassword())
.getResultList();
if ( !results.isEmpty() ) {
user = results.get(0);
}
}
public void logout() {
user = null;
}
public boolean isLoggedIn() {
return user!=null;
}
@Produces @LoggedIn User getCurrentUser() {
if (user==null) {
throw new NotLoggedInException();
}
else {
return user;
}
}
}
The @SessionScoped
annotation defined in Built-in scope types is a scope type that specifies the lifecycle of instances of Login
. Managed beans with this scope must be serializable.
The @Inject
annotation defined by the Dependency Injection for Java specification identifies an injected field which is initialized by the container when the bean is instantiated, or an initializer method which is called by the container after the bean is instantiated, with injected parameters.
The @Users
annotation is a qualifier type defined by the application:
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Users {}
The @LoggedIn
annotation is another qualifier type defined by the application:
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface LoggedIn {}
The @Produces
annotation defined in Declaring a producer method identifies the method getCurrentUser()
as a producer method, which will be called whenever another bean in the system needs the currently logged-in user, for example, whenever the user
attribute of the DocumentEditor
class is injected by the container:
@Model
public class DocumentEditor {
@Inject Document document;
@Inject @LoggedIn User currentUser;
@Inject @Documents EntityManager docDatabase;
public void save() {
document.setCreatedBy(currentUser);
em.persist(document);
}
}
The @Documents
annotation is another application-defined qualifier type. The use of distinct qualifier types enables the container to distinguish which JPA persistence unit is required.
When the login form is submitted, JSF assigns the entered username and password to an instance of the Credentials
bean that is automatically instantiated by the container. Next, JSF calls the login()
method of an instance of Login
that is automatically instantiated by the container. This instance continues to exist for and be available to other requests in the same HTTP session, and provides the User
object representing the current user to any other bean that requires it (for example, DocumentEditor
). If the producer method is called before the login()
method initializes the user object, it throws a NotLoggedInException
.
1.3.2. EJB example
Alternatively, we could write our Login
bean to take advantage of the functionality defined by EJB:
@Stateful @SessionScoped @Model
public class Login {
@Inject Credentials credentials;
@Inject @Users EntityManager userDatabase;
...
private User user;
@Inject
void initQuery(@Users EntityManagerFactory emf) {
...
}
@TransactionAttribute(REQUIRES_NEW)
@RolesAllowed("guest")
public void login() {
...
}
public void logout() {
user = null;
}
public boolean isLoggedIn() {
return user!=null;
}
@RolesAllowed("user")
@Produces @LoggedIn User getCurrentUser() {
...
}
}
The EJB @Stateful
annotation specifies that this bean is an EJB stateful session bean. The EJB @TransactionAttribute
and @RolesAllowed
annotations declare the EJB transaction demarcation and security attributes of the annotated methods.
1.3.3. Java EE component environment example
In the previous examples, we injected container-managed persistence contexts using qualifier types. We need to tell the container what persistence context is being referred to by which qualifier type. We can declare references to persistence contexts and other resources in the Java EE component environment in Java code.
public class Databases {
@Produces @PersistenceContext(unitName="UserData")
@Users EntityManager userDatabaseEntityManager;
@Produces @PersistenceUnit(unitName="UserData")
@Users EntityManagerFactory userDatabaseEntityManagerFactory;
@Produces @PersistenceContext(unitName="DocumentData")
@Documents EntityManager docDatabaseEntityManager;
}
The JPA @PersistenceContext
and @PersistenceUnit
annotations identify the JPA persistence unit.
1.3.4. Event example
Beans may raise events. For example, our Login
class could raise events when a user logs in or out.
@SessionScoped @Model
public class Login implements Serializable {
@Inject Credentials credentials;
@Inject @Users EntityManager userDatabase;
@Inject @LoggedIn Event<User> userLoggedInEvent;
@Inject @LoggedOut Event<User> userLoggedOutEvent;
...
private User user;
@Inject
void initQuery(@Users EntityManagerFactory emf) {
...
}
public void login() {
List<User> results = ... ;
if ( !results.isEmpty() ) {
user = results.get(0);
userLoggedInEvent.fire(user);
}
}
public void logout() {
userLoggedOutEvent.fire(user);
user = null;
}
public boolean isLoggedIn() {
return user!=null;
}
@Produces @LoggedIn User getCurrentUser() {
...
}
}
The method fire()
of the built-in bean of type Event
defined in The Event
interface allows the application to fire events. Events consist of an event object - in this case the User
- and event qualifiers. Event qualifier - such as @LoggedIn
and @LoggedOut
- allow event consumers to specify which events of a certain type they are interested in.
Other beans may observe these events and use them to synchronize their internal state, with no coupling to the bean producing the events:
@SessionScoped
public class Permissions implements Serializable {
@Produces
private Set<Permission> permissions = new HashSet<Permission>();
@Inject @Users EntityManager userDatabase;
Parameter<String> usernameParam;
CriteriaQuery<Permission> query;
@Inject
void initQuery(@Users EntityManagerFactory emf) {
CriteriaBuilder cb = emf.getCriteriaBuilder();
usernameParam = cb.parameter(String.class);
query = cb.createQuery(Permission.class);
Root<Permission> p = query.from(Permission.class);
query.select(p);
query.where( cb.equal(p.get(Permission_.user).get(User_.username),
usernameParam) );
}
void onLogin(@Observes @LoggedIn User user) {
permissions = new HashSet<Permission>( userDatabase.createQuery(query)
.setParameter(usernameParam, user.getUsername())
.getResultList() );
}
void onLogout(@Observes @LoggedOut User user {
permissions.clear();
}
}
The @Produces
annotation applied to a field identifies the field as a producer field, as defined in Producer fields, a kind of shortcut version of a producer method. This producer field allows the permissions of the current user to be injected to an injection point of type Set<Permission>
.
The @Observes
annotation defined in Declaring an observer method identifies the method with the annotated parameter as an observer method that is called by the container whenever an event matching the type and qualifiers of the annotated parameter is fired.
1.3.5. Injection point metadata example
It is possible to implement generic beans that introspect the injection point to which they belong. This makes it possible to implement injection for Logger
s, for example.
class Loggers {
@Produces Logger getLogger(InjectionPoint injectionPoint) {
return Logger.getLogger( injectionPoint.getMember().getDeclaringClass().getSimpleName() );
}
}
The InjectionPoint
interface defined in Injection point metadata, provides metadata about the injection point to the object being injected into it.
Then this class will have a Logger
named "Permissions"
injected:
@SessionScoped
public class Permissions implements Serializable {
@Inject Logger log;
...
}
1.3.6. Interceptor example
Interceptors allow common, cross-cutting concerns to be applied to beans via custom annotations. Interceptor types may be individually enabled or disabled at deployment time.
The AuthorizationInterceptor
class defines a custom authorization check:
@Secure @Interceptor
public class AuthorizationInterceptor {
@Inject @LoggedIn User user;
@Inject Logger log;
@AroundInvoke
public Object authorize(InvocationContext ic) throws Exception {
try {
if ( !user.isBanned() ) {
log.fine("Authorized");
return ic.proceed();
}
else {
log.fine("Not authorized");
throw new NotAuthorizedException();
}
}
catch (NotAuthenticatedException nae) {
log.fine("Not authenticated");
throw nae;
}
}
}
The @Interceptor
annotation, defined in Declaring the interceptor bindings of an interceptor, identifies the AuthorizationInterceptor
class as an interceptor. The @Secure
annotation is a custom interceptor binding type, as defined in Interceptor binding types.
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface Secure {}
The @Secure
annotation is used to apply the interceptor to a bean:
@Model
public class DocumentEditor {
@Inject Document document;
@Inject @LoggedIn User user;
@Inject @Documents EntityManager em;
@Secure
public void save() {
document.setCreatedBy(currentUser);
em.persist(document);
}
}
When the save()
method is invoked, the authorize()
method of the interceptor will be called. The invocation will proceed to the DocumentEditor
class only if the authorization check is successful.
1.3.7. Decorator example
Decorators are similar to interceptors, but apply only to beans of a particular Java interface. Like interceptors, decorators may be easily enabled or disabled at deployment time. Unlike interceptors, decorators are aware of the semantics of the intercepted method.
For example, the DataAccess
interface might be implemented by many beans:
public interface DataAccess<T, V> {
public V getId(T object);
public T load(V id);
public void save(T object);
public void delete(T object);
public Class<T> getDataType();
}
The DataAccessAuthorizationDecorator
class defines the authorization checks:
@Decorator
public abstract class DataAccessAuthorizationDecorator<T, V> implements DataAccess<T, V> {
@Inject @Delegate DataAccess<T, V> delegate;
@Inject Logger log;
@Inject Set<Permission> permissions;
public void save(T object) {
authorize(SecureAction.SAVE, object);
delegate.save(object);
}
public void delete(T object) {
authorize(SecureAction.DELETE, object);
delegate.delete(object);
}
private void authorize(SecureAction action, T object) {
V id = delegate.getId(object);
Class<T> type = delegate.getDataType();
if ( permissions.contains( new Permission(action, type, id) ) ) {
log.fine("Authorized for " + action);
}
else {
log.fine("Not authorized for " + action);
throw new NotAuthorizedException(action);
}
}
}
The @Decorator
annotation defined in Declaring a decorator identifies the DataAccessAuthorizationDecorator
class as a decorator. The @Delegate
annotation defined in Decorator delegate injection points identifies the delegate, which the decorator uses to delegate method calls to the container. The decorator applies to any bean that implements DataAccess
.
The decorator intercepts invocations just like an interceptor. However, unlike an interceptor, the decorator contains functionality that is specific to the semantics of the method being called.
Decorators may be declared abstract, relieving the developer of the responsibility of implementing all methods of the decorated interface. If a decorator does not implement a method of a decorated interface, the decorator will simply not be called when that method is invoked upon the decorated bean.
Part I - Core CDI
2. Concepts
a) A bean comprises of a (nonempty) set of bean types.
- BeanDefinitionTest.testBeanTypesNonEmpty()
b) A bean comprises of a (nonempty) set of qualifiers.
- BeanDefinitionTest.testQualifiersNonEmpty()
c) A bean comprises of a scope.
- BeanDefinitionTest.testHasScopeType()
e) A bean comprises of an optional bean name.
- NameDefinitionTest.testNonDefaultNamed()
- NameDefinitionTest.testNamedNotDeclaredByBean()
f) A bean comprises of a set of interceptor bindings.
- InterceptorBindingTypeWithMemberTest.testInterceptorBindingTypeWithMember()
g) A bean comprises of a bean implementation.
- SimpleBeanLifecycleTest.testManagedBean()
h) A bean may or may not be an alternative.
A bean is a source of contextual objects which define application state and/or logic. These objects are called contextual instances of the bean. The container creates and destroys these instances and associates them with the appropriate context. Contextual instances of a bean may be injected into other objects (including other bean instances) that execute in the same context. A bean may bear metadata defining its lifecycle and interactions with other beans.
A bean comprises the following attributes:
-
A (nonempty) set of bean types
-
A (nonempty) set of qualifiers
-
A scope
-
Optionally, a bean name
-
A set of interceptor bindings
-
A bean implementation
Furthermore, a bean may or may not be an alternative.
A bean developer provides the bean implementation by writing business logic in Java code. The developer then defines the remaining attributes by explicitly annotating the bean class, or by allowing them to be defaulted by the container, as specified in Programming model.
The bean types and qualifiers of a bean determine where its instances will be injected by the container, as defined in Dependency injection and lookup.
The bean developer may also create interceptors and/or decorators or reuse existing interceptors and/or decorators. The interceptor bindings of a bean determine which interceptors will be applied at runtime. The bean types and qualifiers of a bean determine which decorators will be applied at runtime. Interceptors are defined by Java interceptors specification, and interceptor bindings are specified in Interceptor bindings. Decorators are defined in Decorators.
2.1. Functionality provided by the container to the bean
A bean is provided by the container with the following capabilities:
-
transparent creation and destruction and scoping to a particular context, specified in Scopes and contexts and Lifecycle of contextual instances,
-
scoped resolution by bean type and qualifier annotation type when injected into a Java-based client, as defined by Typesafe resolution,
-
lifecycle callbacks and automatic injection of other bean instances, specified in Programming model and Dependency injection and lookup,
-
method interception, callback interception, and decoration, as defined in Interceptor bindings and Decorators, and
-
event notification, as defined in Events.
2.2. Bean types
a) A bean may have multiple bean types.
- BeanDefinitionTest.testBeanTypes()
- BeanDefinitionTest.testGenericBeanTypes()
- BeanDefinitionTest.testRawBeanTypes()
l) All beans have the bean type java.lang.Object.
- ProducerMethodDefinitionTest.testApiTypeForClassReturn()
- BeanDefinitionTest.testBeanTypes()
- BeanDefinitionTest.testGenericBeanTypes()
- BeanDefinitionTest.testRawBeanTypes()
A bean type defines a client-visible type of the bean. A bean may have multiple bean types. For example, the following bean has four bean types:
public class BookShop
extends Business
implements Shop<Book> {
...
}
The bean types are BookShop
, Business
, Shop<Book>
and Object
.
The rules for determining the (unrestricted) set of bean types for a bean are defined in Bean types of a managed bean, Bean types of a producer method and Bean types of a producer field.
All beans have the bean type java.lang.Object
.
The bean types of a bean are used by the rules of typesafe resolution defined in Typesafe resolution.
2.2.1. Legal bean types
a) A bean type may be an interface.
- BeanDefinitionTest.testBeanTypes()
b) A bean type may be a concrete class.
- SimpleBeanLifecycleTest.testManagedBean()
c) A bean type may be an abstract class.
- BeanDefinitionTest.testAbstractApiType()
d) A bean type may be declared final.
- BeanDefinitionTest.testBeanTypes()
- BeanDefinitionTest.testFinalApiType()
e) A bean type may have final methods.
- BeanDefinitionTest.testBeanTypes()
f) A bean type may be a parameterized type with actual type parameters.
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityToRawType()
g) A bean type may be a parameterized type with type variables.
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityToRawType()
i) A bean type may be an array type. Two array types are considered identical only if the element type is identical.
- ProducerMethodDefinitionTest.testApiTypeForArrayTypeReturn()
- ProducerFieldDefinitionTest.testApiTypeForArrayTypeReturn()
- ResolutionByTypeTest.testResolveByTypeWithArray()
j) A bean type may be a primitive type. Primitive types are considered to be identical to their corresponding wrapper types in java.lang.
- ResolutionByTypeTest.testResolveByTypeWithPrimitives()
k) A bean type may be a raw type.
- SimpleBeanLifecycleTest.testManagedBean()
la) A type variable is not a legal bean type.
- TypeVariableReturnTypeTest.testTypeVariableNotAllowed()
lb) A parameterized type that contains a wildcard type parameter is not a legal bean type.
- ParametrizedTypeWithWildcard02Test.testParameterizedReturnTypeWithDoubleWildcard()
- ParameterizedTypeWithWildcardTest.testParameterizedReturnTypeWithWildcard()
An array type whose component type is not a legal bean type.
lc) An array type whose component type is a type variable is not a legal bean type.
- ProducerFieldArrayTypeVariableTest.testBeanTypes()
- ProducerMethodArrayTypeVariableTest.testBeanTypes()
ld) An array type whose component type is a parameterized type that contains a wildcard type parameter is not a legal bean type.
- ProducerMethodArrayWildcardTest.testBeanTypes()
- ProducerFieldArrayWildcardTest.testBeanTypes()
Almost any Java type may be a bean type of a bean:
-
A bean type may be an interface, a concrete class or an abstract class, and may be declared final or have final methods.
-
A bean type may be a parameterized type with actual type parameters and type variables.
-
A bean type may be an array type. Two array types are considered identical only if the element type is identical.
-
A bean type may be a primitive type. Primitive types are considered to be identical to their corresponding wrapper types in
java.lang
. -
A bean type may be a raw type.
However, some Java types are not legal bean types :
-
A type variable is not a legal bean type.
-
A parameterized type that contains a wildcard type parameter is not a legal bean type.
-
An array type whose component type is not a legal bean type.
Note that certain additional restrictions are specified in Unproxyable bean types for beans with a normal scope, as defined in Normal scopes and pseudo-scopes.
2.2.2. Restricting the bean types of a bean
The bean types of a bean may be restricted by annotating the bean class or producer method or field with the annotation @javax.enterprise.inject.Typed. When a @Typed annotation is explicitly specified, only the types whose classes are explicitly listed using the value member, together with java.lang.Object are bean types of the bean.
a) Check managed bean
- ResolutionByTypeTest.testBeanTypesOnManagedBean()
- RestrictedManagedBeanTest.testInvalidTypedValueOnManagedBean()
c) Check producer method
- ResolutionByTypeTest.testBeanTypesOnProducerMethod()
- RestrictedProducerFieldTest.testInvalidTypedValueOnProducerField()
d) Check producer field
- ResolutionByTypeTest.testBeanTypesOnProducerField()
- RestrictedProducerMethodTest.testInvalidTypedValueOnProducerField()
e) Check generic managed bean
- ResolutionByTypeTest.testGenericBeanTypesOnManagedBean()
g) Check generic producer method
- ResolutionByTypeTest.testGenericBeanTypesOnProducerMethod()
h) Check generic producer field
- ResolutionByTypeTest.testGenericBeanTypesOnProducerField()
If a bean class or producer method or field specifies a @Typed annotation, and the value member specifies a class which does not correspond to a type in the unrestricted set of bean types of a bean, the container automatically detects the problem and treats it as a definition error.
j) Check managed bean
- ResolutionByTypeTest.testBeanTypesOnManagedBean()
- RestrictedManagedBeanTest.testInvalidTypedValueOnManagedBean()
l) Check producer method
- ResolutionByTypeTest.testBeanTypesOnProducerMethod()
- RestrictedProducerFieldTest.testInvalidTypedValueOnProducerField()
m) Check producer field
- ResolutionByTypeTest.testBeanTypesOnProducerField()
- RestrictedProducerMethodTest.testInvalidTypedValueOnProducerField()
The bean types of a bean may be restricted by annotating the bean class or producer method or field with the annotation @javax.enterprise.inject.Typed
.
@Typed(Shop.class)
public class BookShop
extends Business
implements Shop<Book> {
...
}
When a @Typed
annotation is explicitly specified, only the types whose classes are explicitly listed using the value
member, together with java.lang.Object
, are bean types of the bean.
In the example, the bean has a two bean types: Shop<Book>
and Object
.
If a bean class or producer method or field specifies a @Typed
annotation, and the value
member specifies a class which does not correspond to a type in the unrestricted set of bean types of a bean, the container automatically detects the problem and treats it as a definition error.
2.2.3. Typecasting between bean types
a) A client of a bean may typecast its contextual reference to a bean to any bean type of the bean which is a Java interface. However, the client may not in general typecast its contextual reference to an arbitrary concrete bean type of the bean.
- BeanDefinitionTest.testBeanClientCanCastBeanInstanceToAnyBeanType()
A client of a bean may typecast its contextual reference to a bean to any bean type of the bean which is a Java interface. However, the client may not in general typecast its contextual reference to an arbitrary concrete bean type of the bean. For example, if our managed bean was injected to the following field:
@Inject Business biz;
Then the following typecast is legal:
Shop<Book> bookShop = (Shop<Book>) biz;
However, the following typecast is not legal and might result in an exception at runtime:
BookShop bookShop = (BookShop) biz;
2.3. Qualifiers
For a given bean type, there may be multiple beans which implement the type. For example, an application may have two implementations of the interface PaymentProcessor
:
class SynchronousPaymentProcessor
implements PaymentProcessor {
...
}
class AsynchronousPaymentProcessor
implements PaymentProcessor {
...
}
A client that needs a PaymentProcessor
that processes payments synchronously needs some way to distinguish between the two different implementations. One approach would be for the client to explicitly specify the class that implements the PaymentProcessor
interface. However, this approach creates a hard dependence between client and implementation - exactly what use of the interface was designed to avoid!
A qualifier type represents some client-visible semantic associated with a type that is satisfied by some implementations of the type (and not by others). For example, we could introduce qualifier types representing synchronicity and asynchronicity. In Java code, qualifier types are represented by annotations.
@Synchronous
class SynchronousPaymentProcessor
implements PaymentProcessor {
...
}
@Asynchronous
class AsynchronousPaymentProcessor
implements PaymentProcessor {
...
}
Finally, qualifier types are applied to injection points to distinguish which implementation is required by the client. For example, when the container encounters the following injected field, an instance of SynchronousPaymentProcessor
will be injected:
@Inject @Synchronous PaymentProcessor paymentProcessor;
But in this case, an instance of AsynchronousPaymentProcessor
will be injected:
@Inject @Asynchronous PaymentProcessor paymentProcessor;
The container inspects the qualifier annotations and type of the injected attribute to determine the bean instance to be injected, according to the rules of typesafe resolution defined in Typesafe resolution.
An injection point may even specify multiple qualifiers.
Qualifier types are also used as event selectors by event consumers, as defined in Events, and to bind decorators to beans, as specified in Decorators.
2.3.1. Built-in qualifier types
aa) Every bean has the built-in qualifier @Any, even if it does not explicitly declare this qualifier, except for the special @New qualified beans defined in Section 3.14, "@New qualified beans".
- ProducerMethodDefinitionTest.testDefaultBindingType()
- QualifierDefinitionTest.testDefaultQualifierDeclaredInJava()
- AnyInjectionTest.testAnyInjectionIfExactlyOneBeanForType()
ab) If a bean does not explicitly declare a qualifier other than @Named, the bean has exactly one additional qualifier, of type @Default. This is called the default qualifier.
- ProducerMethodDefinitionTest.testDefaultBindingType()
- ProducerFieldDefinitionTest.testDefaultBindingType()
- QualifierDefinitionTest.testDefaultQualifierDeclaredInJava()
b) The default qualifier is also assumed for any injection point that does not explicitly declare a qualifier.
- QualifierDefinitionTest.testDefaultQualifierForInjectionPoint()
Three standard qualifier types are defined in the package javax.enterprise.inject
. In addition, the built-in qualifier type @Named
is defined by the package javax.inject
.
Every bean has the built-in qualifier @Any
, even if it does not explicitly declare this qualifier, except for the special @New
qualified beans defined in @New
qualified beans.
If a bean does not explicitly declare a qualifier other than @Named
, the bean has exactly one additional qualifier, of type @Default
. This is called the default qualifier.
The following declarations are equivalent:
@Default
public class Order { ... }
public class Order { ... }
Both declarations result in a bean with two qualifiers: @Any
and @Default
.
The following declaration results in a bean with three qualifiers: @Any
, @Default
and @Named("ord")
.
@Named("ord")
public class Order { ... }
The default qualifier is also assumed for any injection point that does not explicitly declare a qualifier, as defined in The default qualifier at injection points. The following declarations, in which the use of the @Inject
annotation identifies the constructor parameter as an injection point, are equivalent:
public class Order {
@Inject
public Order(@Default OrderProcessor processor) { ... }
}
public class Order {
@Inject
public Order(OrderProcessor processor) { ... }
}
2.3.2. Defining new qualifier types
aa) A qualifier type is a Java annotation defined as @Target({METHOD, FIELD, PARAMETER, TYPE}) and @Retention(RUNTIME).
Note: Non-runtime retention annotations are discarded by the compiler
ba) A qualifier type may be declared by specifying the @javax.inject.Qualifier meta-annotation.
- QualifierDefinitionTest.testQualifierDeclaresBindingAnnotation()
d) A qualifier type may define annotation members.
Note: This is true by default in the JLS
A qualifier type is a Java annotation defined as @Retention(RUNTIME)
. Typically a qualifier type is defined as @Target({METHOD, FIELD, PARAMETER, TYPE})
.
A qualifier type may be declared by specifying the @javax.inject.Qualifier
meta-annotation.
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Synchronous {}
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Asynchronous {}
A qualifier type may define annotation members.
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface PayBy {
PaymentMethod value();
}
2.3.3. Declaring the qualifiers of a bean
The qualifiers of a bean are declared by annotating the bean class or producer method or field with the qualifier types.
a) Test by annotating a bean class.
- QualifierDefinitionTest.testQualifiersDeclaredInJava()
b) Test by annotating a producer method.
- ProducerMethodDefinitionTest.testBindingType()
c) Test by annotating a producer field.
- ProducerFieldDefinitionTest.testBindingType()
d) Any bean may declare multiple qualifier types.
- ResolutionByTypeTest.testAllQualifiersSpecifiedForResolutionMustAppearOnBean()
- QualifierDefinitionTest.testMultipleQualifiers()
The qualifiers of a bean are declared by annotating the bean class or producer method or field with the qualifier types.
@LDAP
class LdapAuthenticator
implements Authenticator {
...
}
public class Shop {
@Produces @All
public List<Product> getAllProducts() { ... }
@Produces @WishList
public List<Product> getWishList() { ... }
}
Any bean may declare multiple qualifier types.
@Synchronous @Reliable
class SynchronousReliablePaymentProcessor
implements PaymentProcessor {
...
}
2.3.4. Specifying qualifiers of an injected field
a) Qualifier types may be applied to injected fields (see Section 3.8, "Injected fields") to determine the bean that is injected, according to the rules of typesafe resolution defined in Section 5.3, "Typesafe resolution".
- SimpleBeanLifecycleTest.testCreateInjectsFieldsDeclaredInJava()
b) A bean may only be injected to an injection point if it has all the qualifiers of the injection point.
- ResolutionByTypeTest.testAllQualifiersSpecifiedForResolutionMustAppearOnBean()
Qualifier types may be applied to injected fields (see Injected fields) to determine the bean that is injected, according to the rules of typesafe resolution defined in Typesafe resolution.
@Inject @LDAP Authenticator authenticator;
A bean may only be injected to an injection point if it has all the qualifiers of the injection point.
@Inject @Synchronous @Reliable PaymentProcessor paymentProcessor;
@Inject @All List<Product> catalog;
@Inject @WishList List<Product> wishList;
2.3.5. Specifying qualifiers of a method or constructor parameter
Qualifier types may be applied to parameters of producer methods, initializer methods, disposer methods, observer methods or bean constructors (see Chapter 3, Bean implementation) to determine the bean instance that is passed when the method is called by the container.
a) Test producer method.
- ProducerMethodDefinitionTest.testBindingTypesAppliedToProducerMethodParameters()
- QualifierDefinitionTest.testFieldInjectedFromProducerMethod()
b) Test initializer method.
- InitializerMethodTest.testBindingTypeOnInitializerParameter()
c) Test disposer method.
- DisposalMethodDefinitionTest.testBindingTypesAppliedToDisposalMethodParameters()
ca) Test observer method.
- EventTest.testObserverMethodParameterInjectionPoints()
d) Test bean constructor.
- SimpleBeanLifecycleTest.testInjectionOfParametersIntoBeanConstructor()
Qualifier types may be applied to parameters of producer methods, initializer methods, disposer methods, observer methods or bean constructors (see Programming model) to determine the bean instance that is passed when the method is called by the container. The container uses the rules of typesafe resolution defined in Typesafe resolution to determine values for these parameters.
For example, when the container encounters the following producer method, an instance of SynchronousPaymentProcessor
will be passed to the first parameter and an instance of AsynchronousPaymentProcessor
will be passed to the second parameter:
@Produces
PaymentProcessor getPaymentProcessor(@Synchronous PaymentProcessor sync,
@Asynchronous PaymentProcessor async) {
return isSynchronous() ? sync : async;
}
2.4. Scopes
a) All beans have a scope.
- BeanDefinitionTest.testHasScopeType()
b) A scope type is represented by an annotation type.
Note: This is a statement of intent
c) The set of scope types is extensible.
- ScopeDefinitionTest.testScopeTypesAreExtensible()
Scoped objects, exist in a well-defined lifecycle context:
-
they may be automatically created when needed and then automatically destroyed when the context in which they were created ends, and
-
their state is automatically shared by clients that execute in the same context.
All beans have a scope. The scope of a bean determines the lifecycle of its instances, and which instances of the bean are visible to instances of other beans, as defined in Scopes and contexts. A scope type is represented by an annotation type.
For example, an object that represents the current user is represented by a session scoped object:
@Produces @SessionScoped User getCurrentUser() { ... }
An object that represents an order is represented by a conversation scoped object:
@ConversationScoped
public class Order { ... }
A list that contains the results of a search screen might be represented by a request scoped object:
@Produces @RequestScoped @Named("orders")
List<Order> getOrderSearchResults() { ... }
The set of scope types is extensible.
2.4.1. Built-in scope types
There are five standard scope types defined by this specification, all defined in the package javax.enterprise.context.
a) The container must provide an implementation of the @RequestScoped, @ApplicationScoped and @SessionScoped annotations defined in Section 6.7, “Context management for built-in scopes”.
- ContextTest.testBuiltInContexts()
ba) The @ConversationScoped annotation represents the conversation scope defined in Section 6.7.4, "Conversation context lifecycle".
- LongRunningConversationPropagatedByFacesContextTest.testConversationPropagated()
ca) The @Dependent pseudo-scope is for dependent objects, as defined in Section 6.4, "Dependent pseudo-scope"
- ContextTest.testBuiltInContexts()
e) If an interceptor or decorator has any scope other than @Dependent, non-portable behavior results.
There are five standard scope types defined by this specification, all defined in the package javax.enterprise.context
.
-
The container must provide an implementation of the @RequestScoped, @ApplicationScoped and @SessionScoped annotations defined in Context management for built-in scopes. Note that these standard scopes can be extended by third-party extensions as defined in The
Context
interface -
The
@ConversationScoped
annotation represents the conversation scope defined in Conversation context lifecycle. -
Finally, there is a
@Dependent
pseudo-scope for dependent objects, as defined in Dependent pseudo-scope.
If an interceptor or decorator has any scope other than @Dependent
, non-portable behavior results.
2.4.2. Defining new scope types
aa) A scope type is a Java annotation defined as @Target({TYPE, METHOD, FIELD}) and @Retention(RUNTIME).
- ScopeDefinitionTest.testScopeTypeHasCorrectTarget()
ab) A scope type is a Java annotation defined as @Target({TYPE, METHOD, FIELD}) and @Retention(RUNTIME).
Note: Non-runtime retention annotations are discarded by the compiler
- ScopeDefinitionTest.testScopeTypeHasCorrectTarget()
ac) A scope type must not have any attributes. If a scope type has attributes non-portable behavior results.
ba) All scope types must specify the @javax.inject.Scope or @javax.enterprise.context.NormalScope meta-annotation.
- ScopeDefinitionTest.testScopeTypeDeclaresScopeTypeAnnotation()
A scope type is a Java annotation defined as @Retention(RUNTIME)
. Typically a scope type is defined as @Target({TYPE, METHOD, FIELD})
. All scope types must also specify the @javax.inject.Scope
or @javax.enterprise.context.NormalScope
meta-annotation.
A scope type must not have any attributes. If a scope type has attributes non-portable behavior results.
For example, the following annotation declares a "business process scope":
@Inherited
@NormalScope
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface BusinessProcessScoped {}
Custom scopes are normally defined by portable extensions, which must also provide a context object, as defined in The Context
interface, that implements the custom scope.
2.4.3. Declaring the bean scope
a) The scope of a bean is defined by annotating the bean class or producer method or field with a scope type.
- ScopeDefinitionTest.testScopeDeclaredInJava()
A bean class or producer method or field may specify at most one scope type annotation. If a bean class or producer method or field specifies multiple scope type annotations, the container automatically detects the problem and treats it as a definition error.
ba) Test with a bean class.
- TooManyScopesTest.testTooManyScopesSpecifiedInJava()
- SessionBeanTooManyScopesTest.testTooManyScopesSpecifiedInJava()
bb) Test with a producer method.
- ProducerMethodTooManyScopesTest.testTooManyScopesSpecifiedInJava()
- SessionBeanProducerMethodTooManyScopesTest.testTooManyScopesSpecifiedInJava()
bc) Test with a producer field.
- ProducerFieldTooManyScopesTest.testTooManyScopesSpecifiedInJava()
- SessionBeanProducerFieldTooManyScopesTest.testTooManyScopesSpecifiedInJava()
c) A scope type may be specified using a stereotype annotation, as defined in Section 2.7.2, "Declaring the stereotypes for a bean"
- StereotypeDefinitionTest.testStereotypeWithScopeType()
The scope of a bean is defined by annotating the bean class or producer method or field with a scope type.
A bean class or producer method or field may specify at most one scope type annotation. If a bean class or producer method or field specifies multiple scope type annotations, the container automatically detects the problem and treats it as a definition error.
public class Shop {
@Produces @ApplicationScoped @All
public List<Product> getAllProducts() { ... }
@Produces @SessionScoped @WishList
public List<Product> getWishList() { ..... }
}
Likewise, a bean with the custom business process scope may be declared by annotating it with the @BusinessProcessScoped
annotation:
@BusinessProcessScoped
public class Order { ... }
Alternatively, a scope type may be specified using a stereotype annotation, as defined in Declaring the stereotypes for a bean.
2.4.4. Default scope
aa) When no scope is explicitly declared by annotating the bean class or producer method or field the scope of a bean is defaulted.
- ScopeDefinitionTest.testDefaultScope()
b) If the bean does not declare any stereotype with a declared default scope, the default scope for the bean is @Dependent.
- StereotypeDefinitionTest.testStereotypeWithoutScopeType()
c) If all stereotypes declared by the bean that have some declared default scope have the same default scope, then that scope is the default scope for the bean.
- ProducerMethodDefinitionTest.testStereotypeSpecifiesScope()
- ScopeDefinitionTest.testMultipleCompatibleScopeStereotypes()
da) If there are two different stereotypes declared by the bean that declare different default scopes, then there is no default scope and the bean must explicitly declare a scope. If it does not explicitly declare a scope, the container automatically detects the problem and treats it as a definition error.
- IncompatibleStereotypesTest.testMultipleIncompatibleScopeStereotypes()
- ScopeDefinitionTest.testMultipleIncompatibleScopeStereotypesWithScopeSpecified()
e) If a bean explicitly declares a scope, any default scopes declared by stereotypes are ignored.
- ScopeDefinitionTest.testScopeSpecifiedAndStereotyped()
- StereotypeDefinitionTest.testExplicitScopeOverridesMergedScopesFromMultipleStereotype()
When no scope is explicitly declared by annotating the bean class or producer method or field the scope of a bean is defaulted.
The default scope for a bean which does not explicitly declare a scope depends upon its declared stereotypes:
-
If the bean does not declare any stereotype with a declared default scope, the default scope for the bean is
@Dependent
. -
If all stereotypes declared by the bean that have some declared default scope have the same default scope, then that scope is the default scope for the bean.
-
If there are two different stereotypes declared by the bean that declare different default scopes, then there is no default scope and the bean must explicitly declare a scope. If it does not explicitly declare a scope, the container automatically detects the problem and treats it as a definition error.
If a bean explicitly declares a scope, any default scopes declared by stereotypes are ignored.
2.5. Default bean discovery mode
If the bean discovery mode is annotated then:
a) bean classes that don’t have bean defining annotation (as defined in Section 2.5.1, “Bean defining annotations”) are not discovered
- DefaultBeanDiscoveryModeTest.beanClassesNotDiscoveredTest()
b) producer methods (as defined in Section 3.3, “Producer methods”) whose bean class does not have a bean defining annotation are not discovered
- DefaultBeanDiscoveryModeTest.producerMethodNotDiscovered()
c) producer fields (as defined in Section 3.4, “Producer fields”) whose bean class does not have a bean defining annotation are not discovered
- DefaultBeanDiscoveryModeTest.producerFieldNotDiscovered()
d) disposer methods (as defined in Section 3.5, “Disposer methods”) whose bean class does not have a bean defining annotation are not discovered
- DefaultBeanDiscoveryModeTest.disposerMethodNotDiscovered()
e) observer methods (as defined in Section 10.4.2, “Declaring an observer method”) whose bean class does not have a bean defining annotation are not discovered
- DefaultBeanDiscoveryModeTest.observerMethodNotDiscovered()
The default bean discovery mode for a bean archive is annotated
, and such a bean archive is said to be an implicit bean archive as defined in Bean archives.
If the bean discovery mode is annotated
then:
-
bean classes that don’t have bean defining annotation (as defined in Bean defining annotations) are not discovered, and
-
producer methods (as defined in Producer methods) whose bean class does not have a bean defining annotation are not discovered, and
-
producer fields (as defined in Producer fields) whose bean class does not have a bean defining annotation are not discovered, and
-
disposer methods (as defined in Disposer methods) whose bean class does not have a bean defining annotation are not discovered, and
-
observer methods (as defined in Declaring an observer method) whose bean class does not have a bean defining annotation are not discovered.
2.5.1. Bean defining annotations
a) A bean class may have a bean defining annotation, allowing it to be placed anywhere in an application, as defined in Section 12.1. A bean class with a bean defining annotation is said to be an implicit bean.
Note: This is a statement of intent
The set of bean defining annotations contains:
ba) @ApplicationScoped, @SessionScoped, @ConversationScoped and @RequestScoped annotations
- EnterpriseBeanDiscoveryTest.testImplicitBeanArchiveNoDescriptor()
- EnterpriseBeanDiscoveryTest.testImplicitBeanArchiveModeAnnotated()
- BeanDiscoveryTest.testNormalScopeImplicitBeanArchiveNoDescriptor()
- BeanDiscoveryTest.testNormalScopeImplicitBeanArchiveModeAnnotated()
bb) all other normal scope types
- BeanDiscoveryTest.testNormalScopeImplicitBeanArchiveNoDescriptor()
- BeanDiscoveryTest.testNormalScopeImplicitBeanArchiveModeAnnotated()
bc) @Interceptor annotation
- BeanDiscoveryTest.testInterceptorIsBeanDefiningAnnotation()
bd) @Decorator annotation
- BeanDiscoveryTest.testDecoratorIsBeanDefiningAnnotation()
be) all stereotype annotations (i.e. annotations annotated with @Stereotype)
- BeanDiscoveryTest.testStereotypeImplicitBeanArchiveNoDescriptor()
- BeanDiscoveryTest.testStereotypeImplicitBeanArchiveModeAnnotated()
bf) the @Dependent scope annotation
- BeanDiscoveryTest.testDependentScopeImplicitBeanArchiveNoDescriptor()
- BeanDiscoveryTest.testPseudoScopeImplicitBeanArchiveModeAnnotated()
ca) Note that to ensure compatibility with other JSR-330 implementations, all pseudo-scope annotations except @Dependent are not bean defining annotations.
- BeanDiscoveryTest.testPseudoScopeImplicitBeanArchiveModeAnnotated()
cb) However, a stereotype annotation including a pseudo-scope annotation is a bean defining annotation.
- BeanDiscoveryTest.testStereotypeImplicitBeanArchiveNoDescriptor()
- BeanDiscoveryTest.testStereotypeImplicitBeanArchiveModeAnnotated()
A bean class may have a bean defining annotation, allowing it to be placed anywhere in an application, as defined in Bean archives. A bean class with a bean defining annotation is said to be an implicit bean.
The set of bean defining annotations contains:
-
@ApplicationScoped
,@SessionScoped
,@ConversationScoped
and@RequestScoped
annotations, -
all other normal scope types,
-
@Interceptor
and@Decorator
annotations, -
all stereotype annotations (i.e. annotations annotated with
@Stereotype
), -
and the
@Dependent
scope annotation.
If one of these annotations is declared on a bean class, then the bean class is said to have a bean defining annotation. For example, this dependent scoped bean has a bean defining annotation:
@Dependent
public class BookShop
extends Business
implements Shop<Book> {
...
}
whilst this dependent scoped bean does not have a bean defining annotation:
public class CoffeeShop
extends Business
implements Shop<Coffee> {
...
}
Note that to ensure compatibility with other JSR-330 implementations, all pseudo-scope annotations except @Dependent
are not bean defining annotations. However, a stereotype annotation including a pseudo-scope annotation is a bean defining annotation.
2.6. Bean names
a) A valid bean name is a period-separated list of valid EL identifiers
- ResolutionByNameTest.testELResolverReturnsContextualInstance()
- ResolutionByNameTest.testBeanNameWithSeparatedListOfELIdentifiers()
A bean may have a bean name. A bean with a name may be referred to by its name when used in a non typesafe environment (like the Unified Expression Language). A valid bean name is a period-separated list of valid EL identifiers.
The following strings are valid bean names:
com.acme.settings
orderManager
Subject to the restrictions defined in Ambiguous names, multiple beans may share the same bean name.
Bean names are used by the rules of bean name resolution defined in Name resolution.
2.6.1. Declaring the bean name
To specify the name of a bean, the qualifier @javax.inject.Named is applied to the bean class or producer method or field.
a) Test with a bean class.
- NameDefinitionTest.testNonDefaultNamed()
b) Test with a producer method.
- ProducerMethodDefinitionTest.testNamedMethod()
c) Test with a producer field.
- ProducerFieldDefinitionTest.testNamedField()
To specify the name of a bean, the qualifier @javax.inject.Named
is applied to the bean class or producer method or field. This bean is named currentOrder
:
@Named("currentOrder")
public class Order { ... }
2.6.2. Default bean names
A default name must be assigned by the container when a bean class or producer method or field of a bean declares a @Named annotation and no bean name is explicitly specified by the value member.
a) Test with a bean class.
- NameDefinitionTest.testDefaultNamed()
- NameDefinitionTest.testDefaultNamed()
- NamedAtInjectionPointTest.testFieldNameUsedAsBeanName()
b) Test with a producer method.
- ProducerMethodDefinitionTest.testDefaultNamedMethod()
- ProducerMethodDefinitionTest.testDefaultNamedMethod()
c) Test with a producer field.
- ProducerFieldDefinitionTest.testDefaultNamedByStereotype()
- ProducerFieldDefinitionTest.testDefaultNamed()
e) A default name must be assigned by the container when a bean declares a stereotype that declares an empty @Named annotation, and the bean does not explicitly specify an bean name.
- DefaultNamedTest.testStereotypeDeclaringNamed()
If a bean class or producer method or field of a bean declares a @Named annotation and no bean name is explicitly specified the value of the value member is defaulted.
fa) Test with a bean class.
- NameDefinitionTest.testDefaultNamed()
- NameDefinitionTest.testDefaultNamed()
- NamedAtInjectionPointTest.testFieldNameUsedAsBeanName()
fb) Test with a producer method.
- ProducerMethodDefinitionTest.testDefaultNamedMethod()
- ProducerMethodDefinitionTest.testDefaultNamedMethod()
fc) Test with a producer field.
- ProducerFieldDefinitionTest.testDefaultNamedByStereotype()
- ProducerFieldDefinitionTest.testDefaultNamed()
In the following circumstances, a default name must be assigned by the container:
-
A bean class or producer method or field of a bean declares a
@Named
annotation and no bean name is explicitly specified by thevalue
member. -
A bean declares a stereotype that declares an empty
@Named
annotation, and the bean does not explicitly specify a bean name.
The default name for a bean depends upon the kind of the bean. The rules for determining the default name for a bean are defined in Default bean name for a managed bean, Default bean name for a producer method and Default bean name for a producer field.
2.6.3. Beans with no name
a) If @Named is not declared by the bean, nor by its stereotypes, a bean has no name.
- ProducerFieldDefinitionTest.testDefaultNamedByStereotype()
- NameDefinitionTest.testNamedNotDeclaredByBean()
- NameDefinitionTest.testNamedNotDeclaredByStereotype()
b) If an interceptor or decorator has a name, non-portable behavior results.
If @Named
is not declared by the bean, nor by its stereotypes, a bean has no name.
If an interceptor or decorator has a name, non-portable behavior results.
2.7. Alternatives
a) An alternative is a bean that must be explicitly selected if it should be available for lookup, injection or EL resolution.
Note: Tested in section 5.1.1 Declaring selected alternatives.
An alternative is a bean that must be explicitly selected if it should be available for lookup, injection or name resolution.
2.7.1. Declaring an alternative
An alternative may be declared by annotating the bean class or producer method or field with the @Alternative annotation.
aa) Test with a bean class.
- AlternativeInLibraryWithExtensionTest.testAlternative()
- Specialization04Test.testEnabledAlternativeSpecializes()
- AlternativeAvailabilityTest.testAlternativeAvailability()
- Specialization03Test.testEnabledAlternativeSpecializes()
- Specialization02Test.testEnabledAlternativeSpecializes()
- Specialization01Test.testNotEnabledAlternativeDoesNotSpecialize()
- Specialization05Test.testEnabledAlternativeSpecializes()
- Specialization06Test.testEnabledAlternativeSpecializes()
ab) Test with a producer method.
- AlternativeAvailabilityTest.testProducerAlternativesOnMethodAndField()
- AlternativeAvailabilityTest.testStereotypeAlternativeOnProducerMethodAndField()
ac) Test with a producer field.
- AlternativeAvailabilityTest.testProducerAlternativesOnMethodAndField()
- AlternativeAvailabilityTest.testStereotypeAlternativeOnProducerMethodAndField()
An alternative may be declared by annotating a bean, producer method or producer field with a stereotype that declares an @Alternative annotation.
ba) Test with a bean.
- AlternativeAvailabilityTest.testAnyEnabledAlternativeStereotypeMakesAlternativeEnabled()
bb) Test with a producer method.
- AlternativeAvailabilityTest.testProducerAlternativesOnMethodAndField()
- AlternativeAvailabilityTest.testStereotypeAlternativeOnProducerMethodAndField()
bc) Test with a producer field.
- AlternativeAvailabilityTest.testProducerAlternativesOnMethodAndField()
- AlternativeAvailabilityTest.testStereotypeAlternativeOnProducerMethodAndField()
c) If an interceptor or decorator is an alternative, non-portable behavior results.
Note: Non-portable behavior.
An alternative may be declared by annotating the bean class or producer method or field with the @Alternative
annotation.
@Alternative
public class MockOrder extends Order { ... }
Alternatively, an alternative may be declared by annotating a bean, producer method or producer field with a stereotype that declares an @Alternative
annotation.
If an interceptor or decorator is an alternative, non-portable behavior results.
2.8. Stereotypes
a) A stereotype may specify that all beans with the stereotype have defaulted bean names.
- DefaultNamedTest.testStereotypeDeclaringNamed()
- NameDefinitionTest.testStereotypeDefaultsName()
aa) A stereotype may specify that all beans with the stereotype are alternatives.
- AlternativeAvailabilityTest.testAnyEnabledAlternativeStereotypeMakesAlternativeEnabled()
A bean may declare zero, one or multiple stereotypes.
b) A bean may declare zero stereotypes.
Note: Not testable through API
c) Test with one stereotype.
- StereotypeDefinitionTest.testOneStereotypeAllowed()
d) Test with multiple stereotypes.
- StereotypeDefinitionTest.testMultipleStereotypesAllowed()
In many systems, use of architectural patterns produces a set of recurring bean roles. A stereotype allows a framework developer 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:
-
a default scope, and
-
a set of interceptor bindings.
A stereotype may also specify that:
-
all beans with the stereotype have defaulted bean names, or that
-
all beans with the stereotype are alternatives.
A bean may declare zero, one or multiple stereotypes.
2.8.1. Defining new stereotypes
A beans stereotype is a Java annotation defined as @Target({TYPE, METHOD, FIELD}), @Target(TYPE), @Target(METHOD), @Target(FIELD) or @Target({METHOD, FIELD}) and @Retention(RUNTIME).
aa) Test @Target({TYPE, METHOD, FIELD}).
ab) Test @Target(TYPE).
ac) Test @Target(FIELD).
ad) Test @Target({METHOD, FIELD}).
ae) @Retention(RUNTIME) - untestable.
Note: Non-runtime retention annotations are discarded by the compiler
b) A stereotype may be declared by specifying the @javax.enterprise.inject.Stereotype meta-annotation.
- StereotypeDefinitionTest.testOneStereotypeAllowed()
A bean stereotype is a Java annotation defined as @Retention(RUNTIME)
. Typically a bean stereotype is defined as @Target({TYPE, METHOD, FIELD})
, @Target(TYPE)
, @Target(METHOD)
, @Target(FIELD)
or @Target({METHOD, FIELD})
.
A stereotype may be declared by specifying the @javax.enterprise.inject.Stereotype
meta-annotation.
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface Action {}
Declaring the default scope for a stereotype
The default scope of a stereotype is defined by annotating the stereotype with a scope type. A stereotype may declare at most one scope. If a stereotype declares more than one scope, the container automatically detects the problem and treats it as a definition error.
aa) Test with one scope.
- StereotypeDefinitionTest.testStereotypeWithScopeType()
- StereotypeDefinitionTest.testStereotypeWithoutScopeType()
ab) Test that a stereotype with multiple scopes throws an exception.
- TooManyScopeTypesTest.testStereotypeWithTooManyScopeTypes()
The default scope of a stereotype is defined by annotating the stereotype with a scope type. A stereotype may declare at most one scope. If a stereotype declares more than one scope, the container automatically detects the problem and treats it as a definition error.
For example, the following stereotype might be used to identify action classes in a web application:
@RequestScoped
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface Action {}
Then actions would have scope @RequestScoped
unless the scope is explicitly specified by the bean.
Specifying interceptor bindings for a stereotype
aa) The interceptor bindings of a stereotype are defined by annotating the stereotype with the interceptor binding types.
- StereotypeWithMultipleInterceptorBindingsTest.testMultipleInterceptorBindings()
a) A stereotype may declare zero interceptor bindings.
- StereotypeDefinitionTest.testOneStereotypeAllowed()
b) A stereotype may declare one interceptor bindings.
- InterceptorDefinitionTest.testStereotypeInterceptorBindings()
c) A stereotype may declare multiple interceptor bindings.
- StereotypeWithMultipleInterceptorBindingsTest.testMultipleInterceptorBindings()
The interceptor bindings of a stereotype are defined by annotating the stereotype with the interceptor binding types. A stereotype may declare zero, one or multiple interceptor bindings, as defined in Interceptor bindings for stereotypes.
We may specify interceptor bindings that apply to all actions:
@RequestScoped
@Secure
@Transactional
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface Action {}
Declaring a @Named
stereotype
aa) A stereotype may declare an empty @Named annotation, which specifies that every bean with the stereotype has a defaulted name when a name is not explicitly specified by the bean.
- ProducerFieldDefinitionTest.testDefaultNamedByStereotype()
- DefaultNamedTest.testStereotypeDeclaringNamed()
- DefaultNamedTest.testStereotypeNamedOverridenByBean()
- ProducerMethodWithDefaultNameTest.testProducerMethodQualifiers()
- NameDefinitionTest.testStereotypeDefaultsName()
ab) A @Named qualifier declared by a stereotype is not added to the qualifiers of a bean with the stereotype.
- ProducerFieldDefinitionTest.testDefaultNamedByStereotype()
- DefaultNamedTest.testStereotypeDeclaringNamed()
- ProducerMethodWithDefaultNameTest.testProducerMethodQualifiers()
ac) If a stereotype declares a non-empty @Named annotation, the container automatically detects the problem and treats it as a definition error.
- NonEmptyNamedTest.testStereotypeWithNonEmptyNamed()
b) A stereotype should not declare any qualifier annotation other than @Named. If a stereotype declares any other qualifier annotation, non-portable behavior results.
Note: The behavior here is undefined.
c) A stereotype should not be annotated @Typed. If a stereotype is annotated @Typed, non-portable behavior results.
A stereotype may declare an empty @Named
annotation, which specifies that every bean with the stereotype has a defaulted name when a name is not explicitly specified by the bean. A @Named
qualifier declared by a stereotype is not added to the qualifiers of a bean with the stereotype.
If a stereotype declares a non-empty @Named
annotation, the container automatically detects the problem and treats it as a definition error.
We may specify that all actions have bean names:
@RequestScoped
@Secure
@Transactional
@Named
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface Action {}
A stereotype should not declare any qualifier annotation other than @Named
. If a stereotype declares any other qualifier annotation, non-portable behavior results.
A stereotype should not be annotated @Typed
. If a stereotype is annotated @Typed
, non-portable behavior results.
Declaring an @Alternative
stereotype
a) A stereotype may declare an @Alternative annotation, which specifies that every bean with the stereotype is an alternative.
- AlternativeAvailabilityTest.testAnyEnabledAlternativeStereotypeMakesAlternativeEnabled()
A stereotype may declare an @Alternative
annotation, which specifies that every bean with the stereotype is an alternative.
We may specify that all mock objects are alternatives:
@Alternative
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface Mock {}
Stereotypes with additional stereotypes
a) A stereotype may declare other stereotypes.
- StereotypeInheritenceTest.testInheritence()
b) Stereotype declarations are transitive - a stereotype declared by a second stereotype is inherited by all beans and other stereotypes that declare the second stereotype.
- StereotypeInheritenceTest.testInheritence()
c) Stereotypes declared @Target(TYPE) may not be applied to stereotypes declared @Target({TYPE, METHOD, FIELD}), @Target(METHOD), @Target(FIELD), @Target({METHOD, FIELD}).
Note: No definition of what happens if you do this
A stereotype may declare other stereotypes.
@Auditable
@Action
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface AuditableAction {}
Stereotype declarations are transitive - a stereotype declared by a second stereotype is inherited by all beans and other stereotypes that declare the second stereotype.
Stereotypes declared @Target(TYPE)
may not be applied to stereotypes declared @Target({TYPE, METHOD, FIELD})
, @Target(METHOD)
, @Target(FIELD)
or @Target({METHOD, FIELD})
.
2.8.2. Declaring the stereotypes for a bean
Stereotype annotations may be applied to a bean class or producer method or field.
a) Test with a bean class.
- ScopeDefinitionTest.testScopeSpecifiedAndStereotyped()
b) Test with a producer method.
- ProducerMethodDefinitionTest.testStereotypeSpecifiesScope()
c) Test with a producer field.
- ProducerFieldDefinitionTest.testStereotype()
db) The default scope declared by the stereotype may be overridden by the bean.
- ScopeDefinitionTest.testWebBeanScopeTypeOverridesStereotype()
e) Multiple stereotypes may be applied to the same bean.
- StereotypeDefinitionTest.testMultipleStereotypesAllowed()
- StereotypeDefinitionTest.testExplicitScopeOverridesMergedScopesFromMultipleStereotype()
Stereotype annotations may be applied to a bean class or producer method or field.
@Action
public class LoginAction { ... }
The default scope declared by the stereotype may be overridden by the bean:
@Mock @ApplicationScoped @Action
public class MockLoginAction extends LoginAction { ... }
Multiple stereotypes may be applied to the same bean:
@Dao @Action
public class LoginAction { ... }
2.8.3. Built-in stereotypes
aa) The built-in stereotype @javax.enterprise.inject.Model is intended for use with beans that define the model layer of an MVC web application architecture such as JSF.
Note: Tested by API signature test
The built-in stereotype @javax.enterprise.inject.Model
is intended for use with beans that define the model layer of an MVC web application architecture such as JSF:
@Named
@RequestScoped
@Stereotype
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface Model {}
In addition, the special-purpose @Interceptor
and @Decorator
stereotypes are defined in Declaring the interceptor bindings of an interceptor and Declaring a decorator.
2.9. Problems detected automatically by the container
a) When the application violates a rule defined by this specification, the container automatically detects the problem. There are three kinds of problem - definition errors occur when a single bean definition violates the rules of this specification, deployment problems occur when there are problems resolving dependencies, or inconsistent specialization, in a particular deployment, and exceptions occur at runtime.
Note: Generalization
b) Definition errors are developer errors. They may be detected by tooling at development time, and are also detected by the container at initialization time. If a definition error exists in a deployment, initialization will be aborted by the container.
- TooManyScopeTypesTest.testStereotypeWithTooManyScopeTypes()
- ArrayTest.testInjectionPointWithArrayType()
ba) If a definition error exists, the container must throw a subclass of javax.enterprise.inject.spi.DefinitionException.
- ProducerFieldTooManyScopesTest.testTooManyScopesSpecifiedInJava()
- DependentWithPublicFieldTest.testNonDependentScopedBeanCanNotHavePublicField()
- TooManyScopesTest.testTooManyScopesSpecifiedInJava()
- ProducerMethodTooManyScopesTest.testTooManyScopesSpecifiedInJava()
- RestrictedManagedBeanTest.testInvalidTypedValueOnManagedBean()
c) Deployment problems are detected by the container at initialization time. If a deployment problem exists in a deployment, initialization will be aborted by the container.
- NoClassWithSpecifiedNameTest.test()
- AmbiguousDependencyTest.testAmbiguousDependency()
ca) If a deployment problem occurs, the container must throw a subclass of javax.enterprise.inject.spi.DeploymentException.
- NoClassWithSpecifiedNameTest.test()
- AmbiguousDependencyTest.testAmbiguousDependency()
d) The container is permitted to define a non-portable mode, for use at development time, in which some definition errors and deployment problems do not cause application initialization to abort.
e) Exceptions represent problems that may not be detected until they actually occur at runtime. All exceptions defined by this specification are unchecked exceptions. All exceptions defined by this specification may be safely caught and handled by the application.
When the application violates a rule defined by this specification, the container automatically detects the problem. There are three kinds of problem:
-
Definition errors - occur when a single bean definition violates the rules of this specification. If a definition error exists, the container must throw a subclass of
javax.enterprise.inject.spi.DefinitionException
. -
Deployment problems - occur when there are problems resolving dependencies, or inconsistent specialization, in a particular deployment. If a deployment problem occurs, the container must throw a subclass of
javax.enterprise.inject.spi.DeploymentException
. -
Exceptions - occur at runtime
Definition errors are developer errors. They may be detected by tooling at development time, and are also detected by the container at initialization time. If a definition error exists in a deployment, initialization will be aborted by the container.
Deployment problems are detected by the container at initialization time. If a deployment problem exists in a deployment, initialization will be aborted by the container.
The container is permitted to define a non-portable mode, for use at development time, in which some definition errors and deployment problems do not cause application initialization to abort.
Exceptions represent problems that may not be detected until they actually occur at runtime. All exceptions defined by this specification are unchecked exceptions. All exceptions defined by this specification may be safely caught and handled by the application.
3. Programming model
The container provides built-in support for injection and contextual lifecycle management of the following kinds of bean:
-
Managed beans
-
Producer methods and fields
All containers must support managed beans, producer methods and producer fields.
A portable extension may provide other kinds of beans by implementing the interface Bean
defined in The Bean
interface.
3.1. Managed beans
a) If the bean class of a managed bean is annotated with both the @Interceptor and @Decorator stereotypes, the container automatically detects the problem and treats it as a definition error.
- InterceptorCanNotBeDecoratorTest.testInterceptorCanNotAlsoBeDecorator()
If a managed bean has a non-static public field, it must have scope @Dependent. If a managed bean with a non-static public field declares any scope other than @Dependent, the container automatically detects the problem and treats it as a definition error.
fa) Check a dependent scoped bean with a public field.
- SimpleBeanDefinitionTest.testDependentScopedBeanCanHaveNonStaticPublicField()
fb) Check a managed bean with a static public field which declares any scope other than @Dependent.
- NonDependentWithPublicStaticFieldTest.testNonDependentScopedBeanCanHavePublicStaticField()
fc) If a managed bean with a non-static public field declares any scope other than @Dependent, the container automatically detects the problem and treats it as a definition error.
- DependentWithPublicFieldTest.testNonDependentScopedBeanCanNotHavePublicField()
g) If the managed bean class is a generic type, it must have scope @Dependent. If a managed bean with a parameterized bean class declares any scope other than @Dependent, the container automatically detects the problem and treats it as a definition error.
- GenericManagedBeanTest.testNonDependentGenericManagedBeanNotOk()
A managed bean is a bean that is implemented by a Java class. This class is called the bean class of the managed bean. The basic lifecycle and semantics of managed beans are defined by the Managed Beans specification.
If the bean class of a managed bean is annotated with both @Interceptor
and @Decorator
, the container automatically detects the problem and treats it as a definition error.
If a managed bean has a non-static public field, it must have scope @Dependent
. If a managed bean with a non-static public field declares any scope other than @Dependent
, the container automatically detects the problem and treats it as a definition error.
If the managed bean class is a generic type, it must have scope @Dependent
. If a managed bean with a parameterized bean class declares any scope other than @Dependent
, the container automatically detects the problem and treats it as a definition error.
3.1.1. Which Java classes are managed beans?
b) A top-level Java class is not a managed bean if it is a non-static inner class.
- SimpleBeanDefinitionTest.testNonStaticInnerClassDeclaredInJavaNotDiscovered()
ba) A top-level Java class that is a static inner class can be a managed bean.
- SimpleBeanDefinitionTest.testStaticInnerClassDeclaredInJavaAllowed()
ca) A top-level Java class is not a managed bean if it is an abstract class, unless it is annotated @Decorator.
- SimpleBeanDefinitionTest.testAbstractClassDeclaredInJavaNotDiscovered()
cb) A top-level Java class is not a managed bean if it is an interface, unless it is annotated @Decorator.
- SimpleBeanDefinitionTest.testInterfaceNotDiscoveredAsSimpleBean()
g) A top-level Java class is not a managed bean if it implements javax.enterprise.inject.spi.Extension.
- SimpleBeanDefinitionTest.testExtensionNotDiscoveredAsSimpleBean()
h) A top-level Java class is not a managed bean if it is annotated @Vetoed or placed in a package annotated @Vetoed.
- VetoedTest.testClassLevelVeto()
- VetoedTest.testPackageLevelVeto()
p) A top-level Java class is only a managed bean if it has an appropriate constructor - a constructor with no parameters.
- SimpleBeanDefinitionTest.testSimpleBeanOnlyIfConstructorParameterless()
q) A top-level Java class is only a managed bean if it has an appropriate constructor - a constructor annotated @Inject.
- SimpleBeanDefinitionTest.testSimpleBeanOnlyIfConstructorIsInitializer()
r) If packages annotated @Vetoed are split across classpath entries, non-portable behavior results. An application can prevent packages being split across jars by sealing the package as defined by the Extension Mechanism Architecture.
Note: Non-portable behavior.
A top-level Java class is a managed bean if it meets all of the following conditions:
-
It is not a non-static inner class.
-
It is a concrete class, or is annotated
@Decorator
. -
It does not implement
javax.enterprise.inject.spi.Extension
. -
It is not annotated
@Vetoed
or in a package annotated@Vetoed
. -
It has an appropriate constructor - either:
-
the class has a constructor with no parameters, or
-
the class declares a constructor annotated
@Inject
.
-
All Java classes that meet these conditions are managed beans and thus no special declaration is required to define a managed bean.
If packages annotated @Vetoed
are split across classpath entries, non-portable behavior results. An application can prevent packages being split across jars by sealing the package as defined by the Extension Mechanism Architecture.
3.1.2. Bean types of a managed bean
a) The unrestricted set of bean types for a managed bean contains the bean class, every superclass and all interfaces it implements directly or indirectly.
- BeanDefinitionTest.testBeanTypes()
- BeanDefinitionTest.testGenericBeanTypes()
- BeanDefinitionTest.testRawBeanTypes()
- ManagedBeanTypesTest.testGenericHierarchyBeanTypes()
The unrestricted set of bean types for a managed bean contains the bean class, every superclass and all interfaces it implements directly or indirectly.
Note the additional restrictions upon bean types of beans with normal scopes defined in Unproxyable bean types.
3.1.3. Declaring a managed bean
a) A managed bean with a constructor that takes no parameters does not require any special annotations
- SimpleBeanDefinitionTest.testEmptyConstructorUsed()
ab) If the managed bean does not have a constructor that takes no parameters, it must have a constructor annotated @Inject. No additional special annotations are required.
A bean class may also specify a scope, name, stereotypes and/or qualifiers.
ba) Test a bean with a scope.
- BeanDefinitionTest.testHasScopeType()
bb) Test a bean with a name.
- NameDefinitionTest.testNonDefaultNamed()
bd) Test a bean with a stereotype.
- BeanDefinitionTest.testMultipleStereotypes()
be) Test a bean with a qualifier.
- QualifierDefinitionTest.testQualifiersDeclaredInJava()
c) A managed bean may extend another managed bean.
- BeanDefinitionTest.testBeanExtendsAnotherBean()
A managed bean with a constructor that takes no parameters does not require any special annotations. The following classes are beans:
public class Shop { .. }
class PaymentProcessorImpl implements PaymentProcessor { ... }
If the managed bean does not have a constructor that takes no parameters, it must have a constructor annotated @Inject
. No additional special annotations are required.
A bean class may specify a scope, bean name, stereotypes and/or qualifiers:
@ConversationScoped @Default
public class ShoppingCart { ... }
A managed bean may extend another managed bean:
@Named("loginAction")
public class LoginAction { ... }
@Mock
@Named("loginAction")
public class MockLoginAction extends LoginAction { ... }
The second bean is a "mock object" that overrides the implementation of LoginAction
when running in an embedded CDI based integration testing environment.
3.1.4. Specializing a managed bean
If a bean class of a managed bean X is annotated @Specializes, then the bean class of X must directly extend the bean class of another managed bean Y. Then X directly specializes Y, as defined in Section 4.3, "Specialization".
aa) Test that a specializing bean has all its own qualifiers and the qualifiers of the specialized bean.
- SimpleBeanSpecializationTest.testSpecializingBeanHasQualifiersOfSpecializedAndSpecializingBean()
ab) Test that a specializing bean has the name of the specialized bean.
- SimpleBeanSpecializationTest.testSpecializingBeanHasNameOfSpecializedBean()
ac) Test a specialized bean extending a managed bean.
- Specialization04Test.testEnabledAlternativeSpecializes()
- Specialization03Test.testEnabledAlternativeSpecializes()
- Specialization02Test.testEnabledAlternativeSpecializes()
- Specialization01Test.testNotEnabledAlternativeDoesNotSpecialize()
- Specialization05Test.testEnabledAlternativeSpecializes()
- SimpleBeanLifecycleTest.testSpecializedBeanExtendsManagedBean()
- Specialization06Test.testEnabledAlternativeSpecializes()
If the bean class of X does not directly extend the bean class of another managed bean, the container automatically detects the problem and treats it as a definition error.
da) Test a specializing bean extending a non simple bean.
- SpecializingClassExtendsNonSimpleBeanTest.testSpecializingClassExtendsNonSimpleBean()
db) Test a specializing bean extending nothing.
- SpecializingBeanExtendsNothingTest.testSpecializingClassDirectlyExtendsNothing()
dd) Test a specializing bean implementing an interface and extending nothing.
- SpecializingBeanImplementsInterfaceOnly.testSpecializingClassImplementsInterfaceAndExtendsNothing()
If a bean class of a managed bean X is annotated @Specializes
, then the bean class of X must directly extend the bean class of another managed bean Y. Then X directly specializes Y, as defined in Specialization.
If the bean class of X does not directly extend the bean class of another managed bean, the container automatically detects the problem and treats it as a definition error.
For example, MockLoginAction
directly specializes LoginAction
:
public class LoginAction { ... }
@Mock @Specializes
public class MockLoginAction extends LoginAction { ... }
3.1.5. Default bean name for a managed bean
a) The default name for a managed bean is the unqualified class name of the bean class, after converting the first character to lower case
- NameDefinitionTest.testDefaultNamed()
- NameDefinitionTest.testNameStartingWithMultipleUpperCaseCharacters()
- NameDefinitionTest.testNameStartingWithUnderScoreCharacter()
- NameDefinitionTest.testNameStartingWithDollarCharacter()
- NameDefinitionTest.testNameStartingWithLowerCaseCharacter()
The default name for a managed bean is the unqualified class name of the bean class, after converting the first character to lower case.
For example, if the bean class is named ProductList
, the default bean name is productList
.
3.2. Producer methods
aa) A producer method must be a default-access, public, protected or private, non-abstract method of a managed bean class.
- ProducerMethodDefinitionTest.testProducerOnNonBean()
- EnterpriseArchiveModulesTest.testProducerAndEventDuringDisposal()
- WebArchiveModulesTest.testProducerAndEventDuringDisposal()
b) A producer method may be static.
- ProducerMethodDefinitionTest.testStaticMethod()
c) A producer method may be non-static.
- ProducerMethodDefinitionTest.testDefaultBindingType()
- EnterpriseArchiveModulesTest.testProducerAndEventDuringDisposal()
- WebArchiveModulesTest.testProducerAndEventDuringDisposal()
e) If a producer method sometimes returns a null value, then the producer method must have scope @Dependent.
- ProducerMethodDefinitionTest.testDependentProducerReturnsNullValue()
f) If a producer method returns a null value at runtime, and the producer method declares scope other than @Dependent, an IllegalProductException is thrown by the container. This restriction allows the container to use a client proxy, as defined in Section 5.4, "Client proxies".
- ProducerMethodDefinitionTest.testNonDependentProducerReturnsNullValue()
ga) If the producer method return type is a parameterized type, it must specify an actual type parameter or type variable for each type parameter.
- ProducerMethodDefinitionTest.testParameterizedReturnType()
ha) If a producer method return type contains a wildcard type parameter the container automatically detects the problem and treats it as a definition error.
- ParametrizedTypeWithWildcard02Test.testParameterizedReturnTypeWithDoubleWildcard()
- ParameterizedTypeWithWildcardTest.testParameterizedReturnTypeWithWildcard()
hb) If a producer method return type is an array type whose component type contains a wildcard type parameter the container automatically detects the problem and treats it as a definition error.
- ProducerMethodArrayWildcardTest.testBeanTypes()
iaa) If the producer method return type is a parameterized type with a type variable, it must have scope @Dependent.
- ProducerMethodDefinitionTest.testTypeVariableReturnType()
iab) If a producer method with a parameterized return type with a type variable declares any scope other than @Dependent, the container automatically detects the problem and treats it as a definition error.
- ParameterizedReturnTypeWithTypeVariableTest.testNonDependentScopedProducerMethodWithParameterizedTypeWithTypeVariable()
ib) If a producer method return type is a type variable the container automatically detects the problem and treats it as a definition error.
- TypeVariableReturnTypeTest.testTypeVariableNotAllowed()
ic) If a producer method return type is an array type whose component type is a type variable the container automatically detects the problem and treats it as a definition error.
- ProducerMethodArrayTypeVariableTest.testBeanTypes()
j) The application may call producer methods directly. However, if the application calls a producer method directly, no parameters will be passed to the producer method by the container; the returned object is not bound to any context; and its lifecycle is not managed by the container.
- ProducerMethodLifecycleTest.testWhenApplicationInvokesProducerMethodParametersAreNotInjected()
k) A bean may declare multiple producer methods.
- ProducerMethodDefinitionTest.testBindingType()
- ProducerMethodDefinitionTest.testScopeType()
A producer method acts as a source of objects to be injected, where:
-
the objects to be injected are not required to be instances of beans, or
-
the concrete type of the objects to be injected may vary at runtime, or
-
the objects require some custom initialization that is not performed by the bean constructor.
A producer method must be a default-access, public, protected or private, non-abstract method of a managed bean class. A producer method may be either static or non-static.
If a producer method sometimes returns a null value, then the producer method must have scope @Dependent
. If a producer method returns a null value at runtime, and the producer method declares any other scope, an IllegalProductException
is thrown by the container. This restriction allows the container to use a client proxy, as defined in Client proxies.
If the producer method return type is a parameterized type, it must specify an actual type parameter or type variable for each type parameter.
If a producer method return type contains a wildcard type parameter or is an array type whose component type contains a wildcard type parameter, the container automatically detects the problem and treats it as a definition error.
If the producer method return type is a parameterized type with a type variable, it must have scope @Dependent
. If a producer method with a parameterized return type with a type variable declares any scope other than @Dependent
, the container automatically detects the problem and treats it as a definition error.
If a producer method return type is a type variable or an array type whose component type is a type variable the container automatically detects the problem and treats it as a definition error.
The application may call producer methods directly. However, if the application calls a producer method directly, no parameters will be passed to the producer method by the container; the returned object is not bound to any context; and its lifecycle is not managed by the container.
A bean may declare multiple producer methods.
3.2.1. Bean types of a producer method
a) If the return type of a producer method is an interface, the unrestricted set of bean types contains the return type, all interfaces it extends directly or indirectly and java.lang.Object
- ProducerMethodDefinitionTest.testApiTypeForInterfaceReturn()
If a return type of a producer method is primitive or is a Java array type, the unrestricted set of bean types contains exactly two types: the method return type and java.lang.Object.
ba) Check primitive return type
- ProducerMethodDefinitionTest.testApiTypeForPrimitiveReturn()
bb) Check array return type
- ProducerMethodDefinitionTest.testApiTypeForArrayTypeReturn()
c) If the return type of a producer method is a class, the unrestricted set of bean types contains the return type, every superclass and all interfaces it implements directly or indirectly.
- ProducerMethodDefinitionTest.testApiTypeForClassReturn()
The bean types of a producer method depend upon the method return type:
-
If the return type is an interface, the unrestricted set of bean types contains the return type, all interfaces it extends directly or indirectly and
java.lang.Object
. -
If a return type is primitive or is a Java array type, the unrestricted set of bean types contains exactly two types: the method return type and
java.lang.Object
. -
If the return type is a class, the unrestricted set of bean types contains the return type, every superclass and all interfaces it implements directly or indirectly.
Note the additional restrictions upon bean types of beans with normal scopes defined in Unproxyable bean types.
3.2.2. Declaring a producer method
a) A producer method may be declared by annotating a method with the @javax.enterprise.inject.Produces annotation
- ProducerMethodDefinitionTest.testDefaultBindingType()
ba) A producer method may specify a scope.
- ProducerMethodDefinitionTest.testScopeType()
- ProducerMethodDefinitionTest.testStereotypeSpecifiesScope()
bb) A producer method may specify a name.
- ProducerMethodDefinitionTest.testNamedMethod()
- ProducerMethodDefinitionTest.testDefaultNamedMethod()
bd) A producer method may specify stereotypes.
- ProducerMethodDefinitionTest.testStereotypeSpecifiesScope()
be) A producer method may specify qualifiers.
- ProducerMethodDefinitionTest.testBindingType()
If a producer method is annotated @Inject, has a parameter annotated @Disposes, or has a parameter annotated @Observes, the container automatically detects the problem and treats it as a definition error.
ca) Test with a producer method annotated @Inject.
- InitializerMethodAnnotatedProducesTest.testInitializerMethodAnnotatedProduces()
da) Test with a producer method annotated @Disposes.
- ParameterAnnotatedDisposesTest.testProducerMethodWithParameterAnnotatedDisposes()
ea) Test with a producer method annotated @Observes.
- ParameterAnnotatedObservesTest.testProducerMethodWithParameterAnnotatedObserves()
ga) Interceptors and decorators may not declare producer methods. If an interceptor or decorator has a method annotated @Produces, the container automatically detects the problem and treats it as a definition error.
- ProducerMethodOnInterceptorTest.testProducerMethodNotAllowedOnInterceptor()
- ProducerMethodOnDecoratorTest.testProducerMethodNotAllowedOnDecorator()
gb) Interceptors and decorators may not declare producer methods. If an interceptor or decorator has a method annotated @Produces, the container automatically detects the problem and treats it as a definition error.
- ProducerMethodOnInterceptorTest.testProducerMethodNotAllowedOnInterceptor()
- ProducerMethodOnDecoratorTest.testProducerMethodNotAllowedOnDecorator()
h) A producer method may have any number of parameters.
- ProducerMethodDefinitionTest.testBindingTypesAppliedToProducerMethodParameters()
i) All producer method parameters are injection points.
- ProducerMethodDefinitionTest.testBindingTypesAppliedToProducerMethodParameters()
- DisposedParameterPositionTest.testDisposedParameterPosition()
A producer method may be declared by annotating a method with the @javax.enterprise.inject.Produces
annotation.
public class Shop {
@Produces PaymentProcessor getPaymentProcessor() { ... }
@Produces List<Product> getProducts() { ... }
}
A producer method may also specify scope, bean name, stereotypes and/or qualifiers.
public class Shop {
@Produces @ApplicationScoped @Catalog @Named("catalog")
List<Product> getProducts() { ... }
}
If a producer method is annotated @Inject
, has a parameter annotated @Disposes
, or has a parameter annotated @Observes
, the container automatically detects the problem and treats it as a definition error.
Interceptors and decorators may not declare producer methods. If an interceptor or decorator has a method annotated @Produces
, the container automatically detects the problem and treats it as a definition error.
A producer method may have any number of parameters. All producer method parameters are injection points.
public class OrderFactory {
@Produces @ConversationScoped
public Order createCurrentOrder(Shop shop, @Selected Product product) {
Order order = new Order(product, shop);
return order;
}
}
3.2.3. Specializing a producer method
aa) If a producer method X is annotated @Specializes, then it must be non-static and directly override another producer method Y. Then X directly specializes Y, as defined in Section 4.3 "Specialization".
- ProducerMethodSpecializationTest.testSpecializingProducerMethod()
ba) If a producer method is static, the container automatically detects the problem and treats it as a definition error.
- SpecializesStaticMethodTest.testSpecializedStaticMethod()
ca) If a producer method does not directly override another producer method, the container automatically detects the problem and treats it as a definition error.
- IndirectOverrideTest.testSpecializedMethodIndirectlyOverridesAnotherProducerMethod()
If a producer method X is annotated @Specializes
, then it must be non-static and directly override another producer method Y. Then X directly specializes Y, as defined in Specialization.
If the method is static or does not directly override another producer method, the container automatically detects the problem and treats it as a definition error.
@Mock
public class MockShop extends Shop {
@Override @Specializes
@Produces
PaymentProcessor getPaymentProcessor() {
return new MockPaymentProcessor();
}
@Override @Specializes
@Produces
List<Product> getProducts() {
return PRODUCTS;
}
...
}
3.2.4. Default bean name for a producer method
The default name for a producer method is the method name, unless the method follows the JavaBeans property getter naming convention, in which case the default name is the JavaBeans property name
a) Test default name is the method name.
- ProducerMethodWithDefaultNameTest.testMethodName()
b) Test default name is the JavaBeans property name.
- ProducerMethodWithDefaultNameTest.testJavaBeansPropertyName()
The default name for a producer method is the method name, unless the method follows the JavaBeans property getter naming convention, in which case the default name is the JavaBeans property name.
For example, this producer method is named products
:
@Produces @Named
public List<Product> getProducts() { ... }
This producer method is named paymentProcessor
:
@Produces @Named
public PaymentProcessor paymentProcessor() { ... }
3.3. Producer fields
a) A producer field must be a default-access, public, protected or private, field of a managed bean class
- EnterpriseProducerFieldDefinitionTest.testStaticProducerField()
- ProducerFieldLifecycleTest.testProducerFieldNotAnotherBean()
b) A producer field may be static.
- ProducerFieldLifecycleTest.testProducerStaticFieldBean()
c) A producer field may be non-static.
- ProducerFieldDefinitionTest.testBeanDeclaresMultipleProducerFields()
d) If a producer field sometimes contains a null value when accessed, then the producer field must have scope @Dependent
- ProducerFieldLifecycleTest.testProducerFieldReturnsNullIsDependent()
e) If a producer field contains a null value at runtime, and the producer field declares any other scope, an IllegalProductException is thrown by the container. This restriction allows the container to use a client proxy, as defined in Section 5.4, "Client proxies"
- ProducerFieldLifecycleTest.testProducerFieldReturnsNullIsNotDependent()
fa) If the producer field type is a parameterized type, it must specify an actual type parameter or type variable for each type parameter
- ProducerFieldDefinitionTest.testParameterizedReturnType()
- ProducerFieldDefinitionTest.testProducerFieldWithTypeVariable()
fb) If the producer field type is a parameterized type, it must specify an actual type parameter or type variable for each type parameter
- ProducerFieldDefinitionTest.testParameterizedReturnType()
- ProducerFieldDefinitionTest.testProducerFieldWithTypeVariable()
ga) If a producer field type contains a wildcard type parameter the container automatically detects the problem and treats it as a definition error.
- ProducerFieldTypeWithWildcardTest.testProducerFieldTypeWithWildcard()
gc) If a producer field type is an array type whose component type contains a wildcard parameter the container automatically detects the problem and treats it as a definition error.
- ProducerFieldArrayWildcardTest.testBeanTypes()
gb) If the producer field type is a parameterized type with a type variable, it must have scope @Dependent. If a producer field with a parameterized type with a type variable declares any scope other than @Dependent, the container automatically detects the problem and treats it as a definition error.
- RequestScopedProducerFieldWithTypeVariableTest.testRequestScopedProducerFieldParameterizedWithTypeVariableNotAllowed()
ha) If a producer field type is a type variable the container automatically detects the problem and treats it as a definition error.
- ProducerFieldWithTypeVariableTest.testProducerFieldWithTypeOfTypeVariableNotAllowed()
hb) If a producer field type is an array type whose component type is a type variable the container automatically detects the problem and treats it as a definition error.
- ProducerFieldArrayTypeVariableTest.testBeanTypes()
i) The application may access producer fields directly. However, if the application accesses a producer field directly, the returned object is not bound to any context; and its lifecycle is not managed by the container
Note: This is a statement of intent
j) A bean may declare multiple producer fields
- ProducerFieldDefinitionTest.testBeanDeclaresMultipleProducerFields()
A producer field is a slightly simpler alternative to a producer method.
A producer field must be a default-access, public, protected or private, field of a managed bean class. A producer field may be either static or non-static.
If a producer field sometimes contains a null value when accessed, then the producer field must have scope @Dependent
. If a producer field contains a null value at runtime, and the producer field declares any other scope, an IllegalProductException
is thrown by the container. This restriction allows the container to use a client proxy, as defined in Client proxies.
If the producer field type is a parameterized type, it must specify an actual type parameter or type variable for each type parameter.
If a producer field type contains a wildcard type parameter or is an array type whose component type contains a wildcard parameter, the container automatically detects the problem and treats it as a definition error.
If the producer field type is a parameterized type with a type variable, it must have scope @Dependent
. If a producer field with a parameterized type with a type variable declares any scope other than @Dependent
, the container automatically detects the problem and treats it as a definition error.
If a producer field type is a type variable or is an array type whose component type is a type variable the container automatically detects the problem and treats it as a definition error.
The application may access producer fields directly. However, if the application accesses a producer field directly, the returned object is not bound to any context; and its lifecycle is not managed by the container.
A bean may declare multiple producer fields.
3.3.1. Bean types of a producer field
a) The bean types of a producer field depend upon the field type. If the field type is an interface, the unrestricted set of bean types contains the field type, all interfaces it extends directly or indirectly and java.lang.Object.
- ProducerFieldDefinitionTest.testApiTypeForInterfaceReturn()
The bean types of a producer field depend upon the field type. If a field type is primitive or is a Java array type, the unrestricted set of bean types contains exactly two types: the field type and java.lang.Object.
ba) Check primitive type
- ProducerFieldDefinitionTest.testApiTypeForPrimitiveReturn()
bb) Check array type
- ProducerFieldDefinitionTest.testApiTypeForArrayTypeReturn()
c) The bean types of a producer field depend upon the field type. If the field type is a class, the unrestricted set of bean types contains the field type, every superclass and all interfaces it implements directly or indirectly
- ProducerFieldDefinitionTest.testApiTypeForClassReturn()
The bean types of a producer field depend upon the field type:
-
If the field type is an interface, the unrestricted set of bean types contains the field type, all interfaces it extends directly or indirectly and
java.lang.Object
. -
If a field type is primitive or is a Java array type, the unrestricted set of bean types contains exactly two types: the field type and
java.lang.Object
. -
If the field type is a class, the unrestricted set of bean types contains the field type, every superclass and all interfaces it implements directly or indirectly.
Note the additional restrictions upon bean types of beans with normal scopes defined in Unproxyable bean types.
3.3.2. Declaring a producer field
a) A producer field may be declared by annotating a field with the @javax.enterprise.inject.Produces annotation.
- ProducerFieldDefinitionTest.testBeanDeclaresMultipleProducerFields()
b) A producer field may specify a scope.
- ProducerFieldDefinitionTest.testScopeType()
c) A producer field may specify a name.
- ProducerFieldDefinitionTest.testNamedField()
e) A producer field may specify stereotypes.
- ProducerFieldDefinitionTest.testStereotype()
f) A producer field may specify qualifiers.
- ProducerFieldDefinitionTest.testBindingType()
g) If a producer field is annotated @Inject, the container automatically detects the problem and treats it as a definition error.
- InjectAnnotatedProducerFieldTest.testInjectAnnotatedProducerFieldNotAllowed()
ia) Interceptors and decorators may not declare producer fields. If an interceptor or decorator has a field annotated @Produces, the container automatically detects the problem and treats it as a definition error.
- ProducerFieldOnInterceptorTest.testProducerFieldNotAllowedOnInterceptor()
- ProducerFieldOnDecoratorTest.testProducerFieldNotAllowedOnDecorator()
ib) Interceptors and decorators may not declare producer fields. If an interceptor or decorator has a field annotated @Produces, the container automatically detects the problem and treats it as a definition error.
- ProducerFieldOnInterceptorTest.testProducerFieldNotAllowedOnInterceptor()
- ProducerFieldOnDecoratorTest.testProducerFieldNotAllowedOnDecorator()
A producer field may be declared by annotating a field with the @javax.enterprise.inject.Produces
annotation.
public class Shop {
@Produces PaymentProcessor paymentProcessor = ....;
@Produces List<Product> products = ....;
}
A producer field may also specify scope, bean name, stereotypes and/or qualifiers.
public class Shop {
@Produces @ApplicationScoped @Catalog @Named("catalog")
List<Product> products = ....;
}
If a producer field is annotated @Inject
, the container automatically detects the problem and treats it as a definition error.
Interceptors and decorators may not declare producer fields. If an interceptor or decorator has a field annotated @Produces
, the container automatically detects the problem and treats it as a definition error.
3.3.3. Default bean name for a producer field
a) The default name for a producer field is the field name
- ProducerFieldDefinitionTest.testDefaultNamedByStereotype()
The default name for a producer field is the field name.
For example, this producer field is named products
:
@Produces @Named
public List<Product> products = ...;
3.4. Disposer methods
aa) A disposer method must be a default-access, public, protected or private, non-abstract method of a managed bean class.
- DisposalMethodDefinitionTest.testDisposalMethodOnNonBean()
b) A disposer method may be static.
- ProducerMethodDefinitionTest.testStaticDisposerMethod()
- DisposalMethodDefinitionTest.testBindingTypesAppliedToDisposalMethodParameters()
c) A disposer method may be non-static.
- DisposalMethodDefinitionTest.testBindingTypesAppliedToDisposalMethodParameters()
e) A bean may declare multiple disposer methods.
- DisposalMethodDefinitionTest.testBindingTypesAppliedToDisposalMethodParameters()
A disposer method allows the application to perform customized cleanup of an object returned by a producer method or producer field.
A disposer method must be a default-access, public, protected or private, non-abstract method of a managed bean class. A disposer method may be either static or non-static.
A bean may declare multiple disposer methods.
3.4.1. Disposed parameter of a disposer method
a) Each disposer method must have exactly one disposed parameter, of the same type as the corresponding producer method return type or producer field type.
- MultipleDisposeParametersDefinitionTest.testMultipleDisposeParameters()
- DisposedParameterPositionTest.testDisposedParameterPosition()
ba) When searching for disposer methods for a producer method or producer field the container considers the type and qualifiers of the disposed parameter. If a producer method or producer field declared by the same bean class is assignable to the disposed parameter, according to the rules of typesafe resolution defined in Section 5.2, "Typesafe resolution", the container must call this method when destroying any instance returned by that producer method or producer field.
- DisposalMethodDefinitionTest.testBindingTypesAppliedToDisposalMethodParameters()
- DisposalMethodDefinitionTest.testDisposalMethodOnNonBean()
- DisposesMethodCalledOnceTest.testDisposerCalledOnce1()
- DisposesMethodCalledOnceTest.testDisposerCalledOnce2()
- DisposesMethodCalledOnceTest.testDisposerCalledOnce3()
- DisposesMethodCalledOnceTest.testDisposerCalledOnce4()
- DisposesMethodCalledOnceTest.testDisposerCalledOnce5()
- DisposesMethodCalledOnceTest.testDisposerCalledOnce6()
da) A disposer method may resolve to multiple producer methods or producer fields declared by the bean class, in which case the container must call it when destroying any instance returned by any of these producer methods or producer fields.
- DisposalMethodDefinitionTest.testDisposalMethodForMultipleProducerMethods()
Each disposer method must have exactly one disposed parameter, of the same type as the corresponding producer method return type or producer field type. When searching for disposer methods for a producer method or producer field the container considers the type and qualifiers of the disposed parameter. If a producer method or producer field declared by the same bean class is assignable to the disposed parameter, according to the rules of typesafe resolution defined in Typesafe resolution, the container must call this method when destroying any instance returned by that producer method or producer field.
A disposer method may resolve to multiple producer methods or producer fields declared by the bean class, in which case the container must call it when destroying any instance returned by any of these producer methods or producer fields.
3.4.2. Declaring a disposer method
a) A disposer method may be declared by annotating a parameter @javax.enterprise.inject.Disposes. That parameter is the disposed parameter
- DisposalMethodDefinitionTest.testBindingTypesAppliedToDisposalMethodParameters()
ba) Qualifiers may be declared by annotating the disposed parameter.
- DisposalMethodDefinitionTest.testBindingTypesAppliedToDisposalMethodParameters()
bb) If a method has more than one parameter annotated @Disposes, the container automatically detects the problem and treats it as a definition error.
- MultipleDisposeParametersDefinitionTest.testMultipleDisposeParameters()
ca) If a disposer method is annotated @Produces, the container automatically detects the problem and treats it as a definition error.
- ProducesUnallowedDefinitionTest.testProducesUnallowed()
da) If a disposer method is annotated @Inject, the container automatically detects the problem and treats it as a definition error.
- InitializerUnallowedDefinitionTest.testInitializerUnallowed()
ea) If a disposer method has a parameter annotated @Observes, the container automatically detects the problem and treats it as a definition error.
- ObserverParameterUnallowedDefinitionTest.testObserverParameterUnallowed()
ga) Interceptors and decorators may not declare disposer methods. If an interceptor or decorator has a method annotated @Disposes, the container automatically detects the problem and treats it as a definition error.
- DisposerMethodOnInterceptorTest.testDisposerMethodNotAllowedOnInterceptor()
- DisposerMethodOnDecoratorTest.testDisposerMethodNotAllowedOnDecorator()
gb) Interceptors and decorators may not declare disposer methods. If an interceptor or decorator has a method annotated @Disposes, the container automatically detects the problem and treats it as a definition error.
- DisposerMethodOnInterceptorTest.testDisposerMethodNotAllowedOnInterceptor()
- DisposerMethodOnDecoratorTest.testDisposerMethodNotAllowedOnDecorator()
h) In addition to the disposed parameter, a disposer method may declare additional parameters, which may also specify qualifiers. These additional parameters are injection points.
- DisposalMethodDefinitionTest.testDisposalMethodParametersGetInjected()
- DisposedParameterPositionTest.testDisposedParameterPosition()
A disposer method may be declared by annotating a parameter @javax.enterprise.inject.Disposes
. That parameter is the disposed parameter. Qualifiers may be declared by annotating the disposed parameter:
public class UserDatabaseEntityManager {
@Produces @ConversationScoped @UserDatabase
public EntityManager create(EntityManagerFactory emf) {
return emf.createEntityManager();
}
public void close(@Disposes @UserDatabase EntityManager em) {
em.close();
}
}
public class Resources {
@PersistenceContext
@Produces @UserDatabase
private EntityManager em;
public void close(@Disposes @UserDatabase EntityManager em) {
em.close();
}
}
If a method has more than one parameter annotated @Disposes
, the container automatically detects the problem and treats it as a definition error.
If a disposer method is annotated @Produces
or @Inject
or has a parameter annotated @Observes
, the container automatically detects the problem and treats it as a definition error.
Interceptors and decorators may not declare disposer methods. If an interceptor or decorator has a method annotated @Disposes
, the container automatically detects the problem and treats it as a definition error.
In addition to the disposed parameter, a disposer method may declare additional parameters, which may also specify qualifiers. These additional parameters are injection points.
public void close(@Disposes @UserDatabase EntityManager em, Logger log) { ... }
3.4.3. Disposer method resolution
aa) A disposer method is bound to a producer method if the producer method is declared by the same bean class as the disposer method, and the producer method is assignable to the disposed parameter, according to the rules of typesafe resolution defined in Section 5.2, "Typesafe resolution".
- DisposalMethodDefinitionTest.testBindingTypesAppliedToDisposalMethodParameters()
ab) A disposer method is bound to a producer field if the producer field is declared by the same bean class as the disposer method, and the producer field is assignable to the disposed parameter, according to the rules of typesafe resolution defined in Section 5.2, "Typesafe resolution".
- DisposalMethodDefinitionTest.testDisposalMethodCalledForProducerField()
ba) If there are multiple disposer methods for a single producer method or producer field, the container automatically detects the problem and treats it as a definition error.
- MultipleDisposerMethodsForProducerMethodTest.testMultipleDisposerMethodsForProducerMethodNotAllowed()
ca) If there is no producer method or producer field declared by the bean class that is assignable to the disposed parameter of a disposer method, the container automatically detects the problem and treats it as a definition error.
- UnresolvedDisposalMethodDefinitionTest.testUnresolvedDisposalMethod()
A disposer method is bound to a producer method or producer field if:
-
the producer method or producer field is declared by the same bean class as the disposer method, and
-
the producer method or producer field is assignable to the disposed parameter, according to the rules of typesafe resolution defined in Typesafe resolution (using Assignability of raw and parameterized types).
If there are multiple disposer methods for a single producer method or producer field, the container automatically detects the problem and treats it as a definition error.
If there is no producer method or producer field declared by the bean class that is assignable to the disposed parameter of a disposer method, the container automatically detects the problem and treats it as a definition error.
3.5. Bean constructors
a) When the container instantiates a bean, it calls the bean constructor. The bean constructor is a default-access, public, protected or private constructor of the bean class.
- SimpleBeanDefinitionTest.testEmptyConstructorUsed()
When the container instantiates a bean class, it calls the bean constructor. The bean constructor is a default-access, public, protected or private constructor of the bean class.
The application may call bean constructors directly. However, if the application directly instantiates the bean, no parameters are passed to the constructor by the container; the returned object is not bound to any context; no dependencies are injected by the container; and the lifecycle of the new instance is not managed by the container.
3.5.1. Declaring a bean constructor
The bean constructor may be identified by annotating the constructor @Inject
aa) Test an @Inject constructor is used on a managed bean
- SimpleBeanDefinitionTest.testInitializerAnnotatedConstructorUsedOverEmptyConstuctor()
- SimpleBeanLifecycleTest.testCreateInjectsFieldsDeclaredInJava()
- SimpleBeanDefinitionTest.testInitializerAnnotatedConstructor()
ba) If a bean class does not explicitly declare a constructor using @Inject, the constructor that accepts no parameters is the bean constructor.
- SimpleBeanDefinitionTest.testEmptyConstructorUsed()
ca) If a bean class has more than one constructor annotated @Inject, the container automatically detects the problem and treats it as a definition error.
- TooManyInitializerAnnotatedConstructorsTest.testTooManyInitializerAnnotatedConstructor()
da) If a bean constructor has a parameter annotated @Disposes, the container automatically detects the problem and treats it as a definition error.
- ConstructorHasDisposesParameterTest.testConstructorHasDisposesParameter()
ea) If a bean constructor has a parameter annotated @Observes, the container automatically detects the problem and treats it as a definition error.
- ConstructorHasObservesParameterTest.testConstructorHasObservesParameter()
f) A bean constructor may have any number of parameters.
- SimpleBeanLifecycleTest.testInjectionOfParametersIntoBeanConstructor()
g) All parameters of a bean constructor are injection points.
- SimpleBeanLifecycleTest.testInjectionOfParametersIntoBeanConstructor()
- SimpleBeanLifecycleTest.testQualifierTypeAnnotatedConstructor()
The bean constructor may be identified by annotating the constructor @Inject
.
@SessionScoped
public class ShoppingCart implements Serializable {
private User customer;
@Inject
public ShoppingCart(User customer) {
this.customer = customer;
}
public ShoppingCart(ShoppingCart original) {
this.customer = original.customer;
}
ShoppingCart() {}
...
}
@ConversationScoped
public class Order {
private Product product;
private User customer;
@Inject
public Order(@Selected Product product, User customer) {
this.product = product;
this.customer = customer;
}
public Order(Order original) {
this.product = original.product;
this.customer = original.customer;
}
Order() {}
...
}
If a bean class does not explicitly declare a constructor using @Inject
, the constructor that accepts no parameters is the bean constructor.
If a bean class has more than one constructor annotated @Inject
, the container automatically detects the problem and treats it as a definition error.
If a bean constructor has a parameter annotated @Disposes
, or @Observes
, the container automatically detects the problem and treats it as a definition error.
A bean constructor may have any number of parameters. All parameters of a bean constructor are injection points.
3.6. Injected fields
An injected field is a non-static, non-final field of a bean class or of any other classes supporting injection.
a) Test a bean class.
- SimpleBeanLifecycleTest.testCreateInjectsFieldsDeclaredInJava()
An injected field is a non-static, non-final field of a bean class or of any other classes supporting injection.
3.6.1. Declaring an injected field
aa) An injected field may be declared by annotating the field @javax.inject.Inject.
- SimpleBeanLifecycleTest.testCreateInjectsFieldsDeclaredInJava()
b) If an injected field is annotated @Produces, the container automatically detects the problem and treats it as a definition error.
- InjectedFieldAnnotatedWithProducesTest.testDeployment()
An injected field may be declared by annotating the field @javax.inject.Inject
.
@ConversationScoped
public class Order {
@Inject @Selected Product product;
@Inject User customer;
}
If an injected field is annotated @Produces
, the container automatically detects the problem and treats it as a definition error.
3.7. Initializer methods
An initializer method is a default-access, public, protected or private, non-abstract, non-static, non-generic method of a bean class or of any other classes supporting injection.
a) Test a bean-class.
- InitializerMethodTest.testBindingTypeOnInitializerParameter()
f) Method interceptors are never called when the container calls an initializer method
- InterceptorInvocationTest.testInitializerMethodsNotIntercepted()
g) A bean class may declare multiple (or zero) initializer methods
- InitializerMethodTest.testMultipleInitializerMethodsAreCalled()
h) The application may call initializer methods directly, but then no parameters will be passed to the method by the container
Note: This is a statement of intent
An initializer method is a default-access, public, protected or private, non-abstract, non-static, non-generic method of a bean class or of any other classes supporting injection.
A bean class may declare multiple (or zero) initializer methods.
Method interceptors are never called when the container calls an initializer method.
The application may call initializer methods directly, but then no parameters will be passed to the method by the container.
3.7.1. Declaring an initializer method
a) An initializer method may be declared by annotating the method @javax.inject.Inject
- InitializerMethodTest.testMultipleInitializerMethodsAreCalled()
ab) If a generic method of a bean is annotated @Inject, the container automatically detects the problem and treats it as a definition error.
- GenericInitializerMethodTest.testGenericInitializerMethodNotAllowed()
ba) If an initializer method is annotated @Produces, the container automatically detects the problem and treats it as a definition error.
- InitializerMethodAnnotatedProducesTest.testInitializerMethodAnnotatedProduces()
ca) If an initializer method has a parameter annotated @Disposes, the container automatically detects the problem and treats it as a definition error.
- ParameterAnnotatedDisposesTest.testInitializerMethodHasParameterAnnotatedDisposes()
da) If an initializer method has a parameter annotated @Observes, the container automatically detects the problem and treats it as a definition error.
- ParameterAnnotatedObservesTest.testInitializerMethodHasParameterAnnotatedObserves()
e) An initializer method may have any number of parameters.
- InitializerMethodTest.testMultipleInitializerMethodsAreCalled()
f) All initializer method parameters are injection points.
- InitializerMethodTest.testBindingTypeOnInitializerParameter()
An initializer method may be declared by annotating the method @javax.inject.Inject
.
@ConversationScoped
public class Order {
private Product product;
private User customer;
@Inject
void setProduct(@Selected Product product) {
this.product = product;
}
@Inject
public void setCustomer(User customer) {
this.customer = customer;
}
}
If a generic method of a bean is annotated @Inject
, the container automatically detects the problem and treats it as a definition error.
If an initializer method is annotated @Produces
, has a parameter annotated @Disposes
, or has a parameter annotated @Observes
, the container automatically detects the problem and treats it as a definition error.
An initializer method may have any number of parameters. All initializer method parameters are injection points.
3.8. The default qualifier at injection points
a) If an injection point declares no qualifier, the injection point has exactly one qualifier, the default qualifier @Default.
- EventTest.testObserverMethodParameterInjectionPoints()
- InitializerMethodTest.testMultipleInitializerMethodsAreCalled()
- DisposalMethodDefinitionTest.testDisposalMethodParametersGetInjected()
If an injection point declares no qualifier, the injection point has exactly one qualifier, the default qualifier @Default
.
The following are equivalent:
@ConversationScoped
public class Order {
private Product product;
private User customer;
@Inject
public void init(@Selected Product product, User customer) {
this.product = product;
this.customer = customer;
}
}
@ConversationScoped
public class Order {
private Product product;
private User customer;
@Inject
public void init(@Selected Product product, @Default User customer) {
this.product = product;
this.customer = customer;
}
}
The following definitions are equivalent:
public class Payment {
public Payment(BigDecimal amount) { ... }
@Inject Payment(Order order) {
this(order.getAmount();
}
}
public class Payment {
public Payment(BigDecimal amount) { ... }
@Inject Payment(@Default Order order) {
this(order.getAmount();
}
}
Finally, the following are equivalent:
@Inject Order order;
@Inject @Default Order order;
3.9. The qualifier @Named
at injection points
a) If an injected field declares a @Named annotation that does not specify the value member, the name of the field is assumed.
- NamedAtInjectionPointTest.testFieldNameUsedAsBeanName()
b) If any other injection point declares a @Named annotation that does not specify the value member, the container automatically detects the problem and treats it as a definition error.
- NamedNonFieldInjectionPointTest.testNamedInitializerMethodInjectionPointNotAllowed()
- NamedNonFieldInjectionPointTest.testNamedProducerInjectionPointNotAllowed()
- NamedNonFieldInjectionPointTest.testNamedObserverMethodInjectionPointNotAllowed()
The use of @Named
as an injection point qualifier is not recommended, except in the case of integration with legacy code that uses string-based names to identify beans.
If an injected field declares a @Named
annotation that does not specify the value
member, the name of the field is assumed. For example, the following field has the qualifier @Named("paymentService")
:
@Inject @Named PaymentService paymentService;
If any other injection point declares a @Named
annotation that does not specify the value
member, the container automatically detects the problem and treats it as a definition error.
3.10. @New
qualified beans
d) For each managed bean, a second bean exists which has the same bean class.
- NewSimpleBeanTest.testForEachSimpleBeanANewBeanExists()
e) For each managed bean, a second bean exists which has the same bean types.
- NewSimpleBeanTest.testNewBeanHasTheSameBeanTypes()
f) For each managed bean, a second bean exists which has the same bean constructor.
- NewSimpleBeanTest.testNewBeanHasSameConstructor()
g) For each managed bean, a second bean exists which has the same initializer methods.
- NewSimpleBeanTest.testNewBeanHasSameInitializers()
h) For each managed bean, a second bean exists which has the same injected fields.
- NewSimpleBeanTest.testNewBeanHasSameInjectedFields()
i) For each managed bean, a second bean exists which has the same interceptor bindings.
- NewSimpleBeanTest.testNewBeanHasTheSameInterceptorBindings()
p) This second bean has scope @Dependent.
r) This second bean has exactly one qualifier: @javax.enterprise.inject.New(X.class) where x is the bean class.
s) This second bean has no bean name.
t) This second bean has no stereotypes.
- NewSimpleBeanTest.testNewBeanHasNoStereotypes()
u) This second bean has no observer methods.
- NewSimpleBeanTest.testNewBeanHasNoObservers()
v) This second bean has no producer methods.
- NewSimpleBeanTest.testNewBeanHasNoProducerMethods()
w) This second bean has no producer fields.
- NewSimpleBeanTest.testNewBeanHasNoProducerFields()
x) This second bean has no disposer methods.
- NewSimpleBeanTest.testNewBeanHasNoDisposerMethods()
xb) This second bean is not an alternative.
- NewSimpleBeanTest.testNewBeanIsNotAlternative()
xc) This second bean is enabled, in the sense of Section 5.1.2, "Enabled and disabled beans", if and only if some other enabled bean has an injection point with the qualifier @New(X.class) where X is the bean class.
- DynamicLookupTest.testNewBeanNotEnabledWithouInjectionPoint()
xd) This bean is called the @New qualified bean for the class X.
Note that this second bean exists, and may be enabled and available for injection even if the first bean is disabled, as defined by Section 5.1.2, “Enabled and disabled beans” or if the bean class is deployed outside of a bean deployment archive, as defined in Section 12.1, “Bean deployment archives”, and is therefore not discovered during the bean discovery process defined in Chapter 12, Packaging and deployment. The container discovers @New qualified beans by inspecting injection points of other enabled beans.
ya) Check that @New on a field injection point outside the BDA, but in the classpath causes a bean with qualifier @New and the given type to be created
- NewSimpleBeanTest.testNewBeanCreatedForFieldInjectionPoint()
yc) Check that @New on a initializer method injection point outside the BDA, but in the classpath causes a bean with qualifier @New and the given type to be created
- NewSimpleBeanTest.testNewBeanCreatedForInitializerInjectionPoint()
ye) Check that @New on a constructor injection point outside the BDA, but in the classpath causes a bean with qualifier @New and the given type to be created
- NewSimpleBeanTest.testNewBeanCreatedForConstructorInjectioAnPoint()
yg) Check that @New on a producer method injection point outside the BDA, but in the classpath causes a bean with qualifier @New and the given type to be created
- NewSimpleBeanTest.testNewBeanCreatedForProducerMethod()
yi) Check that @New on a observer method injection point outside the BDA, but in the classpath causes a bean with qualifier @New and the given type to be created
- NewSimpleBeanTest.testNewBeanCreatedForObserverMethod()
yk) Check that @New on a disposer method injection point outside the BDA, but in the classpath causes a bean with qualifier @New and the given type to be created
- NewSimpleBeanTest.testNewBeanCreatedForDisposerMethod()
z) When the qualifier @New is specified at an injection point and no value member is explicitly specified, the container defaults the value to the declared type of the injection point.
- NewSimpleBeanTest.testNewBeanWithNoMemberValue()
The @New qualifier was deprecated in CDI 1.1. CDI applications are encouraged to inject @Dependent scoped beans instead.
For each managed bean, a second bean exists which:
-
has the same bean class,
-
has the same bean types,
-
has the same bean constructor, initializer methods and injected fields, and
-
has the same interceptor bindings.
However, this second bean:
-
has scope
@Dependent
, -
has exactly one qualifier:
@javax.enterprise.inject.New(X.class)
whereX
is the bean class, -
has no bean name,
-
has no stereotypes,
-
has no observer methods, producer methods or fields or disposer methods, and
-
is not an alternative, and
-
is enabled, in the sense of Enabled and disabled beans, if and only if some other enabled bean has an injection point with the qualifier
@New(X.class)
whereX
is the bean class.
This bean is called the @New qualified bean for the class X
.
Note that this second bean exists - and may be enabled and available for injection - even if the first bean is disabled, as defined by Enabled and disabled beans, or if the bean class is deployed outside of a bean archive, as defined in Bean archives, and is therefore not discovered during the bean discovery process defined in Packaging and deployment. The container discovers @New
qualified beans by inspecting injection points of other enabled beans.
This allows the application to obtain a new instance of a bean which is not bound to the declared scope, but has had dependency injection performed.
@Produces @ConversationScoped
@Special Order getSpecialOrder(@New(Order.class) Order order) {
...
return order;
}
When the qualifier @New
is specified at an injection point and no value
member is explicitly specified, the container defaults the value
to the declared type of the injection point. So the following injection point has qualifier @New(Order.class)
:
@Produces @ConversationScoped
@Special Order getSpecialOrder(@New Order order) { ... }
3.11. Unproxyable bean types
Certain legal bean types cannot be proxied by the container. If an injection point whose declared type cannot be proxied by the container resolves to a bean with a normal scope, the container automatically detects the problem and treats it as a deployment problem.
aa) Test a class which doesn't have a non-private constructor with no parameters.
- BeanConstructorWithParametersTest.testDeployment()
- PrivateConstructorTest.testClassWithPrivateConstructor()
baa) Test a class which is declared final.
- AddingNormalScopeTest.testAddingScopeType()
- FinalClassTest.testInjectionPointWithUnproxyableTypeWhichResolvesToNormalScopedBean()
bba) Test a class that has non-static, final method with public visibility.
- NonPrivateNonStaticMethodTest.testClassWithPublicFinalMethodCannotBeProxied()
bbb) Test a class that has non-static, final method with public visibility declared on a superclass.
- NonPrivateNonStaticSuperclassMethodTest.testClassWithPublicFinalMethodCannotBeProxied()
bca) Test with a class that has static final method with public visibility.
- StaticFinalMethodTest.testClassWithStaticFinalMethodCanBeProxied()
bda) Test a class that has final method with private visibility.
- PrivateFinalMethodTest.testClassWithPrivateFinalMethodCanBeProxied()
ca) Test primitive type.
- UnproxyableTest.testInjectionPointWithUnproxyableTypeWhichResolvesToNormalScopedBean()
da) Test array type.
- ArrayTest.testInjectionPointWithArrayType()
A bean type must be proxyable if an injection point resolves to a bean:
ea) That has an associated decorator.
- DecoratoredBeanProxyTest.testClientProxyBeanWithAssociatedDecorator()
eb) That has a bound interceptor.
- InterceptedBeanProxyTest.testClientProxyBeanWithBoundInterceptor()
The container uses proxies to provide certain functionality. Certain legal bean types cannot be proxied by the container:
-
classes which don’t have a non-private constructor with no parameters,
-
classes which are declared final,
-
classes which have non-static, final methods with public, protected or default visibility,
-
primitive types,
-
and array types.
A bean type must be proxyable if an injection point resolves to a bean:
-
that requires a client proxy, or
-
that has an associated decorator, or
-
that has a bound interceptor.
Otherwise, the container automatically detects the problem, and treats it as a deployment problem.
4. Inheritance and specialization
A bean may inherit type-level metadata and members from its superclasses.
Inheritance of type-level metadata by beans from their superclasses is controlled via use of the Java @Inherited
meta-annotation. Type-level metadata is never inherited from interfaces implemented by a bean.
Member-level metadata is not inherited. However, injected fields, initializer methods, lifecycle callback methods and non-static observer methods are inherited by beans from their superclasses.
The implementation of a bean may be extended by the implementation of a second bean. This specification recognizes two distinct scenarios in which this situation occurs:
-
The second bean specializes the first bean in certain deployment scenarios. In these deployments, the second bean completely replaces the first, fulfilling the same role in the system.
-
The second bean is simply reusing the Java implementation, and otherwise bears no relation to the first bean. The first bean may not even have been designed for use as a contextual object.
The two cases are quite dissimilar.
By default, Java implementation reuse is assumed. In this case, the two beans have different roles in the system, and may both be available in a particular deployment.
The bean developer may explicitly specify that the second bean specializes the first. Then the second bean inherits, and may not override, the qualifiers and bean name of the first bean. The second bean is able to serve the same role in the system as the first. In a particular deployment, only one of the two beans may fulfill that role.
4.1. Inheritance of type-level metadata
Suppose a class X is extended directly or indirectly by the bean class of a managed bean Y. If X is annotated with a qualifier type, stereotype or interceptor binding type Z then Y inherits the annotation if and only if Z declares the @Inherited meta-annotation and neither Y nor any intermediate class that is a subclass of X and a superclass of Y declares an annotation of type Z.
aa) Test qualifier type for directly extended managed bean annotated @Inherited is inherited.
- QualifierInheritedTest.testResolution()
- QualifierDefinitionTest.testQualifierDeclaredInheritedIsInherited()
- QualifierDefinitionTest.testQualifierDeclaredInheritedIsBlockedByIntermediateClass()
aaa) Test qualifier type for directly extended managed bean not annotated @Inherited is not inherited.
- QualifierNotInheritedTest.testResolution()
- QualifierDefinitionTest.testQualifierNotDeclaredInheritedIsNotInherited()
ab) Test stereotype for directly extended managed bean annotated @Inherited is inherited.
- ScopeDefinitionTest.testWebBeanScopeTypeOverridesStereotype()
- StereotypeDefinitionTest.testStereotypeDeclaredInheritedIsInherited()
aba) Test stereotype for directly extended managed bean not annotated @Inherited is not inherited.
- StereotypeDefinitionTest.testStereotypeNotDeclaredInheritedIsNotInherited()
ad) Test interceptor binding type for directly extended managed bean annotated @Inherited is inherited.
- InterceptorBindingInheritanceTest.testInterceptorBindingDirectlyInheritedFromManagedBean()
ada) Test interceptor binding type for directly extended managed bean not annotated @Inherited is not inherited.
- InterceptorBindingInheritanceTest.testInterceptorBindingDirectlyInheritedFromManagedBean()
ag) Test qualifier type for indirectly extended managed bean annotated @Inherited is inherited.
- QualifierDefinitionTest.testQualifierDeclaredInheritedIsIndirectlyInherited()
aga) Test qualifier type for indirectly extended managed bean not annotated @Inherited is not inherited.
- QualifierDefinitionTest.testQualifierNotDeclaredInheritedIsNotIndirectlyInherited()
ah) Test stereotype for indirectly extended managed bean annotated @Inherited is inherited.
- StereotypeDefinitionTest.testStereotypeDeclaredInheritedIsIndirectlyInherited()
aha) Test stereotype for indirectly extended managed bean not annotated @Inherited is not inherited.
- StereotypeDefinitionTest.testStereotypeNotDeclaredInheritedIsNotIndirectlyInherited()
aj) Test interceptor binding type for indirectly extended managed bean annotated @Inherited is inherited.
- InterceptorBindingInheritanceTest.testInterceptorBindingIndirectlyInheritedFromManagedBean()
aja) Test interceptor binding type for indirectly extended managed bean not annotated @Inherited is not inherited.
- InterceptorBindingInheritanceTest.testInterceptorBindingIndirectlyInheritedFromManagedBean()
Suppose a class X is extended directly or indirectly by the bean class of a managed bean Y. If X is annotated with a scope type Z then Y inherits the annotation if and only if Z declares the @Inherited meta-annotation and neither Y nor any intermediate class that is a subclass of X and a superclass of Y declares a scope type.
ba) Test scope type for directly extended managed bean annotated @Inherited is inherited.
- ScopeDefinitionTest.testScopeTypeDeclaredInheritedIsInherited()
- ScopeDefinitionTest.testScopeTypeDeclaredInheritedIsBlockedByIntermediateScopeTypeMarkedInherited()
- ScopeDefinitionTest.testScopeTypeDeclaredInheritedIsBlockedByIntermediateScopeTypeNotMarkedInherited()
baa) Test scope type for directly extended managed bean not annotated @Inherited is not inherited.
- ScopeDefinitionTest.testScopeTypeNotDeclaredInheritedIsNotInherited()
bc) Test scope type for indirectly extended managed bean annotated @Inherited is inherited.
- ScopeDefinitionTest.testScopeTypeDeclaredInheritedIsIndirectlyInherited()
bca) Test scope type for indirectly extended managed bean not annotated @Inherited is not inherited.
- ScopeDefinitionTest.testScopeTypeNotDeclaredInheritedIsNotIndirectlyInherited()
hhh) For class X which is extended directly by the bean class of a managed bean Y, a scope type explicitly declared by X and inherited by Y from X takes precedence over default scopes of stereotypes declared or inherited by Y.
- StereotypeDefinitionTest.testStereotypeScopeIsOverriddenByInheritedScope()
hhi) For class X which is extended indirectly by the bean class of a managed bean Y, a scope type explicitly declared by X and inherited by Y from X takes precedence over default scopes of stereotypes declared or inherited by Y.
- StereotypeDefinitionTest.testStereotypeScopeIsOverriddenByIndirectlyInheritedScope()
i) For annotations defined by the bean specification, all built-in scope types are declared @Inherited
Note: sigtest
j) For annotations defined by the bean specification, all built-in stereotypes are declared @Inherited
Note: sigtest
k) For annotations defined by the bean specification, no built-in qualifier type is declared @Inherited
Note: sigtest
m) The @Named annotation is not declared @Inherited and bean names are not inherited unless specialization is used
Note: sigtest
Suppose a class X is extended directly or indirectly by the bean class of a managed bean Y.
-
If X is annotated with a qualifier type, stereotype or interceptor binding type Z then Y inherits the annotation if and only if Z declares the
@Inherited
meta-annotation and neither Y nor any intermediate class that is a subclass of X and a superclass of Y declares an annotation of type Z. (This behavior is defined by the Java Language Specification.) -
If X is annotated with a scope type Z then Y inherits the annotation if and only if Z declares the
@Inherited
meta-annotation and neither Y nor any intermediate class that is a subclass of X and a superclass of Y declares a scope type. (This behavior is different to what is defined in the Java Language Specification.)
A scope type explicitly declared by X and inherited by Y from X takes precedence over default scopes of stereotypes declared or inherited by Y.
For annotations defined by the application or third-party extensions, it is recommended that:
-
scope types should be declared
@Inherited
, -
qualifier types should not be declared
@Inherited
, -
interceptor binding types should be declared
@Inherited
, and -
stereotypes may be declared
@Inherited
, depending upon the semantics of the stereotype.
All scope types, qualifier types, and interceptor binding types defined by this specification adhere to these recommendations.
The stereotypes defined by this specification are not declared @Inherited
.
However, in special circumstances, these recommendations may be ignored.
Note that the @Named
annotation is not declared @Inherited
and bean names are not inherited unless specialization is used.
4.2. Inheritance of member-level metadata
Suppose a class X is extended directly or indirectly by the bean class of a managed bean. If X declares an injected field x then Y inherits x.
aa) Check managed bean X directly extends managed bean Y
- InjectionTest.testInjectionFieldsAndInitializerMethods()
- SimpleBeanLifecycleTest.testSubClassInheritsPostConstructOnSuperclass()
- SimpleBeanLifecycleTest.testSubClassDoesNotInheritPostConstructOnSuperclassBlockedByIntermediateClass()
- SimpleBeanLifecycleTest.testSubClassInheritsPreDestroyOnSuperclass()
- SimpleBeanLifecycleTest.testSubClassDoesNotInheritPreDestroyConstructOnSuperclassBlockedByIntermediateClass()
- ObserverInheritanceTest.testNonStaticObserverMethodInherited()
- EventTest.testNonStaticObserverMethodInherited()
- InitializerMethodInheritanceTest.testManagedBeanDirectlyInheritsInitializer()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingDirectlyInheritedFromManagedBean()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingDirectlyNotInheritedFromManagedBean()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInheritedBySpecializingSubclass()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInherited()
- DisposerMethodInheritanceTest.testManagedBeanDisposerMethodNotInherited()
- ProducerFieldDefinitionTest.testNonStaticProducerFieldNotInherited()
ac) Check managed bean X indirectly extends managed bean Y
- InjectionTest.testFieldDeclaredInIndirectSuperclassInjected()
- SimpleBeanLifecycleTest.testIndirectSubClassInheritsPostConstructOnSuperclass()
- SimpleBeanLifecycleTest.testIndirectSubClassInheritsPreDestroyOnSuperclass()
- EventTest.testNonStaticObserverMethodIndirectlyInherited()
- ObserverInheritanceTest.testNonStaticObserverMethodInherited()
- InitializerMethodInheritanceTest.testManagedBeanIndirectlyInheritsInitializer()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingIndirectlyInheritedFromManagedBean()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingIndirectlyNotInheritedFromManagedBean()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInherited()
- DisposerMethodInheritanceTest.testManagedBeanDisposerMethodNotInherited()
- ProducerFieldDefinitionTest.testNonStaticProducerFieldNotIndirectlyInherited()
Suppose a class X is extended directly or indirectly by the bean class of a managed bean Y. If X declares an initializer, non-static observer, @PostConstruct or @PreDestroy method x() then Y inherits x() if and only if neither Y nor any intermediate class that is a subclass of X and a superclass of Y overrides the method x().
baa) Check managed bean X directly extends managed bean Y with @PostConstruct
- SimpleBeanLifecycleTest.testSubClassInheritsPostConstructOnSuperclass()
- SimpleBeanLifecycleTest.testSubClassDoesNotInheritPostConstructOnSuperclassBlockedByIntermediateClass()
bac) Check managed bean X indirectly extends managed bean Y with @PostConstruct
- SimpleBeanLifecycleTest.testIndirectSubClassInheritsPostConstructOnSuperclass()
bba) Check managed bean X directly extends managed bean Y with @PostDestroy
- SimpleBeanLifecycleTest.testSubClassInheritsPreDestroyOnSuperclass()
- SimpleBeanLifecycleTest.testSubClassDoesNotInheritPreDestroyConstructOnSuperclassBlockedByIntermediateClass()
bbc) Check managed bean X indirectly extends managed bean Y with @PostDestroy
- SimpleBeanLifecycleTest.testIndirectSubClassInheritsPreDestroyOnSuperclass()
dc) Check managed bean X directly extends managed bean Y with a non-static observer method
- ObserverInheritanceTest.testNonStaticObserverMethodInherited()
- EventTest.testNonStaticObserverMethodInherited()
di) Check managed bean X indirectly extends managed bean Y with a non-static observer method
- EventTest.testNonStaticObserverMethodIndirectlyInherited()
- ObserverInheritanceTest.testNonStaticObserverMethodInherited()
dm) Check managed bean X directly extends managed bean Y with a initializer method
- InitializerMethodInheritanceTest.testManagedBeanDirectlyInheritsInitializer()
do) Check managed bean X indirectly extends managed bean Y with a initializer method
- InitializerMethodInheritanceTest.testManagedBeanIndirectlyInheritsInitializer()
Suppose a class X is extended directly or indirectly by the bean class of a managed bean. If X declares a non-static method x() annotated with an interceptor binding type Z then Y inherits the binding if and only if neither Y nor any intermediate class that is a subclass of X and a superclass of Y overrides the method x().
ka) Check managed bean X directly extends managed bean Y
- InjectionTest.testInjectionFieldsAndInitializerMethods()
- SimpleBeanLifecycleTest.testSubClassInheritsPostConstructOnSuperclass()
- SimpleBeanLifecycleTest.testSubClassDoesNotInheritPostConstructOnSuperclassBlockedByIntermediateClass()
- SimpleBeanLifecycleTest.testSubClassInheritsPreDestroyOnSuperclass()
- SimpleBeanLifecycleTest.testSubClassDoesNotInheritPreDestroyConstructOnSuperclassBlockedByIntermediateClass()
- ObserverInheritanceTest.testNonStaticObserverMethodInherited()
- EventTest.testNonStaticObserverMethodInherited()
- InitializerMethodInheritanceTest.testManagedBeanDirectlyInheritsInitializer()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingDirectlyInheritedFromManagedBean()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingDirectlyNotInheritedFromManagedBean()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInheritedBySpecializingSubclass()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInherited()
- DisposerMethodInheritanceTest.testManagedBeanDisposerMethodNotInherited()
- ProducerFieldDefinitionTest.testNonStaticProducerFieldNotInherited()
kc) Check managed bean X indirectly extends managed bean Y
- InjectionTest.testFieldDeclaredInIndirectSuperclassInjected()
- SimpleBeanLifecycleTest.testIndirectSubClassInheritsPostConstructOnSuperclass()
- SimpleBeanLifecycleTest.testIndirectSubClassInheritsPreDestroyOnSuperclass()
- EventTest.testNonStaticObserverMethodIndirectlyInherited()
- ObserverInheritanceTest.testNonStaticObserverMethodInherited()
- InitializerMethodInheritanceTest.testManagedBeanIndirectlyInheritsInitializer()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingIndirectlyInheritedFromManagedBean()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingIndirectlyNotInheritedFromManagedBean()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInherited()
- DisposerMethodInheritanceTest.testManagedBeanDisposerMethodNotInherited()
- ProducerFieldDefinitionTest.testNonStaticProducerFieldNotIndirectlyInherited()
Suppose a class X is extended directly or indirectly by the bean class of a managed bean Y. If X declares a non-static producer or disposer method x() then Y does not inherit this method.
da) Check managed bean X directly extends managed bean Y with a non-static producer method
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInheritedBySpecializingSubclass()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInherited()
db) Check managed bean X directly extends managed bean Y with a non-static disposer method
- DisposerMethodInheritanceTest.testManagedBeanDisposerMethodNotInherited()
dg) Check managed bean X indirectly extends managed bean Y with a non-static producer method
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInherited()
dh) Check managed bean X indirectly extends managed bean Y with a non-static disposer method
- DisposerMethodInheritanceTest.testManagedBeanDisposerMethodNotInherited()
Suppose a class X is extended directly or indirectly by the bean class of a managed bean or session bean Y. If X declares a non-static producer field x then Y does not inherit this field.
ea) Check managed bean X directly extends managed bean Y
- InjectionTest.testInjectionFieldsAndInitializerMethods()
- SimpleBeanLifecycleTest.testSubClassInheritsPostConstructOnSuperclass()
- SimpleBeanLifecycleTest.testSubClassDoesNotInheritPostConstructOnSuperclassBlockedByIntermediateClass()
- SimpleBeanLifecycleTest.testSubClassInheritsPreDestroyOnSuperclass()
- SimpleBeanLifecycleTest.testSubClassDoesNotInheritPreDestroyConstructOnSuperclassBlockedByIntermediateClass()
- ObserverInheritanceTest.testNonStaticObserverMethodInherited()
- EventTest.testNonStaticObserverMethodInherited()
- InitializerMethodInheritanceTest.testManagedBeanDirectlyInheritsInitializer()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingDirectlyInheritedFromManagedBean()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingDirectlyNotInheritedFromManagedBean()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInheritedBySpecializingSubclass()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInherited()
- DisposerMethodInheritanceTest.testManagedBeanDisposerMethodNotInherited()
- ProducerFieldDefinitionTest.testNonStaticProducerFieldNotInherited()
ec) Check managed bean X indirectly extends managed bean Y
- InjectionTest.testFieldDeclaredInIndirectSuperclassInjected()
- SimpleBeanLifecycleTest.testIndirectSubClassInheritsPostConstructOnSuperclass()
- SimpleBeanLifecycleTest.testIndirectSubClassInheritsPreDestroyOnSuperclass()
- EventTest.testNonStaticObserverMethodIndirectlyInherited()
- ObserverInheritanceTest.testNonStaticObserverMethodInherited()
- InitializerMethodInheritanceTest.testManagedBeanIndirectlyInheritsInitializer()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingIndirectlyInheritedFromManagedBean()
- InterceptorBindingInheritanceTest.testMethodInterceptorBindingIndirectlyNotInheritedFromManagedBean()
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInherited()
- DisposerMethodInheritanceTest.testManagedBeanDisposerMethodNotInherited()
- ProducerFieldDefinitionTest.testNonStaticProducerFieldNotIndirectlyInherited()
If X is a generic type, and an injection point or observer method declared by X is inherited by Y, and the declared type of the injection point, producer method, producer field, disposed para- meter or event parameter contains type variables declared by X, the type of the injection point, producer method, producer field, disposed parameter or event parameter inherited in Y is the declared type, after substitution of actual type arguments declared by Y or any intermediate class that is a subclass of X and a superclass of Y.
f) Check injection point
- MemberLevelInheritanceTest.testInjectionPointDefinition()
- MemberLevelInheritanceTest.testInjectionPoint()
g) check observer method
- MemberLevelInheritanceTest.testObserverResolution()
- MemberLevelInheritanceTest.testObserver()
Suppose a class X is extended directly or indirectly by the bean class of a managed bean Y.
-
If X declares an injected field
x
then Y inheritsx
. (This behavior is defined by the Common Annotations for the Java Platform specification.) -
If X declares an initializer, non-static observer,
@PostConstruct
or@PreDestroy
methodx()
then Y inheritsx()
if and only if neither Y nor any intermediate class that is a subclass of X and a superclass of Y overrides the methodx()
. (This behavior is defined by the Common Annotations for the Java Platform specification.) -
If X declares a non-static method
x()
annotated with an interceptor binding type Z then Y inherits the binding if and only if neither Y nor any intermediate class that is a subclass of X and a superclass of Y overrides the methodx()
. (This behavior is defined by the Common Annotations for the Java Platform specification.) -
If X declares a non-static producer or disposer method
x()
then Y does not inherit this method. (This behavior is different to what is defined in the Common Annotations for the Java Platform specification.) -
If X declares a non-static producer field
x
then Y does not inherit this field. (This behavior is different to what is defined in the Common Annotations for the Java Platform specification.)
If X is a generic type, and an injection point or observer method declared by X is inherited by Y, and the declared type of the injection point or event parameter contains type variables declared by X, the type of the injection point or event parameter inherited in Y is the declared type, after substitution of actual type arguments declared by Y or any intermediate class that is a subclass of X and a superclass of Y.
For example, the bean DaoClient
has an injection point of type Dao<T>
.
public class DaoClient<T> {
@Inject Dao<T> dao;
...
}
This injection point is inherited by UserDaoClient
, but the type of the inherited injection point is Dao<User>
.
public class UserDaoClient
extends DaoClient<User> { ... }
4.3. Specialization
a) If two beans both support a certain bean type, and share at least one qualifier, then they are both eligible for injection to any injection point with that declared type and qualifier.
When an enabled bean specializes a second bean, we can be certain that the second bean is never instantiated or called by the container. Even if the second bean defines a producer or observer method, the method will never be called.
ca) The second bean is never instantiated.
- SpecializationTest.testProcessBeanAttributesFiredProperlyForSpecializedBean()
- Specialization03Test.testEnabledAlternativeSpecializes()
- Specialization02Test.testEnabledAlternativeSpecializes()
- VetoTest.testSpecializedBeanAvailableAfterSpecializingBeanVetoed()
- Specialization05Test.testEnabledAlternativeSpecializes()
cb) Producer method on specialized bean is not called.
- ProducerMethodDefinitionTest.testNonStaticProducerMethodNotInheritedBySpecializingSubclass()
- Specialization04Test.testEnabledAlternativeSpecializes()
- SimpleBeanSpecializationTest.testProducerMethodOnSpecializedBeanNotCalled()
- Specialization03Test.testEnabledAlternativeSpecializes()
- Specialization02Test.testEnabledAlternativeSpecializes()
- ProducerMethodLifecycleTest.testProducerMethodFromSpecializedBeanUsed()
- Specialization05Test.testEnabledAlternativeSpecializes()
cc) Observer method on specialized bean is not called.
- EventTest.testObserverCalledOnSpecializedBeanOnly()
- Specialization04Test.testEvent()
- Specialization03Test.testEvent()
- Specialization02Test.testEvent()
- Specialization05Test.testEvent()
cd) Producer field on specialized bean is not used.
- ProducerFieldLifecycleTest.testProducerFieldFromSpecializingBeanUsed()
If two beans both support a certain bean type, and share at least one qualifier, then they are both eligible for injection to any injection point with that declared type and qualifier.
Consider the following beans:
@Default @Asynchronous
public class AsynchronousService implements Service {
...
}
@Alternative
public class MockAsynchronousService extends AsynchronousService {
...
}
Suppose that the MockAsynchronousService
alternative is selected, as defined in Modularity:
@Alternative @Priority(APPLICATION+100)
public class MockAsynchronousService extends AsynchronousService {
...
}
Then, according to the rules of Unsatisfied and ambiguous dependencies, the following ambiguous dependency is resolvable, and so the attribute will receive an instance of MockAsynchronousService
:
@Inject Service service;
However, the following attribute will receive an instance of AsynchronousService
, even though MockAsynchronousService
is a selected alternative, because MockAsynchronousService
does not have the qualifier @Asynchronous
:
@Inject @Asynchronous Service service;
This is a useful behavior in some circumstances, however, it is not always what is intended by the developer.
The only way one bean can completely override a second bean at all injection points is if it implements all the bean types and declares all the qualifiers of the second bean. However, if the second bean declares a producer method or observer method, then even this is not enough to ensure that the second bean is never called!
To help prevent developer error, the first bean may:
-
directly extend the bean class of the second bean, or
-
directly override the producer method, in the case that the second bean is a producer method, and then
explicitly declare that it specializes the second bean.
@Alternative @Specializes
public class MockAsynchronousService extends AsynchronousService {
...
}
When an enabled bean, as defined in Enabled and disabled beans, specializes a second bean, we can be certain that the second bean is never instantiated or called by the container. Even if the second bean defines a producer or observer method, the method will never be called.
4.3.1. Direct and indirect specialization
ia) A bean X is said to specialize another bean Y if X directly specializes Y.
- SpecializationModularity04Test.testSpecialization()
- ProducerMethodSpecializationTest.testSpecializingProducerMethod()
- ProducerMethodSpecializationTest.testSpecializingBeanInjection()
- SimpleBeanSpecializationTest.testIndirectSpecialization()
- SimpleBeanSpecializationTest.testSpecializingBeanInjection()
- SpecializationModularity01Test.testSpecialization()
- SpecializationModularity02Test.testSpecialization()
ib) A bean X is said to specialize another bean Y if a bean Z exists, such that X directly specializes Z and Z specializes Y.
- SimpleBeanSpecializationTest.testIndirectSpecialization()
j) A bean X that specializes bean Y will include all qualifiers of Y, together with all qualifiers declared explicitly by X.
- ProducerMethodSpecializationTest.testSpecializingProducerMethod()
- SimpleBeanSpecializationTest.testSpecializingBeanHasQualifiersOfSpecializedAndSpecializingBean()
k) A bean X that specializes bean Y will have the same name as Y if Y has a name.
- ProducerMethodSpecializationTest.testSpecializingProducerMethod()
- SimpleBeanSpecializationTest.testSpecializingBeanHasNameOfSpecializedBean()
l) X must have all the bean types of Y. If X does not have some bean type of Y, the container automatically detects the problem and treats it as a definition error.
- TypeConflictDetectionTest.testDeployment()
- SessionBeanSpecializingSessionBeanWithClientViewTest.testDeployment()
- SpecializingBeanWithoutBeanTypeOfSpecializedBeanTest.testDeployment()
If Y has a bean name and X declares a bean name explicitly the container automatically detects the problem and treats it as a definition error.
la) Test that a specializing producer method with a name throws a definition exception.
- SpecializingAndSpecializedBeanHaveNameTest.testSpecializingAndSpecializedBeanHasName()
lb) Test that a specializing managed bean with a name throws a definition exception.
- SpecializingAndSpecializedBeanHasNameTest.testSpecializingAndSpecializedBeanHasName()
n) If an interceptor or decorator is annotated @Specializes, non-portable behavior results.
Note: Defines non-portable behavior
The annotation @javax.enterprise.inject.Specializes
is used to indicate that one bean directly specializes another bean, as defined in Specializing a managed bean and Specializing a producer method.
Formally, a bean X is said to specialize another bean Y if either:
-
X directly specializes Y, or
-
a bean Z exists, such that X directly specializes Z and Z specializes Y.
Then X will inherit the qualifiers and bean name of Y:
-
the qualifiers of X include all qualifiers of Y, together with all qualifiers declared explicitly by X, and
-
if Y has a bean name, the bean name of X is the same as the bean name of Y.
Furthermore, X must have all the bean types of Y. If X does not have some bean type of Y, the container automatically detects the problem and treats it as a definition error.
If Y has a bean name and X declares a bean name explicitly the container automatically detects the problem and treats it as a definition error.
For example, the following bean would have the inherited qualifiers @Default
and @Asynchronous
:
@Mock @Specializes
public class MockAsynchronousService extends AsynchronousService {
...
}
If AsynchronousService
declared a bean name:
@Default @Asynchronous @Named("asyncService")
public class AsynchronousService implements Service{
...
}
Then the bean name would also automatically be inherited by MockAsynchronousService
.
If an interceptor or decorator is annotated @Specializes
, non-portable behavior results.
5. Dependency injection and lookup
b) The container is required to support circularities in the bean dependency graph where at least one bean participating in every circular chain of dependencies has a normal scope, as defined in Section 6.3, "Normal scopes and pseudo-scopes".
- SessionBeanInjectionChainTest.testChainOfSessionBeans()
- CircularDependencyTest.testCircularInjectionOnTwoNormalBeans()
- CircularDependencyTest.testCircularInjectionOnOneNormalAndOneDependentBean()
- CircularDependencyTest.testNormalProducerMethodDeclaredOnNormalBeanWhichInjectsProducedBean()
- CircularDependencyTest.testNormalProducerMethodDeclaredOnDependentBeanWhichInjectsProducedBean()
- CircularDependencyTest.testNormalCircularConstructors()
- CircularDependencyTest.testNormalAndDependentCircularConstructors()
- CircularDependencyTest.testSelfConsumingConstructorsOnNormalBean()
c) The container is not required to support circular chains of dependencies where every bean participating in the chain has a pseudo-scope.
The container injects references to contextual instances to the following kinds of injection point:
-
Any injected field of a bean class
-
Any parameter of a bean constructor, bean initializer method, producer method or disposer method
-
Any parameter of an observer method, except for the event parameter
References to contextual instances may also be obtained by programmatic lookup.
In general, a bean type or bean name does not uniquely identify a bean. When resolving a bean at an injection point, the container considers bean type, qualifiers and selected alternatives. This allows bean developers to decouple type from implementation.
The container is required to support circularities in the bean dependency graph where at least one bean participating in every circular chain of dependencies has a normal scope, as defined in Normal scopes and pseudo-scopes. The container is not required to support circular chains of dependencies where every bean participating in the chain has a pseudo-scope.
5.1. Modularity
A bean packaged in a certain module is available for injection, lookup and name resolution to classes packaged in some other module if the bean class of the bean is required to be accessible to the other module by the class accessibility requirements of the module architecture.
aa) Test with injection.
- EnabledSessionBeanInjectionAvailability02Test.testInjection()
- SpecializationModularity04Test.testSpecialization()
- SpecializationModularity03Test.testSpecialization()
- SpecializationModularity06Test.testSpecialization()
- SpecializationModularity05Test.testSpecialization()
- EnabledSessionBeanInjectionAvailabilityTest.testInjection()
- SpecializationModularity01Test.testSpecialization()
- EnabledManagedBeanInjectionAvailability02Test.testInjection()
- EnabledManagedBeanInjectionAvailabilityTest.testInjection()
- SpecializationModularity02Test.testSpecialization()
- InterceptorModularityTest.testInterceptorEnvironment()
ab) Test with lookup.
- InterModuleLookupTest.testEnabledManagedBeanAvailableForInjection()
- InterModuleLookup02Test.testEnabledManagedBeanAvailableForInjection()
ac) Test with name resolution.
- InterModuleELResolutionTest.testEnabledManagedBeanAvailableForELResolution()
d) An alternative is never available for injection, lookup or name resolution in a module unless the module is a bean archive and the alternative is explicitly selected for the bean archive or the application..
Note: If a module/library is not BDA then no injection is possible at all
e) Nor is an alternative available for injection, lookup or name resolution in every bean deployment archive. An alternative must be explicitly selected in every bean deployment archive in which the alternative should be available for injection, lookup and name resolution.
- AlternativeAvailabilityTest.testAlternativeAvailability()
Beans and their clients may be deployed in modules in a module architecture. In a module architecture, certain modules are considered bean archives. The library is a bean archive if it contains a beans.xml
file, as defined in Bean archives.
A bean packaged in a certain module is available for injection, lookup and name resolution to classes packaged in some other module if and only if the bean class of the bean is required to be accessible to the other module by the class accessibility requirements of the module architecture.
An alternative is not available for injection, lookup or name resolution to classes in a module unless the module is a bean archive and the alternative is explicitly selected for the bean archive or the application.
5.1.1. Declaring selected alternatives
a) This specification defines two methods of selecting alternatives. From Contexts and Dependency Injection 1.1 onwards the @Priority annotation allows an alternative to be selected for an entire application. Contexts and Dependency Injection 1.0 allowed only for an alternative to be selected for a bean archive.
Note: Statement of intent.
This specification defines two methods of selecting alternatives. From Contexts and Dependency Injection 1.1 onwards the @Priority
annotation allows an alternative to be selected for an entire application. Contexts and Dependency Injection 1.0 allowed only for an alternative to be selected for a bean archive.
Declaring selected alternatives for an application
An alternative may be given a priority for the application by placing the @Priority annotation on the bean class of a managed bean.
aa) Test @Priority on the bean class of a managed bean.
- SelectedAlternative01Test.testAlternativeManagedBeanSelected()
- EnterpriseSelectedAlternative03Test.testAlternativeManagedBeanAvailable()
An alternative may be given a priority for the application by placing the @Priority annotation on the bean class that declares the producer method, field or resource.
ba) Test @Priority on the bean class of a producer method.
- SelectedAlternative01Test.testAlternativeProducerSelected()
- EnterpriseSelectedAlternative03Test.testAlternativeProducerSelected()
bb) Test @Priority on the bean class of a producer field.
- SelectedAlternative01Test.testAlternativeProducerSelected()
- EnterpriseSelectedAlternative03Test.testAlternativeProducerSelected()
bc) Test @Priority on the resource.
- ResourceAlternative01Test.testAlternativeResourceSelected()
An alternative may be given a priority for the application:
-
by placing the
@Priority
annotation on the bean class of a managed bean, or -
by placing the
@Priority
annotation on the bean class that declares the producer method, field or resource.
Declaring selected alternatives for a bean archive
a) An alternative may be explicitly declared using the <alternatives> element of the beans.xml file of the bean archive. The <alternative> element contains a list of bean classes and stereotypes.
Note: Statement of intent.
An alternative is selected for the bean archive if the alternative is a managed bean and the bean class of the bean is listed.
ba) Test selected managed bean.
- QualifierInheritedTest.testResolution()
- QualifierNotDeclaredTest.testResolution()
- AlternativeInLibraryWithExtensionTest.testAlternative()
- QualifierNotInheritedTest.testResolution()
- SelectedBeanWithUnselectedStereotypeTest.testSingleAlternativeIsSelected()
- AlternativeAvailabilityTest.testAlternativeAvailability()
An alternative is selected for the bean archive if the alternative is a producer method, field or resource, and the bean class that declares the method or field is listed.
ca) Test selected producer method.
- AlternativeAvailabilityTest.testProducerAlternativesOnMethodAndField()
cb) Test selected producer field.
- AlternativeAvailabilityTest.testProducerAlternativesOnMethodAndField()
cc) Test selected resource.
- ResourceAlternativeAvailabilityTest.testResourceAvailability()
d) An alternative is selected for the bean archive if any @Alternative stereotype of the alternative is listed.
- AlternativeAvailabilityTest.testAnyEnabledAlternativeStereotypeMakesAlternativeEnabled()
- AlternativeAvailabilityTest.testStereotypeAlternativeOnProducerMethodAndField()
e) Each child <class> element must specify the name of a bean class of an alternative bean. If there is no bean whose bean class has the specified name, or if no bean whose bean class has the specified name is an alternative, the container automatically detects the problem and treats it as a deployment problem.
- NoClassWithSpecifiedNameTest.test()
- ClassIsNotAlternativeTest.test()
f) Each child <stereotype> element must specify the name of a @Alternative stereotype annotation. If there is no annotation with the specified name, or the annotation is not a @Alternative stereotype, the container automatically detects the problem and treats it as a deployment problem.
- ClassIsNotAlternativeTest.test()
- NoAnnotationWithSpecifiedNameTest.test()
g) If the same type is listed twice under the <alternatives> element, the container automatically detects the problem and treats it as a deployment problem.
- SameTypeListedTwiceTest.test()
h) For a custom implementation of the Bean interface defined in Section "bean", the container calls isAlternative() to determine whether the bean is an alternative, and getBeanClass() and getStereotypes() to determine whether an alternative is selected in a certain bean deployment archive.
- CustomBeanImplementationTest.testGetBeanClassCalled()
- CustomBeanImplementationTest.testGetStereotypesCalled()
- CustomBeanImplementationTest.testIsPolicyCalled()
i) An alternative selected only for a specific bean archive is not selected for an application.
- Specialization03Test.testEnabledAlternativeSpecializes()
- Specialization02Test.testEnabledAlternativeSpecializes()
- WebArchiveModulesTest.testAlternatives()
- Specialization05Test.testEnabledAlternativeSpecializes()
An alternative may be explicitly declared using the <alternatives>
element of the beans.xml
file of the bean archive. The <alternatives>
element contains a list of bean classes and stereotypes. An alternative is selected for the bean archive if either:
-
the alternative is a managed bean and the bean class of the bean is listed,
-
the alternative is a producer method, field or resource, and the bean class that declares the method or field is listed, or
-
any
@Alternative
stereotype of the alternative is listed.
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">
<alternatives>
<class>com.acme.myfwk.InMemoryDatabase</class>
<stereotype>com.acme.myfwk.Mock</stereotype>
<stereotype>com.acme.site.Australian</stereotype>
</alternatives>
</beans>
Each child <class>
element must specify the name of a bean class of an alternative bean. If there is no bean whose bean class has the specified name, or if no bean whose bean class has the specified name is an alternative, the container automatically detects the problem and treats it as a deployment problem.
Each child <stereotype>
element must specify the name of an @Alternative
stereotype annotation. If there is no annotation with the specified name, or the annotation is not an @Alternative
stereotype, the container automatically detects the problem and treats it as a deployment problem.
If the same type is listed twice under the <alternatives>
element, the container automatically detects the problem and treats it as a deployment problem.
For a custom implementation of the Bean
interface defined in The Bean
interface, the container calls isAlternative()
to determine whether the bean is an alternative, and getBeanClass()
and getStereotypes()
to determine whether an alternative is selected in a certain bean archive.
5.1.2. Enabled and disabled beans
a) A bean is said to be enabled if it is deployed in a bean deployment archive, and it is not a producer method or field of a disabled bean, and it is not specialized by any other enabled bean, as defined in Section 4.3, "Specialization", and either it is not an alternative, or it is not an alternative, or it is a selected alternative of at least one bean archive or the application. Otherwise, the bean is said to be disabled.
Note: Tested in section inter_module_injection
A bean is said to be enabled if:
-
it is deployed in a bean archive, and
-
it is not a producer method or field of a disabled bean, and
-
it is not specialized by any other enabled bean, as defined in Specialization, and either
-
it is not an alternative, or it is a selected alternative of at least one bean archive or the application.
Otherwise, the bean is said to be disabled.
Note that @New
qualified beans defines a special rule that determines whether a @New
qualified bean is enabled or disabled. This rule applies as only to @New
qualified beans, as an exception to the normal rule defined here.
5.1.3. Inconsistent specialization
a) Suppose an enabled bean X specializes a second bean Y. If there is another enabled bean that specializes Y we say that inconsistent specialization exists. The container automatically detects inconsistent specialization and treats it as a deployment problem.
- SpecializationModularity07Test.testSpecialization()
- InconsistentSpecializationTest.testInconsistentSpecialization()
- TwoBeansSpecializeTheSameBeanTest.testTwoSessionBeansSpecializeTheSameBean()
- TwoBeansSpecializeTheSameBeanTest.testTwoBeansSpecializeTheSameBean()
Suppose an enabled bean X specializes a second bean Y. If there is another enabled bean that specializes Y we say that inconsistent specialization exists. The container automatically detects inconsistent specialization and treats it as a deployment problem.
5.1.4. Inter-module injection
A bean is available for injection in a certain module if the bean is not an interceptor or decorator, the bean is enabled, the bean is either not an alternative, or the module is a bean archive and the bean is a selected alternative of the bean archive, and the bean class is required to be accessible to classes in the module, according to the class accessibility requirements of the module architecture.
a) Check a decorator can not be injected
- DecoratorNotInjectedTest.testDecoratorNotResolved()
b) Check an interceptor can not be injected
- InterceptorNotResolvedInterModuleTest.testInterceptorNotAvailableForInjection()
- InterceptorNotResolvedTest.testInterceptorNotAvailableForInjection()
c) Check an enabled managed bean can be injected
- EnabledManagedBeanInjectionAvailability02Test.testInjection()
- EnabledManagedBeanInjectionAvailabilityTest.testInjection()
e) Check an enabled producer field can be injected
- EnabledProducerFieldInjectionAvailability02Test.testInjection()
- AlternativeAvailabilityTest.testProducersOnAlternativeClass()
- EnabledProducerFieldInjectionAvailabilityTest.testInjection()
f) Check an enabled producer method can be injected
- EnabledProducerMethodInjectionAvailabilityTest.testInjection()
- EnabledProducerMethodInjectionAvailability02Test.testInjection()
- AlternativeAvailabilityTest.testProducersOnAlternativeClass()
g) Check producer method of a disabled bean is not injectable
- AlternativeAvailabilityTest.testProducersOnAlternativeClass()
- DisabledProducerMethodInjectionNotAvailableTest.testInjection()
h) Check producer field of a disabled bean is not injectable
- AlternativeAvailabilityTest.testProducersOnAlternativeClass()
- DisabledProducerFieldInjectionNotAvailableTest.testInjection()
i) Check a disabled managed bean is not injectable
- DisabledBeanNotAvailableForInjectionTest.testDeployment()
l) Check a specialized managed bean is not injectable
- SpecializationModularity03Test.testSpecialization()
- SpecializationModularity06Test.testSpecialization()
- SpecializationModularity05Test.testSpecialization()
- SpecializedBeanInjectionNotAvailable02Test.testManagedBeanInjection()
- SpecializedBeanInjectionNotAvailableTest.testManagedBeanInjection()
m) Check a specialized producer field is not injectable
Note: Specialized producer field is not legal.
n) Check a specialized producer method is not injectable
- SpecializedProducerMethodInjectionNotAvailable02Test.testManagedBeanInjection()
- SpecializedProducerMethodInjectionNotAvailableTest.testManagedBeanInjection()
o) Check a selected alternative being managed bean is injected
- SelectedAlternativeManagedBeanInjectionAvailabilityTest.testInjection()
- SelectedAlternativeManagedBeanInjectionAvailability02Test.testInjection()
For a custom implementation of the Bean interface defined in Section 11.1, "The Bean interface, the container calls getBeanClass() to determine the bean class of the bean and InjectionPoint.getMember() and then Member.getDeclaringClass() to determine the class that declares an injection point.
q) Check Bean.getBeanClass() is used to determine the bean class
- CustomBeanImplementationTest.testGetBeanClassCalled()
r) Check InjectionPoint.getMember().getDeclaringClass() is used to determine the class declaring the injection point
- CustomBeanImplementationTest.testInjectionPointGetMemberIsUsedToDetermineTheClassThatDeclaresAnInjectionPoint()
A bean is available for injection in a certain module if:
-
the bean is not an interceptor or decorator,
-
the bean is enabled,
-
the bean is either not an alternative, or the module is a bean archive and the bean is a selected alternative of the bean archive, or the bean is a selected alternative of the application, and
-
the bean class is required to be accessible to classes in the module, according to the class accessibility requirements of the module architecture.
For a custom implementation of the Bean
interface defined in The Bean
interface, the container calls getBeanClass()
to determine the bean class of the bean and InjectionPoint.getMember()
and then Member.getDeclaringClass()
to determine the class that declares an injection point.
5.2. Typesafe resolution
The process of matching a bean to an injection point is called typesafe resolution. Typesafe resolution usually occurs at application initialization time, allowing the container to warn the user if any enabled beans have unsatisfied or unresolvable ambiguous dependencies.
5.2.1. Performing typesafe resolution
A bean is assignable to a given injection point if the bean has a bean type that matches the required type. For this purpose, primitive types are considered to match their corresponding wrapper types in java.lang and array types are considered to match only if their element types are identical. Parameterized and raw types are considered to match if they are identical or if the bean type is assignable to the required type, as defined in Section 5.2.3, "Assignability of raw and parameterized types".
i) Test with a primitive type.
- ResolutionByTypeTest.testResolveByTypeWithPrimitives()
j) Test with an array type.
- ResolutionByTypeTest.testResolveByTypeWithArray()
ka) Test with a parameterized type.
- ResolutionByTypeTest.testResolveByTypeWithTypeParameter()
kb) Test with a raw type.
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityToRawType()
kc) Test with a @Named bean.
- InjectionTest.testInjectionOfNamedBean()
A bean is assignable to a given injection point if the bean has all the required qualifiers. If no required qualifiers were explicitly specified, the container assumes the required qualifier @Default. A bean has the required qualifier if it has a qualifier with (a) the same type and (b) the same annotation member value for each member which is not annotated @javax.enterprise.util.NonBinding.
la) Test with beans with required qualifiers.
- QualifierInheritedTest.testResolution()
- ResolutionByTypeTest.testAllQualifiersSpecifiedForResolutionMustAppearOnBean()
lb) Test with beans without required qualifiers.
- QualifierNotDeclaredTest.testResolution()
- QualifierNotInheritedTest.testResolution()
- ResolutionByTypeTest.testDefaultBindingTypeAssumed()
lc) Test with matching beans with matching qualifier with same type.
- ResolutionByTypeTest.testAllQualifiersSpecifiedForResolutionMustAppearOnBean()
ld) Test with matching beans with matching qualifier with same annotation member value for each member which is not annotated @javax.enterprise.util.NonBinding.
- ResolutionByTypeTest.testResolveByTypeWithNonBindingMembers()
n) A bean is eligible for injection to a certain injection point if it is available for injection in the module that contains the class that declares the injection point, and it is assignable to the injection point.
- JarToJarAlphaVisibilityTest.testDeployment()
- EnterpriseArchiveModulesTest.testVisibilityAndInterceptorEnablement()
- JarToJarReverseAlphaVisibilityTest.testDeployment()
- WebArchiveModulesTest.testInjectionChainVisibilityAndInterceptorEnablement()
For a custom implementation of the Bean interface defined in Section 11.1, "The Bean interface", the container calls getTypes() and getQualifiers() to determine the bean types and qualifiers.
na) Test getTypes() determines bean types.
- CustomBeanImplementationTest.testGetTypesCalled()
nb) Test getQualifiers() determines qualifiers.
- CustomBeanImplementationTest.testGetBindingsCalled()
The container considers bean type and qualifiers when resolving a bean to be injected to an injection point. The type and qualifiers of the injection point are called the required type and required qualifiers.
A bean is assignable to a given injection point if:
-
The bean has a bean type that matches the required type. For this purpose, primitive types are considered to match their corresponding wrapper types in
java.lang
and array types are considered to match only if their element types are identical. Parameterized and raw types are considered to match if they are identical or if the bean type is assignable to the required type, as defined in Assignability of raw and parameterized types or Assignability of raw and parameterized types for delegate injection points. -
The bean has all the required qualifiers. If no required qualifiers were explicitly specified, the container assumes the required qualifier
@Default
. A bean has a required qualifier if it has a qualifier with (a) the same type and (b) the same annotation member value for each member which is not annotated@javax.enterprise.util.Nonbinding
.
A bean is eligible for injection to a certain injection point if:
-
it is available for injection in the module that contains the class that declares the injection point, and
-
it is assignable to the injection point (using Assignability of raw and parameterized types).
For a custom implementation of the Bean
interface defined in The Bean
interface, the container calls getTypes()
and getQualifiers()
to determine the bean types and qualifiers.
5.2.2. Unsatisfied and ambiguous dependencies
When an ambiguous dependency exists, the container attempts to resolve the ambiguity. The container eliminates all eligible beans that are not alternatives selected for the bean archive or selected for the application, except for producer methods and fields of beans that are alternatives.
ca) If there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.
- AmbiguousDependencyResolutionTest.testProducerMethodOnAlternativeIsNotEliminated()
- AmbiguousDependencyResolutionTest.testProducerFieldOnAlternativeIsNotEliminated()
- EnterpriseSelectedAlternative03Test.testDependencyResolvable()
- ResourceAlternative04Test.testAlternativeResourceSelected()
- SelectedAlternative02Test.testDependencyResolvable()
cb) If all the beans left are alternatives with a priority, then the container will determine the highest priority value, and eliminate all beans, except for producer methods and fields of beans that are alternatives with the highest priority value. If there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.
- EnterpriseSelectedAlternative03Test.testDependencyResolvable()
- ResourceAlternative04Test.testAlternativeResourceSelected()
- SelectedAlternative02Test.testDependencyResolvable()
The container must validate all injection points of all enabled beans, all observer methods and all disposer methods when the application is initialized to ensure that there are no unsatisfied or ambiguous dependencies. If an unsatisfied or ambiguous dependency exists, the container automatically detects the problem and treats it as a deployment problem.
aa) Test unsatisfied dependency for enabled bean.
- UnsatisfiedDependencyTest.testUnsatisfiedDependency()
ab) Test unsatisfied dependency for observer method.
ac) Test unsatisfied dependency for disposer method.
ae) Test ambiguous dependency for enabled bean.
- AmbiguousDependencyTest.testAmbiguousDependency()
- MultiModuleSessionBeanAmbiguousDependencyTest.testAmbiguousDependencyDetected()
af) Test ambiguous dependency for observer method.
ag) Test ambiguous dependency for disposer method.
b) For a custom implementation of the Bean interface defined in Section 11.1, "The Bean interface", the container calls getInjectionPoints() to determine the set of injection points.
- CustomBeanImplementationTest.testGetInjectionPointsCalled()
An unsatisfied dependency exists at an injection point when no bean is eligible for injection to the injection point. An ambiguous dependency exists at an injection point when multiple beans are eligible for injection to the injection point.
Note that an unsatisfied or ambiguous dependency cannot exist for a decorator delegate injection point, defined in Decorator delegate injection points.
When an ambiguous dependency exists, the container attempts to resolve the ambiguity. The container eliminates all eligible beans that are not alternatives, except for producer methods and fields of beans that are alternatives. If:
-
there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.
-
all the beans left are alternatives with a priority, or producer methods or fields of beans that are alternatives with a priority, then the container will determine the highest priority value, and eliminate all beans, except for alternatives with the highest priority and producer methods and fields of alternatives with the highest priority value. If there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.
The container must validate all injection points of all enabled beans, all observer methods and all disposer methods when the application is initialized to ensure that there are no unsatisfied or unresolvable ambiguous dependencies. If an unsatisfied or unresolvable ambiguous dependency exists, the container automatically detects the problem and treats it as a deployment problem.
For a custom implementation of the Bean
interface defined in The Bean
interface, the container calls getInjectionPoints()
to determine the set of injection points.
5.2.3. Legal injection point types
a) Any legal bean type, as defined in Section 2.2.1, "Legal bean types" may be the required type of an injection point.
- LegalRequiredTypeTest.testLegalRequiredType()
b) The required type of an injection point may contain a wildcard type parameter.
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithActualTypesToParameterizedTypeWithWildcardsAtInjectionPoint()
c) If an injection point type is a type variable, the container automatically detects the problem and treats it as a definition error.
- TypeVariableInjectionPointTest.testTypeVariableInjectionPoint()
Any legal bean type, as defined in Legal bean types may be the required type of an injection point. Furthermore, the required type of an injection point may contain a wildcard type parameter. However, a type variable is not a legal injection point type.
If an injection point type is a type variable, the container automatically detects the problem and treats it as a definition error.
5.2.4. Assignability of raw and parameterized types
a) A parameterized bean type is considered assignable to a raw required type if the raw types are identical and all type parameters of the bean type are either unbounded type variables or java.lang.Object.
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityToRawType()
- ParameterizedTypesInjectionRawAmbiguousTest.testInjection()
- ParameterizedTypesInjectionToRawTypeTest.testInjection()
A parameterized bean type is considered assignable to a parameterized required type if they have identical raw type and for each parameter: the required type parameter and the bean type parameter are actual types with identical raw type, and, if the type is parameterized, the bean type parameter is assignable to the required type parameter according to these rules, or the required type parameter is a wildcard, the bean type parameter is an actual type and the actual type is assignable to the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or the required type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable to or assignable from the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or the required type parameter is an actual type, the bean type parameter is a type variable and the actual type is as- signable to the upper bound, if any, of the type variable, or the required type parameter and the bean type parameter are both type variables and the upper bound of the required type parameter is assignable to the upper bound, if any, of the bean type parameter.
ba) Check the required type parameter and the bean type parameter are actual types with identical raw type
- ParameterizedTypesInjectionToParameterizedWithActualTypeTest.testInjection()
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithActualTypesToParameterizedTypeWithActualTypes()
- ParameterizedTypesInjectionToParameterizedWithActualTypeTest.testInjection()
bb) Check the required type parameter and the bean type parameter are actual types with identical raw type for nested type parameters
- ParameterizedTypesInjectionToParameterizedWithActualTypeTest.testInjection()
c) Check the required type parameter is a wildcard, the bean type parameter is an actual type and the actual type is assignable to the upper bound of the wildcard and assignable from the lower bound of the wildcard
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithActualTypesToParameterizedTypeWithWildcards()
- ParameterizedTypesInjectionToParameterizedWithWildcardTest.testInjection()
da) Check the required type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable to the upper bound of the wildcard
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithTypeVariablesToParameterizedTypeWithWildcards()
- ParameterizedTypesInjectionToParameterizedWithWildcardTest.testInjection()
db) Check the required type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable from the upper bound of the wildcard
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithTypeVariablesToParameterizedTypeWithWildcards2()
- ParameterizedTypesInjectionToParameterizedWithWildcardTest.testInjection()
dc) Check the required type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable from the lower bound of the wildcard
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithTypeVariablesToParameterizedTypeWithWildcards()
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithTypeVariablesToParameterizedTypeWithWildcards2()
- ParameterizedTypesWithTypeVariableWithMultipleBoundsTest.testInjectionOfBeanWithWildcardWithTypeVariableAsLowerBound()
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithTypeVariablesToParameterizedTypeWithWildcardWithLowerBound()
e) Check the required type parameter is an actual type, the bean type parameter is a type variable and the actual type is assignable to the upper bound of the type variable
- ParameterizedTypesInjectionToParameterizedWithActualTypeTest.testInjection()
- ParameterizedTypesWithTypeVariableWithMultipleBoundsTest.testInjectionOfBeanWithTypeVariableWithMultipleBoundsToParameterizedTypeWithActualType()
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithTypeVariablesToParameterizedTypeWithActualTypes()
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithTypeVariablesWithMultipleBoundsToParameterizedTypeWithActualTypes()
f) Check the required type parameter and the bean type parameter are both type variables and the upper bound of the required type parameter is assignable to the upper bound of the bean type parameter.
- ParameterizedTypesInjectionToParameterizedWithTypeVariableUpperBoundTest.testInjection()
- ParameterizedTypesInjectionToParameterizedWithTypeVariableTest.testInjection()
- ParameterizedTypesWithTypeVariableWithMultipleBoundsTest.testInjectionOfBeanWithTypeVariableWithMultipleBounds()
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithTypeVariablesToParameterizedTypeWithTypeVariable()
- AssignabilityOfRawAndParameterizedTypesTest.testAssignabilityOfParameterizedTypeWithTypeVariableWithMultipleBoundsToParameterizedTypeWithTypeVariable()
g) A raw bean type is considered assignable to a parameterized required type if the raw types are identical and all type parameters of the required type are either unbounded type variables or java.lang.Object.
- RawBeanTypeParameterizedRequiredTypeTest.testNotAssignableTypeParams()
- RawBeanTypeParameterizedRequiredTypeTest.testAssignableTypeParams()
A parameterized bean type is considered assignable to a raw required type if the raw types are identical and all type parameters of the bean type are either unbounded type variables or java.lang.Object
.
A parameterized bean type is considered assignable to a parameterized required type if they have identical raw type and for each parameter:
-
the required type parameter and the bean type parameter are actual types with identical raw type, and, if the type is parameterized, the bean type parameter is assignable to the required type parameter according to these rules, or
-
the required type parameter is a wildcard, the bean type parameter is an actual type and the actual type is assignable to the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or
-
the required type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable to or assignable from the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or
-
the required type parameter is an actual type, the bean type parameter is a type variable and the actual type is assignable to the upper bound, if any, of the type variable, or
-
the required type parameter and the bean type parameter are both type variables and the upper bound of the required type parameter is assignable to the upper bound, if any, of the bean type parameter.
For example, Dao
is eligible for injection to any injection point of type @Default Dao<Order>
, @Default Dao<User>
, @Default Dao<?>
, @Default Dao<? extends Persistent>
or @Default Dao<X extends Persistent>
where X
is a type variable.
public class Dao<T extends Persistent> { ... }
Furthermore, UserDao
is eligible for injection to any injection point of type @Default Dao<User>
, @Default Dao<?>
, @Default Dao<? extends Persistent>
or @Default Dao<? extends User>
.
public class UserDao extends Dao<User> { ... }
A raw bean type is considered assignable to a parameterized required type if the raw types are identical and all type parameters of the required type are either unbounded type variables or java.lang.Object.
Note that a special set of rules, defined in Assignability of raw and parameterized types for delegate injection points, apply if and only if the injection point is a decorator delegate injection point.
5.2.5. Primitive types and null values
If necessary, the container performs boxing or unboxing when it injects a value to a field or parameter of primitive or wrapper type.
aa) Test boxing.
- ResolutionByTypeTest.testResolveByTypeWithPrimitives()
- InjectionTest.testInjectionPerformsBoxingIfNecessary()
ab) Test unboxing.
- ResolutionByTypeTest.testResolveByTypeWithPrimitives()
b) If an injection point of primitive type resolves to a producer method or producer field that returns a null value at runtime, the container must inject the primitive type's default value as defined by the Java Language Specification.
- PrimitiveInjectionPointTest.testPrimitiveInjectionPointResolvedToNonPrimitiveProducerMethod()
For the purposes of typesafe resolution and dependency injection, primitive types and their corresponding wrapper types in the package java.lang
are considered identical and assignable. If necessary, the container performs boxing or unboxing when it injects a value to a field or parameter of primitive or wrapper type.
If an injection point of primitive type resolves to a producer method or producer field that returns a null value at runtime, the container must inject the primitive type’s default value as defined by the Java Language Specification.
5.2.6. Qualifier annotations with members
a) Qualifier types may have annotation members.
Note: A statement of intent
b) An annotation member may be excluded from consideration using the @NonBinding annotation.
- ResolutionByTypeTest.testResolveByTypeWithNonBindingMembers()
- BindingAnnotationWithMemberTest.testAnnotationMemberWithNonBinding()
- BindingAnnotationWithMemberTest.testArrayMemberWithNonBinding()
c) Array-valued or annotation-valued members of a qualifier type should be annotated @NonBinding in a portable application. If an array-valued or annotation-valued member of a qualifier is not annotated @NonBinding, non-portable behavior results.
Qualifier types may have annotation members.
@PayBy(CHEQUE) class ChequePaymentProcessor implements PaymentProcessor { ... }
@PayBy(CREDIT_CARD) class CreditCardPaymentProcessor implements PaymentProcessor { ... }
Then only ChequePaymentProcessor
is a candidate for injection to the following attribute:
@Inject @PayBy(CHEQUE) PaymentProcessor paymentProcessor;
On the other hand, only CreditCardPaymentProcessor
is a candidate for injection to this attribute:
@Inject @PayBy(CREDIT_CARD) PaymentProcessor paymentProcessor;
The container calls the equals()
method of the annotation member value to compare values.
An annotation member may be excluded from consideration using the @Nonbinding
annotation.
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface PayBy {
PaymentMethod value();
@Nonbinding String comment() default "";
}
Array-valued or annotation-valued members of a qualifier type should be annotated @Nonbinding
in a portable application. If an array-valued or annotation-valued member of a qualifier type is not annotated @Nonbinding
, non-portable behavior results.
5.2.7. Multiple qualifiers
a) A bean class may declare multiple qualifiers.
- ResolutionByTypeTest.testAllQualifiersSpecifiedForResolutionMustAppearOnBean()
b) A producer method may declare multiple qualifiers.
- ResolutionByTypeTest.testResolveByTypeWithPrimitives()
c) A producer field may declare multiple qualifiers.
- ResolutionByTypeTest.testResolveByTypeWithPrimitives()
d) A bean must declare all of the qualifiers that are specified at the injection point to be considered a candidate for injection.
- ResolutionByTypeTest.testAllQualifiersSpecifiedForResolutionMustAppearOnBean()
A bean class or producer method or field may declare multiple qualifiers.
@Synchronous @PayBy(CHEQUE) class ChequePaymentProcessor implements PaymentProcessor { ... }
Then ChequePaymentProcessor
would be considered a candidate for injection into any of the following attributes:
@Inject @PayBy(CHEQUE) PaymentProcessor paymentProcessor;
@Inject @Synchronous PaymentProcessor paymentProcessor;
@Inject @Synchronous @PayBy(CHEQUE) PaymentProcessor paymentProcessor;
A bean must declare all of the qualifiers that are specified at the injection point to be considered a candidate for injection.
5.3. Name resolution
d) An name resolves to a bean if the bean has the given bean name, and the bean is available for injection in the module where the name resolution is requested.
- IntegrationWithUnifiedELTest.testELResolverRegisteredWithJsf()
- IntegrationWithUnifiedELTest.testELResolverRegisteredWithServletContainer()
e) For a custom implementation of the Bean interface defined in Section 11.1, "The Bean interface", the container calls getName() to determine the bean name.
- CustomBeanImplementationTest.testGetNameCalled()
The process of matching a bean to a name is called name resolution. Since there is no typing information available during name resolution, the container may consider only the bean name. Name resolution usually occurs at runtime.
A name resolves to a bean if:
-
the bean has the given bean name, and
-
the bean is available for injection in the module where the name resolution is requested.
For a custom implementation of the Bean
interface defined in The Bean
interface, the container calls getName()
to determine the bean name.
5.3.1. Ambiguous names
An ambiguous name exists when a name resolves to multiple beans. When an ambiguous name exists, the container attempts to resolve the ambiguity. The container eliminates all eligible beans that are not alternatives selected for the bean archive or selected for the application, except for producer methods and fields of beans that are alternatives.
ca) If there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.
- ResolutionByNameTest.testAmbiguousELNamesResolved()
- AmbiguousELNamesTest.testAmbiguousELNamesResolved()
- AmbiguousELNamesTest.testAmbiguousELNamesResolved()
cb) If all the beans left are alternatives with a priority, then the container will determine the highest priority value, and eliminate all beans, except for producer methods and fields of beans that are alternatives with the highest priority value. If there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.
- AmbiguousELNamesTest.testAmbiguousELNamesResolved()
- AmbiguousELNamesTest.testAmbiguousELNamesResolved()
All unresolvable ambiguous names are detected by the container when the application is initialized. Suppose two beans are both available for injection in a certain module, and either
da) Test two beans have the same bean name and the name is not resolvable.
- AmbiguousELNamesTest.testAmbiguousELNamesResolved()
- DuplicitNameTest.testDuplicateNamedBeans()
db) Test the bean name of one bean is of the form x.y , where y is a valid bean name, and x is the bean name of the other bean.
- NamePrefixTest.testDuplicateBeanNamePrefix()
- ExpandedNamePrefixTest.testDuplicateBeanNamePrefix()
- ExpandedNamePrefix2Test.testDuplicateBeanNamePrefix()
An ambiguous name exists when a name resolves to multiple beans. When an ambiguous name exists, the container attempts to resolve the ambiguity. The container eliminates all eligible beans that are not alternatives selected for the bean archive or selected for the application, except for producer methods and fields of beans that are alternatives. If:
-
there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.
-
all the beans left are alternatives with a priority, then the container will determine the highest priority value, and eliminate all beans, except for producer methods and fields of beans that are alternatives with the highest priority value. If there is exactly one bean remaining, the container will select this bean, and the ambiguous dependency is called resolvable.
All unresolvable ambiguous names are detected by the container when the application is initialized. Suppose two beans are both available for injection in a certain module, and either:
-
the two beans have the same bean name and the name is not resolvable, or
-
the bean name of one bean is of the form
x.y
, wherey
is a valid bean name, andx
is the bean name of the other bean,
the container automatically detects the problem and treats it as a deployment problem.
5.4. Client proxies
b) A contextual reference to a bean with a normal scope, as defined in Section 6.3, “Normal scopes and pseudo-scopes”, is not a direct reference to a contextual instance of the bean (the object returned by Contextual.create()). Instead, the contextual reference is a client proxy object.
- ClientProxyTest.testClientProxyUsedForNormalScope()
a) Client proxies are never required for a bean whose scope is a pseudo-scope such as @Dependent.
c) Client proxies are serializable
- ClientProxyTest.testSimpleBeanClientProxyIsSerializable()
d) The container must guarantee that when any valid injected reference to a bean of normal scope is invoked, the invocation is always processed by the current instance of the injected bean.
- ClientProxyTest.testInvocationIsProcessedOnCurrentInstance()
e) Client proxies may be shared between multiple injection points.
An injected reference, or reference obtained by programmatic lookup, is usually a contextual reference as defined by Contextual reference for a bean.
A contextual reference to a bean with a normal scope, as defined in Normal scopes and pseudo-scopes, is not a direct reference to a contextual instance of the bean (the object returned by Contextual.create()
). Instead, the contextual reference is a client proxy object. A client proxy implements/extends some or all of the bean types of the bean and delegates all method calls to the current instance (as defined in Normal scopes and pseudo-scopes) of the bean.
There are a number of reasons for this indirection:
-
The container must guarantee that when any valid injected reference to a bean of normal scope is invoked, the invocation is always processed by the current instance of the injected bean. In certain scenarios, for example if a request scoped bean is injected into a session scoped bean, or into a servlet, this rule requires an indirect reference. (Note that the
@Dependent
pseudo-scope is not a normal scope.) -
The container may use a client proxy when creating beans with circular dependencies. This is only necessary when the circular dependencies are initialized via a managed bean constructor or producer method parameter. (Beans with scope
@Dependent
never have circular dependencies.) -
Finally, client proxies may be passivated, even when the bean itself may not be. Therefore the container must use a client proxy whenever a bean with normal scope is injected into a bean with a passivating scope, as defined in Passivation and passivating scopes. (On the other hand, beans with scope
@Dependent
must be serialized along with their client.)
Client proxies are never required for a bean whose scope is a pseudo-scope such as @Dependent
.
Client proxies may be shared between multiple injection points. For example, a particular container might instantiate exactly one client proxy object per bean. (However, this strategy is not required by this specification.)
5.4.1. Client proxy invocation
aa) Every time a method of the bean is invoked upon a client proxy, the client proxy must obtain a contextual instance of the bean, as defined in Section 6.5.2, "Contextual instance of a bean", and invoke the method upon this instance.
- ClientProxyTest.testClientProxyInvocation()
ab) If the scope is not active, as specified in Section 6.5.1, "The active context object for a scope", the client proxy rethrows ContextNotActiveException or IllegalStateException.
- ClientProxyTest.testInactiveScope()
b) The behavior of all methods declared by java.lang.Object, except for toString(), is undefined for a client proxy.
Every time a method of the bean is invoked upon a client proxy, the client proxy must:
-
obtain a contextual instance of the bean, as defined in Contextual instance of a bean, and
-
invoke the method upon this instance.
If the scope is not active, as specified in The active context object for a scope, the client proxy rethrows the ContextNotActiveException
or IllegalStateException
.
The behavior of all methods declared by java.lang.Object
, except for toString()
, is undefined for a client proxy. Portable applications should not invoke any method declared by java.lang.Object
, except for toString()
, on a client proxy.
5.5. Dependency injection
b) The container is required to perform dependency injection whenever it creates a contextual instance of a managed bean.
- InjectionTest.testInjectionOfNamedBean()
d) The container is required to perform dependency injection whenever it instantiates non-contextual instances of managed beans.
- InjectionIntoNonContextualComponentTest.testInjectionIntoJSFManagedBean()
g) The container interacts with instances of beans or objects supporting injection by calling methods and getting and setting the field values.
h) The object injected by the container may not be a direct reference to a contextual instance of the bean. Instead, it is an injectable reference, as defined by Section 6.5.5, "Injectable references".
From time to time the container instantiates beans and other class supporting injection. The resulting instance may or may not be a contextual instance as defined by Contextual instance of a bean.
The container is required to perform dependency injection whenever it creates the following contextual objects:
-
contextual instances of managed beans.
The container is also required to perform dependency injection whenever it instantiates the following non-contextual objects:
-
non-contextual instances of managed beans.
The container interacts with instances of beans or objects supporting injection by calling methods and getting and setting field values.
The object injected by the container may not be a direct reference to a contextual instance of the bean. Instead, it is an injectable reference, as defined by Injectable references.
5.5.1. Injection using the bean constructor
When the container instantiates a managed bean with a constructor annotated @Inject, the container calls this constructor, passing an injectable reference to each parameter. If there is no constructor annotated @Inject, the container calls the constructor with no parameters.
aa) Test managed bean with a constructor annotated @Inject.
- SimpleBeanDefinitionTest.testInitializerAnnotatedConstructorUsedOverEmptyConstuctor()
ba) Test constructor with no parameters is used for a managed bean
- SimpleBeanDefinitionTest.testEmptyConstructorUsed()
When the container instantiates a managed bean with a constructor annotated @Inject
, the container calls this constructor, passing an injectable reference to each parameter. If there is no constructor annotated @Inject
, the container calls the constructor with no parameters.
5.5.2. Injection of fields and initializer methods
When the container creates a new instance of a managed bean the container must: Initialize the values of all injected fields. The container sets the value of each injected field to an injectable reference. Call all initializer methods, passing an injectable reference to each parameter.
ac) Test managed bean fields injected
- InjectionTest.testInjectionOfNamedBean()
ad) Test managed bean initializer methods called
- InitializerMethodTest.testMultipleInitializerMethodsAreCalled()
- InjectionTest.testInjectionFieldsAndInitializerMethods()
- InjectionTest.testInjectionFieldsAndInitializerMethods()
The container must ensure that: Initializer methods declared by a class X in the type hierarchy of the bean are called after all injected fields declared by X or by superclasses of X have been initialized. Any @PostConstruct callback declared by a class X in the type hierarchy of the bean is called after all initializer methods declared by X or by superclasses of X have been called, after all injected fields declared by X or by superclasses of X have been initialized.
bg) Test managed bean initializer methods called after injected field of X
- InjectionTest.testInjectionFieldsAndInitializerMethods()
bh) Test managed bean initializer methods called after injected field of superclass of X
- InjectionTest.testInjectionFieldsAndInitializerMethods()
bk) Test managed bean @PostConstruct called after initializer of X
- InjectionTest.testInjectionFieldsAndInitializerMethods()
bl) Test managed bean @PostConstruct called after initializer of superclass of X
- InjectionTest.testInjectionFieldsAndInitializerMethods()
When the container creates a new instance of a managed bean, the container must:
-
Initialize the values of all injected fields. The container sets the value of each injected field to an injectable reference.
-
Call all initializer methods, passing an injectable reference to each parameter.
The container must ensure that:
-
Initializer methods declared by a class X in the type hierarchy of the bean are called after all injected fields declared by X or by superclasses of X have been initialized.
-
Any
@PostConstruct
callback declared by a class X in the type hierarchy of the bean is called after all initializer methods declared by X or by superclasses of X have been called, after all injected fields declared by X or by superclasses of X have been initialized.
5.5.3. Destruction of dependent objects
a) When the container destroys an instance of a bean, the container destroys all dependent objects, as defined in Section 6.4.2, "Destruction of objects with scope @Dependent", after the @PreDestroy callback completes.
- SimpleBeanLifecycleTest.testDependentsDestroyedAfterPreDestroy()
When the container destroys an instance of a bean, the container destroys all dependent objects, as defined in Destruction of objects with scope @Dependent
, after the @PreDestroy
callback completes.
5.5.4. Invocation of producer or disposer methods
a) When the container calls a producer method, if the method is static, the container must invoke the method.
- ProducerMethodDefinitionTest.testStaticMethod()
b) When the container calls a disposer method, if the method is static, the container must invoke the method.
- DisposalMethodDefinitionTest.testBindingTypesAppliedToDisposalMethodParameters()
c) When the container calls a producer method, if the method is non-static the container must obtain a contextual instance of the bean which declares the method, as defined by Section 6.5.2 "Contextual instance of a bean", then invoke the method upon this instance.
- ProducerMethodSpecializationTest.testSpecializingProducerMethod()
- ProducerMethodLifecycleTest.testProducerMethodFromSpecializedBeanUsed()
d) When the container calls a disposer method, if the method is non-static the container must obtain a contextual instance of the bean which declares the method, as defined by Section 6.5.2 "Contextual instance of a bean", then invoke the method upon this instance.
- DependentContextTest.testDependentsDestroyedWhenDisposerMethodCompletes()
e) The container passes an injectable reference to each injected method parameter.
- ProducerMethodDefinitionTest.testBindingTypesAppliedToProducerMethodParameters()
- DisposalMethodDefinitionTest.testDisposalMethodParametersGetInjected()
f) The container is also responsible for destroying dependent objects created during this invocation, as defined in Section 6.4.2, "Destruction of objects with scope @Dependent".
- DependentContextTest.testDependentsDestroyedWhenProducerMethodCompletes()
- DependentContextTest.testDependentsDestroyedWhenDisposerMethodCompletes()
When the container calls a producer or disposer method, the behavior depends upon whether the method is static or non-static:
-
If the method is static, the container must invoke the method.
-
Otherwise, if the method is non-static, the container must:
-
Obtain a contextual instance of the bean which declares the method, as defined by Contextual instance of a bean.
-
Invoke the method upon this instance, as a business method invocation, as defined in Container invocations and interception.
The container passes an injectable reference to each injected method parameter. The container is also responsible for destroying dependent objects created during this invocation, as defined in Destruction of objects with scope @Dependent
.
5.5.5. Access to producer field values
a) When the container accesses the value of a producer field, if the producer field is static, the container must access the field value.
- ProducerFieldLifecycleTest.testProducerStaticFieldBean()
b) When the container accesses the value of a producer field, if the producer field is non-static, the container must obtain a contextual instance of the bean which declares the producer field, as defined by Section 6.5.2 "Contextual instance of a bean", then access the field value of this instance.
- ProducerFieldLifecycleTest.testProducerFieldBeanCreate()
When the container accesses the value of a producer field, the value depends upon whether the field is static or non-static:
-
If the producer field is static, the container must access the field value.
-
Otherwise, if the producer field is non-static, the container must:
-
Obtain an contextual instance of the bean which declares the producer field, as defined by Contextual instance of a bean.
-
Access the field value of this instance.
5.5.6. Invocation of observer methods
a) When the container calls an observer method (defined in Section 10.4 "Observer methods"), if the observer method is static, the container must invoke the method.
- EventTest.testStaticObserverMethodInvoked()
baa) When the container calls an observer method (defined in Section 10.4 "Observer methods"), if the observer method is non-static, the container must obtain a contextual instance of the bean according to Section 6.5.2 "Contextual instance of a bean". If this observer method is a conditional observer method, obtain the contextual instance that already exists, only if the scope of the bean that declares the observer method is currently active, without creating a new contextual instance. Finally, the container must invoke the observer method on the resulting instance, if any, as a business method invocation, as defined in Section 7.2 "Container invocations and interception".
- EventTest.testObserverCalledOnSpecializedBeanOnly()
- ConditionalObserverTest.testConditionalObserver()
- ConditionalObserverTest.testObserverMethodInvokedOnReturnedInstanceFromContext()
c) The container must pass the event object to the event parameter and an injectable instance to each injected method parameter.
- EventTest.testObserverMethodParameterInjectionPoints()
d) The container is also responsible for destroying dependent objects created during this invocation, as defined in Section 6.4.2, "Destruction of objects with scope @Dependent".
- DependentContextTest.testDependentsDestroyedWhenObserverMethodEvaluationCompletes()
When the container calls an observer method (defined in Observer methods), the behavior depends upon whether the method is static or non-static:
-
If the observer method is static, the container must invoke the method.
-
Otherwise, if the observer method is non-static, the container must:
-
Obtain a contextual instance of the bean which declares the observer method according to Contextual instance of a bean. If this observer method is a conditional observer method, obtain the contextual instance that already exists, only if the scope of the bean that declares the observer method is currently active, without creating a new contextual instance.
-
Invoke the observer method on the resulting instance, if any, as a business method invocation, as defined in Container invocations and interception.
The container must pass the event object to the event parameter and an injectable instance to each injected method parameter. The container is also responsible for destroying dependent objects created during this invocation, as defined in Destruction of objects with scope @Dependent
.
5.5.7. Injection point metadata
aa) The getBean() method returns the Bean object representing the bean that defines the injection point.
- EventMetadataInjectionPointTest.testGetBean()
- InjectionPointTest.testGetBean()
- NonContextualInjectionPointTest.testContextualEjbInjectionPointGetBean()
aaa) If the injection point does not belong to a bean, getBean() returns a null value.
- NonContextualInjectionPointTest.testNonContextualEjbInjectionPointGetBean()
aab) If the injection point represents a dynamically obtained instance, the getBean() method should return the Bean object representing the bean that defines the Instance injection point.
- DynamicInjectionPointTest.testInjectionPointGetBean()
ba) The getType() method returns the required type of the injection point.
- EventMetadataInjectionPointTest.testGetType()
- InjectionPointTest.testGetType()
baa) If the injection point represents a dynamically obtained instance, the getType() method returns the required type (as defined by Instance.select()).
- DynamicInjectionPointTest.testInjectionPointGetType()
bc) The getQualifiers() method returns the required qualifiers of the injection point.
- EventMetadataInjectionPointTest.testGetQualifiers()
- InjectionPointTest.testGetBindingTypes()
bca) If the injection point represents a dynamically obtained instance, the getQualifiers() method returns required qualifiers of the injection point including any additional required qualifers (as defined by Instance.select()).
- DynamicInjectionPointTest.testInjectionPointGetQualifiers()
ca) The getMember() method returns the Field object in the case of field injection.
- EventMetadataInjectionPointTest.testGetMember()
- InjectionPointTest.testGetMemberField()
caa) If the injection point represents a dynamically obtained instance, the getMember() method returns the Field object representing the field that defines the Instance injection point in the case of field injection.
- DynamicInjectionPointTest.testInjectionPointGetMember()
cb) The getMember() method returns the Method object in the case of method parameter injection.
- EventMetadataInjectionPointTest.testGetMember()
- InjectionPointTest.testGetMemberMethod()
cba) If the injection point represents a dynamically obtained instance, the getMember() method returns the Method object representing the method that defines the Instance injection point in the case of method parameter injection.
- DynamicInjectionPointTest.testInjectionPointGetMember()
cc) The getMember() method returns the Constructor object in the case of constructor parameter injection.
- EventMetadataInjectionPointTest.testGetMember()
- InjectionPointTest.testGetMemberConstructor()
cca) If the injection point represents a dynamically obtained instance, the getMember() method returns the Constructor object representing the constructor that defines the Instance injection point in the case of constructor parameter injection.
- DynamicInjectionPointTest.testInjectionPointGetMember()
daa) The getAnnotated() method returns an instance of javax.enterprise.inject.spi.AnnotatedField or javax.enterprise.inject.spi.AnnotatedParameter, depending upon whether the injection point is an injected field or a constructor/method parameter.
- EventMetadataInjectionPointTest.testGetAnnotatedType()
- InjectionPointTest.testGetAnnotatedField()
- InjectionPointTest.testGetAnnotatedParameter()
dab) If the injection point represents a dynamically obtained instance, then the getAnnotated() method returns an instance of javax.enterprise.inject.spi.AnnotatedField or javax.enterprise.inject.spi.AnnotatedParameter representing the Instance injection point, depending upon whether the injection point is an injected field or a constructor/method parameter.
- DynamicInjectionPointTest.testInjectionPointGetAnnotated()
dba) The isDelegate() method returns true if the injection point is a decorator delegate injection point, and false otherwise.
- InjectionPointTest.testIsDelegate()
dbb) If the injection point represents a dynamically obtained instance then isDelegate() returns false.
- DynamicInjectionPointTest.testInjectionPointIsDelegate()
dca) The isTransient() method returns true if the injection point is a transient field, and false otherwise.
- EventMetadataInjectionPointTest.testIsTransient()
- InjectionPointTest.testIsTransient()
dcb) If the injection point represents a dynamically obtained instance then the isTransient() method returns true if the Instance injection point is a transient field, and false otherwise.
- DynamicInjectionPointTest.testInjectionPointIsTransient()
ea) The container must provide a bean with scope @Dependent, bean type InjectionPoint and qualifier @Default, allowing dependent objects, as defined in Section 6.4.1, "Dependent objects", to obtain information about the injection point to which they belong.
- AfterBeanDiscoveryTest.testCustomDependentBeanInjectionPointIsAvailable()
- InjectionPointTest.testDependentScope()
- InjectionPointTest.testApiTypeInjectionPoint()
- InjectionPointTest.testCurrentBinding()
eb) The built-in implementation must be a passivation capable dependency, as defined in Section 6.6.2, "Passivation capable dependencies".
- InjectionPointTest.testPassivationCapability()
f) If a bean that declares any scope other than @Dependent has an injection point of type InjectionPoint and qualifier @Default, the container automatically detects the problem and treats it as a definition error.
- NormalScopedBeanWithInjectionPoint.testRequestScopedBeanWithInjectionPoint()
g) If a disposer method has an injection point of type InjectionPoint and qualifier @Default, the container automatically detects the problema nd treats it as a definition error.
- DisposerInjectionPointMetadataTest.testDisposerWithInjectionPointMetadata()
h) If a class supporting injection that is not a bean has an injection point of type InjectionPoint and qualifier @Default, the container automatically detects the problem and treats it as a definition error.
- InjectionPointTest.testDefinitionErrorDetected()
The interface javax.enterprise.inject.spi.InjectionPoint
provides access to metadata about an injection point. An instance of InjectionPoint
may represent:
-
an injected field or a parameter of a bean constructor, initializer method, producer method, disposer method or observer method, or
-
an instance obtained dynamically using
Instance.get()
.
public interface InjectionPoint {
public Type getType();
public Set<Annotation> getQualifiers();
public Bean<?> getBean();
public Member getMember();
public Annotated getAnnotated();
public boolean isDelegate();
public boolean isTransient();
}
-
The
getBean()
method returns theBean
object representing the bean that defines the injection point. If the injection point does not belong to a bean,getBean()
returns a null value. If the injection point represents a dynamically obtained instance, thegetBean()
method should return theBean
object representing the bean that defines theInstance
injection point. -
The
getType()
andgetQualifiers()
methods return the required type and required qualifiers of the injection point. If the injection point represents a dynamically obtained instance, thegetType()
andgetQualifiers()
methods should return the required type (as defined byInstance.select()
), and required qualifiers of the injection point including any additional required qualifiers (as defined byInstance.select()
). -
The
getMember()
method returns theField
object in the case of field injection, theMethod
object in the case of method parameter injection, or theConstructor
object in the case of constructor parameter injection. If the injection point represents a dynamically obtained instance, thegetMember()
method returns theField
object representing the field that defines theInstance
injection point in the case of field injection, theMethod
object representing the method that defines theInstance
injection point in the case of method parameter injection, or theConstructor
object representing the constructor that defines theInstance
injection point in the case of constructor parameter injection. -
The
getAnnotated()
method returns an instance ofjavax.enterprise.inject.spi.AnnotatedField
orjavax.enterprise.inject.spi.AnnotatedParameter
, depending upon whether the injection point is an injected field or a constructor/method parameter. If the injection point represents a dynamically obtained instance, then thegetAnnotated()
method returns an instance ofjavax.enterprise.inject.spi.AnnotatedField
orjavax.enterprise.inject.spi.AnnotatedParameter
representing theInstance
injection point, depending upon whether the injection point is an injected field or a constructor/method parameter. -
The
isDelegate()
method returnstrue
if the injection point is a decorator delegate injection point, andfalse
otherwise. If the injection point represents a dynamically obtained instance thenisDelegate()
returns false. -
The
isTransient()
method returnstrue
if the injection point is a transient field, andfalse
otherwise. If the injection point represents a dynamically obtained instance then theisTransient()
method returnstrue
if theInstance
injection point is a transient field, andfalse
otherwise.
Occasionally, a bean with scope @Dependent
needs to access metadata relating to the object into which it is injected. For example, the following producer method creates injectable Logger
s. The log category of a Logger
depends upon the class of the object into which it is injected:
@Produces Logger createLogger(InjectionPoint injectionPoint) {
return Logger.getLogger( injectionPoint.getMember().getDeclaringClass().getName() );
}
The container must provide a bean with scope @Dependent
, bean type InjectionPoint
and qualifier @Default
, allowing dependent objects, as defined in Dependent objects, to obtain information about the injection point to which they belong. The built-in implementation must be a passivation capable dependency, as defined in Passivation capable dependencies.
If a bean that declares any scope other than @Dependent
has an injection point of type InjectionPoint
and qualifier @Default
, the container automatically detects the problem and treats it as a definition error.
If a disposer method has an injection point of type InjectionPoint
and qualifier Default
, the container automatically detects the problem and treats it as a definition error.
If a class supporting injection that is not a bean has an injection point of type InjectionPoint
and qualifier @Default
, the container automatically detects the problem and treats it as a definition error.
5.5.8. Bean metadata
The container must provide beans allowing a bean instance to obtain a Bean, Interceptor or Decorator instance containing its metadata.
a) Bean with scope @Dependent, qualifier @Default and type Bean can be injected into any bean instance.
- BuiltinMetadataBeanTest.testBeanMetadata()
- BuiltinMetadataBeanTest.testProducerMethodMetadata()
b) Bean with scope @Dependent, qualifier @Default and type Interceptor can be injected into any interceptor instance.
- BuiltinMetadataSessionBeanTest.testInterceptorMetadata()
- BuiltinMetadataBeanTest.testInterceptorMetadata()
c) Bean with scope @Dependent, qualifier @Default and type Decorator which can be injected into any decorator instance.
- BuiltinMetadataSessionBeanTest.testDecoratorMetadata()
- BuiltinMetadataBeanTest.testDecoratorMetadata()
Additionally, the container must provide beans allowing interceptors and decorators to obtain information about the beans they intercept and decorate.
d) Bean with scope @Dependent, qualifier @Intercepted and type Bean which can be injected into any interceptor instance.
- BuiltinMetadataSessionBeanTest.testInterceptorMetadata()
- BuiltinMetadataBeanTest.testInterceptorMetadata()
e) Bean with scope @Dependent, qualifier @Decorated and type Bean can be injected into any decorator instance.
- BuiltinMetadataSessionBeanTest.testDecoratorMetadata()
- BuiltinMetadataBeanTest.testDecoratorMetadata()
f) These beans are passivation capable dependencies, as defined in Section 6.6.2, "Passivation capable dependencies".
- BuiltinMetadataSessionBeanTest.testInterceptorMetadata()
- BuiltinMetadataSessionBeanTest.testDecoratorMetadata()
- BuiltinMetadataBeanTest.testBeanMetadata()
- BuiltinMetadataBeanTest.testProducerMethodMetadata()
- BuiltinMetadataBeanTest.testInterceptorMetadata()
- BuiltinMetadataBeanTest.testDecoratorMetadata()
h) If an Interceptor instance is injected into a bean instance other than an interceptor instance, the container automatically detects the problem and treats it as a definition error.
- BuiltinInterceptorInjectionTest.testDeploymentFails()
i) If a Decorator instance is injected into a bean instance other than a decorator instance, the container automatically detects the problem and treats it as a definition error.
- BuiltinDecoratorInjectionTest.testDeploymentFails()
r) If a Bean instance with qualifier @Intercepted is injected into a bean instance other than an interceptor instance, the container automatically detects the problem and treats it as a definition error.
- InterceptedBeanConstructorInjectionTest.testDeploymentFails()
- InterceptedBeanInitializerInjectionTest.testDeploymentFails()
- InterceptedBeanFieldInjectionTest.testDeploymentFails()
s) If a Bean instance with qualifier @Decorated is injected into a bean instance other than an interceptor instance, the container automatically detects the problem and treats it as a definition error.
- DecoratedBeanConstructorInjectionTest.testDeploymentFails()
- DecoratedBeanInitializerInjectionTest.testDeploymentFails()
- DecoratedBeanFieldInjectionTest.testDeploymentFails()
The injection of bean metadata is restricted.
j) If the injection point is a field, an initializer method parameter or a bean constructor, with qualifier @Default and type parameter of the injected Bean is not the same as the type declaring the injection point, the container automatically detects the problem and treats it as a definition error.
- BeanTypeParamConstructorTest.testDeploymentFails()
- BeanTypeParamFieldTest.testDeploymentFails()
- BeanTypeParamInitializerTest.testDeploymentFails()
k) If the injection point is a field, an initializer method parameter or a bean constructor, with qualifier @Default and type parameter of the injected Interceptor is not the same as the type declaring the injection point, the container automatically detects the problem and treats it as a definition error.
- InterceptorTypeParamConstructorTest.testDeploymentFails()
- InterceptorTypeParamInitializerTest.testDeploymentFails()
- InterceptorTypeParamFieldTest.testDeploymentFails()
l) If the injection point is a field, an initializer method parameter or a bean constructor, with qualifier @Default and type parameter of the injected Decorator is not the same as the type declaring the injection point, the container automatically detects the problem and treats it as a definition error.
- DecoratorTypeParamInitializerTest.testDeploymentFails()
- DecoratorTypeParamConstructorTest.testDeploymentFails()
- DecoratorTypeParamFieldTest.testDeploymentFails()
m) If the injection point is a field, an initializer method parameter or a bean constructor of an interceptor, with qualifier @Intercepted and the type parameter of the injected Bean is not an unbounded wildcard, the container automatically detects the problem and treats it as a definition error.
- InterceptedBeanTypeParamFieldTest.testDeploymentFails()
- InterceptedBeanTypeParamConstructorTest.testDeploymentFails()
- InterceptedBeanTypeParamInitializerTest.testDeploymentFails()
n) If he injection point is a field, an initializer method parameter or a bean constructor of a decorator, with qualifier @Decorated and the type parameter of the injected Bean is not the same as the delegate type, the container automatically detects the problem and treats it as a definition error.
- DecoratoredBeanTypeParamFieldTest.testDeploymentFails()
- DecoratoredBeanTypeParamConstructorTest.testDeploymentFails()
- DecoratoredBeanTypeParamInitializerTest.testDeploymentFails()
o) If the injection point is a producer method parameter and the type parameter of the injected Bean is not the same as the producer method return type, the container automatically detects the problem and treats it as a definition error.
- BeanTypeParamProducerTest.testDeploymentFails()
p) If the injection point is a disposer method parameter then no Bean instance can be injected, the container automatically detects the problem and treats it as a definition error.
- BeanTypeParamDisposerTest.testDeploymentFails()
The interfaces Bean
, Interceptor
and Decorator
provide metadata about a bean.
The container must provide beans allowing a bean instance to obtain a Bean
, Interceptor
or Decorator
instance containing its metadata:
-
a bean with scope
@Dependent
, qualifier@Default
and typeBean
which can be injected into any bean instance -
a bean with scope
@Dependent
, qualifier@Default
and typeInterceptor
which can be injected into any interceptor instance -
a bean with scope
@Dependent
, qualifier@Default
and typeDecorator
which can be injected into any decorator instance
Additionally, the container must provide beans allowing interceptors and decorators to obtain information about the beans they intercept and decorate:
-
a bean with scope
@Dependent
, qualifier@Intercepted
and typeBean
which can be injected into any interceptor instance, and -
a bean with scope
@Dependent
, qualifier@Decorated
and typeBean
which can be injected into any decorator instance.
These beans are passivation capable dependencies, as defined in Passivation capable dependencies.
If an Interceptor
instance is injected into a bean instance other than an interceptor instance, the container automatically detects the problem and treats it as a definition error.
If a Decorator
instance is injected into a bean instance other than a decorator instance, the container automatically detects the problem and treats it as a definition error.
If a Bean
instance with qualifier @Intercepted
is injected into a bean instance other than an interceptor instance, the container automatically detects the problem and treats it as a definition error.
If a Bean
instance with qualifier @Decorated
is injected into a bean instance other than a decorator instance, the container automatically detects the problem and treats it as a definition error.
The injection of bean metadata is restricted. If:
-
the injection point is a field, an initializer method parameter or a bean constructor, with qualifier
@Default
, then the type parameter of the injectedBean
,Interceptor
orDecorator
must be the same as the type declaring the injection point, or -
the injection point is a field, an initializer method parameter or a bean constructor of an interceptor, with qualifier
@Intercepted
, then the type parameter of the injectedBean
must be an unbounded wildcard, or -
the injection point is a field, an initializer method parameter or a bean constructor of a decorator, with qualifier
@Decorated
, then the type parameter of the injectedBean
must be the same as the delegate type, or -
the injection point is a producer method parameter then the type parameter of the injected
Bean
must be the same as the producer method return type, or -
the injection point is a parameter of a disposer method then the container automatically detects the problem and treats it as a definition error.
Otherwise, the container automatically detects the problem and treats it as a definition error.
@Named("Order") public class OrderProcessor {
@Inject Bean<OrderProcessor> bean;
public void getBeanName() {
return bean.getName();
}
}
5.6. Programmatic lookup
aa) An instance of the javax.enterprise.inject.Instance interface may be injected.
- DynamicLookupTest.testObtainsInjectsInstanceOfInstance()
ba) The method javax.enterprise.inject.Instance.get() returns a contextual reference.
- DynamicLookupTest.testGetMethod()
ca) Any combination of qualifiers may be specified at the injection point.
- DynamicLookupTest.testGetMethod()
da) The @Any qualifier may be used to allow the application to specify qualifiers dynamically.
- DynamicLookupTest.testIsAmbiguous()
e) The @New qualifier may be used, allowing the application to obtain a @New qualified bean, as defined in Section 3.12, "@New qualified beans".
- DynamicLookupTest.testNewBean()
In certain situations, injection is not the most convenient way to obtain a contextual reference. For example, it may not be used when:
-
the bean type or qualifiers vary dynamically at runtime, or
-
depending upon the deployment, there may be no bean which satisfies the type and qualifiers, or
-
we would like to iterate over all beans of a certain type.
In these situations, an instance of the javax.enterprise.inject.Instance
interface may be injected:
@Inject Instance<PaymentProcessor> paymentProcessor;
The method get()
returns a contextual reference:
PaymentProcessor pp = paymentProcessor.get();
Any combination of qualifiers may be specified at the injection point:
@Inject @PayBy(CHEQUE) Instance<PaymentProcessor> chequePaymentProcessor;
Or, the @Any
qualifier may be used, allowing the application to specify qualifiers dynamically:
@Inject @Any Instance<PaymentProcessor> anyPaymentProcessor;
...
Annotation qualifier = synchronously ? new SynchronousQualifier() : new AsynchronousQualifier();
PaymentProcessor pp = anyPaymentProcessor.select(qualifier).get().process(payment);
In this example, the returned bean has qualifier @Synchronous
or @Asynchronous
depending upon the value of synchronously
.
Finally, the @New
qualifier may be used, allowing the application to obtain a @New
qualified bean, as defined in @New
qualified beans:
@Inject @New(ChequePaymentProcessor.class) Instance<PaymentProcessor> chequePaymentProcessor;
It’s even possible to iterate over a set of beans:
@Inject @Any Instance<PaymentProcessor> anyPaymentProcessor;
...
for (PaymentProcessor pp: anyPaymentProcessor) pp.test();
5.6.1. The Instance
interface
aa) The Instance interface provides a method for obtaining instances of beans with a specified combination of required type and qualifiers, and inherits the ability to iterate beans with that combination of required type and qualifiers from java.lang.Iterable.
- DynamicLookupTest.testGetMethod()
- DynamicLookupTest.testIteratorMethod()
ab) For an injected Instance, the required type is the type parameter specified at the injection point, and the required qualifiers are the qualifiers specified at the injection point.
- DynamicLookupTest.testGetMethod()
ba) The select() method returns a child Instance for a given required type and additional required qualifiers. If no required type is given, the required type is the same as the parent.
- DynamicLookupTest.testIteratorMethod()
c) If an injection point of raw type Instance is defined, the container automatically detects the problem and treats it as a definition error.
- RawInstanceDisposerInjectionTest.testDefinitionError()
- RawInstanceProcessInjectionPointTest.testDefinitionError()
- RawInstanceFieldInjectionTest.testDefinitionError()
- RawInstanceCustomBeanTest.testDefinitionError()
- RawInstanceInitMethodInjectionTest.testDefinitionError()
- RawInstanceObserverInjectionTest.testDefinitionError()
- RawInstanceProducerMethodInjectionTest.testDefinitionError()
- RawInstanceConstructorInjectionTest.testDefinitionError()
da) If two instances of the same qualifier type are passed to select(), an IllegalArgumentException is thrown.
- DynamicLookupTest.testDuplicateBindingsThrowsException()
e) If an instance of an annotation that is not a qualifier type is passed to select(), an IllegalArgumentException is thrown.
- DynamicLookupTest.testNonBindingThrowsException()
fa) The get() method must identify a bean that has the required type and required qualifiers and is eligible for injection into the class into which the parent Instance was injected, according to the rules of typesafe resolution, as defined in Section 5.2, "Typesafe resolution", resolving ambiguities according to Section 5.2.1, "Unsatisfied and ambiguous dependencies".
- DynamicLookupTest.testGetMethod()
fba) If typesafe resolution results in an unsatisfied dependency, throw an UnsatisfiedResolutionException.
- DynamicLookupTest.testUnsatisfiedDependencyThrowsException()
fbb) If typesafe resolution results in an unresolvable ambiguous dependency, throw an AmbiguousResolutionException.
- DynamicLookupTest.testAmbiguousDependencyThrowsException()
fc) Otherwise, obtain a contextual reference for the bean and the required type, as defined in Section 6.5.3, "Contextual reference for a bean".
- DynamicLookupTest.testGetMethod()
ja) The iterator() method must identify the set of beans that have the required type and required qualifiers and are eligible for injection into the class into which the parent Instance was injected, according to the rules of typesafe resolution, as defined in Section 5.2, "Typesafe resolution".
- DynamicLookupTest.testIteratorMethod()
- DynamicLookupTest.testAlternatives()
ka) The iterator() method must return an Iterator, that iterates over the set of contextual references for the resulting beans and required type, as defined in Section 6.5.3, "Contextual reference for a bean".
- DynamicLookupTest.testIteratorMethod()
- DynamicLookupTest.testAlternatives()
l) The method isUnsatisfied() returns true if there is no bean that has the required type and qualifiers and is eligible for injection into the class into which the parent Instance was injected, or false otherwise.
- DynamicLookupTest.testIsUnsatisfied()
m) The method isAmbiguous() returns true if there is more than one bean that has the required type and qualifiers and is eligible for injection into the class into which the parent Instance was injected, or false otherwise.
- DynamicLookupTest.testAlternatives()
- DynamicLookupTest.testIsAmbiguous()
The method destroy() instructs the container to destroy the instance. The bean instance passed to destroy() should be a dependent scoped bean instance, or a client proxy for a normal scoped bean. Applications are encouraged to always call destroy() when they no longer require an instance obtained from Instance.
n) Test dependent scoped bean instance passed to destroy().
- DestroyingDependentInstanceTest.testDestroyingDependentInstances()
- DestroyingDependentInstanceTest.testDestroyingInterceptedDependentBean()
o) Test client proxy passed to destroy().
- DestroyingNormalScopedInstanceTest.testApplicationScopedComponent()
- DestroyingNormalScopedInstanceTest.testRequestScopedComponent()
- DestroyingNormalScopedInstanceTest.testCustomScopedComponent()
- DestroyingNormalScopedInstanceTest.testContextDestroyCalled()
- DestroyingNormalScopedInstanceTest.testNullParameter()
p) Test UnsupportedOperationException is thrown when if the active context object for the scope type of the bean does not support destroying bean instances.
- DestroyingNormalScopedInstanceTest.testUnsupportedOperationExceptionThrownIfUnderlyingContextNotAlterable()
The Instance
interface provides a method for obtaining instances of beans with a specified combination of required type and qualifiers, and inherits the ability to iterate beans with that combination of required type and qualifiers from java.lang.Iterable
:
public interface Instance<T> extends Iterable<T>, Provider<T> {
public Instance<T> select(Annotation... qualifiers);
public <U extends T> Instance<U> select(Class<U> subtype, Annotation... qualifiers);
public <U extends T> Instance<U> select(TypeLiteral<U> subtype, Annotation... qualifiers);
public boolean isUnsatisfied();
public boolean isAmbiguous();
public void destroy(T instance);
}
For an injected Instance
:
-
the required type is the type parameter specified at the injection point, and
-
the required qualifiers are the qualifiers specified at the injection point.
For example, this injected Instance
has required type PaymentProcessor
and required qualifier @Any
:
@Inject @Any Instance<PaymentProcessor> anyPaymentProcessor;
The select()
method returns a child Instance
for a given required type and additional required qualifiers. If no required type is given, the required type is the same as the parent.
For example, this child Instance
has required type AsynchronousPaymentProcessor
and additional required qualifier @Asynchronous
:
Instance<AsynchronousPaymentProcessor> async = anyPaymentProcessor.select(
AsynchronousPaymentProcessor.class, new AsynchronousQualifier() );
If an injection point of raw type Instance
is defined, the container automatically detects the problem and treats it as a definition error.
If two instances of the same qualifier type are passed to select()
, an IllegalArgumentException
is thrown.
If an instance of an annotation that is not a qualifier type is passed to select()
, an IllegalArgumentException
is thrown.
The get()
method must:
-
Identify a bean that has the required type and required qualifiers and is eligible for injection into the class into which the parent
Instance
was injected, according to the rules of typesafe resolution, as defined in Performing typesafe resolution, resolving ambiguities according to Unsatisfied and ambiguous dependencies. -
If typesafe resolution results in an unsatisfied dependency, throw an
UnsatisfiedResolutionException
. If typesafe resolution results in an unresolvable ambiguous dependency, throw anAmbiguousResolutionException
. -
Otherwise, obtain a contextual reference for the bean and the required type, as defined in Contextual reference for a bean.
The iterator()
method must:
-
Identify the set of beans that have the required type and required qualifiers and are eligible for injection into the class into which the parent
Instance
was injected, according to the rules of typesafe resolution, as defined in Performing typesafe resolution, resolving ambiguities according to Unsatisfied and ambiguous dependencies. -
Return an
Iterator
, that iterates over the set of contextual references for the resulting beans and required type, as defined in Contextual reference for a bean.
The method isUnsatisfied()
returns true
if there is no bean that has the required type and qualifiers and is eligible for injection into the class into which the parent Instance
was injected, or false
otherwise.
The method isAmbiguous()
returns true
if there is more than one bean that has the required type and qualifiers and is eligible for injection into the class into which the parent Instance
was injected, or false
otherwise.
The method destroy()
instructs the container to destroy the instance. The bean instance passed to destroy()
should be a dependent scoped bean instance, or a client proxy for a normal scoped bean. Applications are encouraged to always call destroy()
when they no longer require an instance obtained from Instance
. All built-in normal scoped contexts support destroying bean instances. An UnsupportedOperationException
is thrown if the active context object for the scope type of the bean does not support destroying bean instances.
5.6.2. The built-in Instance
a) The container must provide a built-in bean with Instance<X> and Provider<X> for every legal bean type x in its set of bean types.
Note: FIXME - see also CDI-232.
b) The container must provide a built-in bean with every qualifier type in its set of qualifier types.
Note: FIXME - see also CDI-232.
d) The container must provide a built-in bean with scope @Dependent.
- BuiltinInstanceTest.testScopeOfBuiltinInstance()
e) The container must provide a built-in bean with no bean name.
- BuiltinInstanceTest.testNameOfBuiltinInstance()
f) The container must provide a built-in bean with an implementation provided automatically by the container.
- BuiltinInstanceTest.testInstanceProvidedForEveryLegalBeanType()
g) The built-in implementation must be a passivation capable dependency, as defined in Section 6.6.2, "Passivation capable dependencies".
- BuiltinInstanceTest.testInstanceIsPassivationCapable()
The container must provide a built-in bean with:
-
Instance<X>
andProvider<X>
for every legal bean typeX
in its set of bean types, -
every qualifier type in its set of qualifier types,
-
scope
@Dependent
, -
no bean name, and
-
an implementation provided automatically by the container.
The built-in implementation must be a passivation capable dependency, as defined in Passivation capable dependencies.
5.6.3. Using AnnotationLiteral
and TypeLiteral
a) Test javax.enterprise.util.AnnotationLiteral when using Instance.select() to specify qualifiers.
- DynamicLookupTest.testIteratorMethod()
b) Test javax.enterprise.util.TypeLiteral when specifying a parameterized type with actual type parameters when calling Instance.select().
- DynamicLookupTest.testNewBean()
javax.enterprise.util.AnnotationLiteral
makes it easier to specify qualifiers when calling select()
:
public PaymentProcessor getSynchronousPaymentProcessor(PaymentMethod paymentMethod) {
class SynchronousQualifier extends AnnotationLiteral<Synchronous>
implements Synchronous {}
class PayByQualifier extends AnnotationLiteral<PayBy>
implements PayBy {
public PaymentMethod value() { return paymentMethod; }
}
return anyPaymentProcessor.select(new SynchronousQualifier(), new PayByQualifier()).get();
}
javax.enterprise.util.TypeLiteral
makes it easier to specify a parameterized type with actual type parameters when calling select()
:
public PaymentProcessor<Cheque> getChequePaymentProcessor() {
PaymentProcessor<Cheque> pp = anyPaymentProcessor
.select( new TypeLiteral<PaymentProcessor<Cheque>>() {} ).get();
}
6. Scopes and contexts
Associated with every scope type is a context object. The context object determines the lifecycle and visibility of instances of all beans with that scope. In particular, the context object defines:
-
When a new instance of any bean with that scope is created
-
When an existing instance of any bean with that scope is destroyed
-
Which injected references refer to any instance of a bean with that scope
The context implementation collaborates with the container via the Context
and Contextual
interfaces to create and destroy contextual instances.
6.1. The Contextual
interface
aa) If an exception occurs while creating an instance, the exception is rethrown by the create() method. If the exception is a checked exception, it must be wrapped and rethrown as an (unchecked) CreationException.
- ProducerMethodLifecycleTest.testCreateRethrowsUncheckedException()
- ProducerMethodLifecycleTest.testCreateWrapsCheckedExceptionAndRethrows()
- SimpleBeanLifecycleTest.testCreationExceptionWrapsCheckedExceptionThrownFromCreate()
- SimpleBeanLifecycleTest.testUncheckedExceptionThrownFromCreateNotWrapped()
ab) If an exception occurs while destroying an instance, the exception must be caught by the destroy() method.
- SimpleBeanLifecycleTest.testContextualDestroyCatchesException()
ac) If the application invokes a contextual instance after it has been destroyed, the behavior is undefined.
Note: A statement about container specific behavior which is not spec defined
a) The container and portable extensions may define implementations of the Contextual interface that do not extend Bean, but it is not recommended that applications directly implement Contextual.
Note: Advice only
The interface javax.enterprise.context.spi.Contextual
defines operations to create and destroy contextual instances of a certain type. Any implementation of Contextual
is called a contextual type. In particular, the Bean
interface defined in The Bean
interface extends Contextual
, so all beans are contextual types.
public interface Contextual<T> {
public T create(CreationalContext<T> creationalContext);
public void destroy(T instance, CreationalContext<T> creationalContext);
}
-
create()
is responsible for creating new contextual instances of the type. -
destroy()
is responsible for destroying instances of the type. In particular, it is responsible for destroying all dependent objects of an instance.
If an exception occurs while creating an instance, the exception is rethrown by the create()
method. If the exception is a checked exception, it must be wrapped and rethrown as an (unchecked) CreationException
.
If an exception occurs while destroying an instance, the exception must be caught by the destroy()
method.
If the application invokes a contextual instance after it has been destroyed, the behavior is undefined.
The container and portable extensions may define implementations of the Contextual
interface that do not extend Bean
, but it is not recommended that applications directly implement Contextual
.
6.1.1. The CreationalContext
interface
ca) The interface javax.enterprise.context.spi.CreationalContext provides operations that are used by the Contextual implementation during instance creation and destruction.
Note: introductory text
d) push() registers an incompletely initialized contextual instance with the container. A contextual instance is considered incompletely initialized until it is returned by the create() method.
- SimpleBeanLifecycleTest.testCreateReturnsSameBeanPushed()
e) release() destroys all dependent objects, as defined in Section 6.4.1, "Dependent objects", of the instance which is being destroyed, by passing each dependent object to the destroy() method of its Contextual object.
- DependentContextTest.testCallingCreationalContextReleaseDestroysDependents()
f) The implementation of Contextual is not required to call push(). However, for certain bean scopes, invocation of push() between instantiation and injection helps the container minimize the use of client proxy objects (which would otherwise be required to allow circular dependencies).
g) If Contextual.create() calls push(), it must also return the instance passed to push().
- SimpleBeanLifecycleTest.testCreateReturnsSameBeanPushed()
h) Contextual.create() should use the given CreationalContext when obtaining contextual references to inject, as defined in Section 6.5.3, "Contextual reference for a bean", in order to ensure that any dependent objects are associated with the contextual instance that is being created.
Note: Advice
i) Contextual.destroy() should call release() to allow the container to destroy dependent objects of the contextual instance.
Note: Advice
The interface javax.enterprise.context.spi.CreationalContext
provides operations that are used by the Contextual
implementation during instance creation and destruction.
public interface CreationalContext<T> {
public void push(T incompleteInstance);
public void release();
}
-
push()
registers an incompletely initialized contextual instance the with the container. A contextual instance is considered incompletely initialized until it is returned by thecreate()
method. -
release()
destroys all dependent objects, as defined in Dependent objects, of the instance which is being destroyed, by passing each dependent object to thedestroy()
method of itsContextual
object.
The implementation of Contextual
is not required to call push()
. However, for certain bean scopes, invocation of push()
between instantiation and injection helps the container minimize the use of client proxy objects (which would otherwise be required to allow circular dependencies).
If Contextual.create()
calls push()
, it must also return the instance passed to push()
.
Contextual.create()
should use the given CreationalContext
when obtaining contextual references to inject, as defined in Contextual reference for a bean, in order to ensure that any dependent objects are associated with the contextual instance that is being created.
Contextual.destroy()
should call release()
to allow the container to destroy dependent objects of the contextual instance.
6.2. The Context
interface
aa) The javax.enterprise.context.spi.Context interface provides an operation for obtaining contextual instances with a particular scope of any contextual type.
Note: Introductory text
ab) The method getScope() returns the scope type of the context object.
- DependentContextTest.testContextScopeType()
ha) When a context object is active the isActive() method returns true. Otherwise, we say that the context object is inactive and the isActive() method returns false.
- DependentContextTest.testContextIsActive()
- DependentContextTest.testContextIsActiveWhenInvokingProducerMethod()
j) The Context.get() method may either return an existing instance of the given contextual type, or if no CreationalContext is given, return a null value, or if a CreationalContext is given, create a new instance of the given contextual type by calling Contextual.create() and return the new instance.
- NormalContextTest.testGetReturnsExistingInstance()
- GetWithNoCreationalContextTest.testGetWithoutCreationalContextReturnsNull()
- NormalContextTest.testGetReturnsExistingInstance()
- NormalContextTest.testGetWithCreationalContextReturnsNewInstance()
- SimpleBeanLifecycleTest.testContextCreatesNewInstanceForInjection()
k) The Context.get() method may either return an existing instance of the given contextual type, or if no CreationalContext is given, return a null value, or if a CreationalContext is given, create a new instance of the given contextual type by calling Contextual.create() and return the new instance.
- NormalContextTest.testGetReturnsExistingInstance()
- GetWithNoCreationalContextTest.testGetWithoutCreationalContextReturnsNull()
- NormalContextTest.testGetReturnsExistingInstance()
- NormalContextTest.testGetWithCreationalContextReturnsNewInstance()
- SimpleBeanLifecycleTest.testContextCreatesNewInstanceForInjection()
l) The Context.get() method may either return an existing instance of the given contextual type, or if no CreationalContext is given, return a null value, or if a CreationalContext is given, create a new instance of the given contextual type by calling Contextual.create() and return the new instance.
- NormalContextTest.testGetReturnsExistingInstance()
- GetWithNoCreationalContextTest.testGetWithoutCreationalContextReturnsNull()
- NormalContextTest.testGetReturnsExistingInstance()
- NormalContextTest.testGetWithCreationalContextReturnsNewInstance()
- SimpleBeanLifecycleTest.testContextCreatesNewInstanceForInjection()
m) If the context object is inactive, the get() method must throw a ContextNotActiveException.
- GetOnInactiveContextTest.testInvokingGetOnInactiveContextFails()
na) The get() method may not return a null value unless no CreationalContext is given, or Contextual.create() returns a null value.
- GetWithNoCreationalContextTest.testGetWithoutCreationalContextReturnsNull()
- NormalContextTest.testGetMayNotReturnNullUnlessContextualCreateReturnsNull()
nb) The get() method may not return a null value unless no CreationalContext is given, or Contextual.create() returns a null value.
- GetWithNoCreationalContextTest.testGetWithoutCreationalContextReturnsNull()
- NormalContextTest.testGetMayNotReturnNullUnlessContextualCreateReturnsNull()
o) The get() method may not create a new instance of the given contextual type unless a CreationalContext is given.
- GetFromContextualTest.testGetMayNotCreateNewInstanceUnlessCreationalContextGiven()
s) When the container calls get() for a context that is associated with a passivating scope it must ensure that the given instance of Contextual and the instance of CreationalContext, if given, are serializable.
- CustomPassivatingScopeCalledWithSerializableParametersTest.testWithImplicitBean()
- CustomPassivatingScopeCalledWithSerializableParametersTest.testWithExtensionProvidedBean()
t) The destroy() method destroys an existing contextual instance, removing it from the context instance.
- AlterableContextTest.testApplicationScopedComponent()
- AlterableContextTest.testRequestScopedComponent()
- AlterableContextTest.testCustomScopedComponent()
- AlterableContextTest.testNothingHappensIfNoInstanceToDestroy()
p) The context object is responsible for destroying any contextual instance it creates by passing the instance to the destroy() method of the Contextual object representing the contextual type.
- ContextDestroysBeansTest.testContextDestroysBeansWhenDestroyed()
q) A destroyed instance must not subsequently be returned by the get() method.
- DestroyedInstanceReturnedByGetTest.testDestroyedInstanceMustNotBeReturnedByGet()
r) The context object must pass the same instance of CreationalContext to Contextual.destroy() that it passed to Contextual.create() when it created the instance.
- DestroyForSameCreationalContextTest.testDestroyForSameCreationalContextOnly()
- DestroyForSameCreationalContext2Test.testDestroyForSameCreationalContextOnly()
The javax.enterprise.context.spi.Context
interface provides an operation for obtaining contextual instances with a particular scope of any contextual type. Any instance of Context
is called a context object.
The context object is responsible for creating and destroying contextual instances by calling operations of the Contextual
interface.
The Context
interface is called by the container and may be called by portable extensions. It should not be called directly by the application.
public interface Context {
public Class<? extends Annotation> getScope();
boolean isActive();
public <T> T get(Contextual<T> bean);
public <T> T get(Contextual<T> bean, CreationalContext<T> creationalContext);
}
public interface AlterableContext extends Context {
public void destroy(Contextual<?> contextual);
}
The method getScope()
returns the scope type of the context object.
A context object may be defined for any of the built-in scopes and registered with the container using the AfterBeanDiscovery
event as described in AfterBeanDiscovery
event.
At a particular point in the execution of the program a context object may be active with respect to the current thread. When a context object is active the isActive()
method returns true
. Otherwise, we say that the context object is inactive and the isActive()
method returns false
.
The get()
method obtains contextual instances of the contextual type represented by the given instance of Contextual
. The get()
method may either:
-
return an existing instance of the given contextual type, or
-
if no
CreationalContext
is given, return a null value, or -
if a
CreationalContext
is given, create a new instance of the given contextual type by callingContextual.create()
, passing the givenCreationalContext
, and return the new instance.
The get()
method may not return a null value unless no CreationalContext
is given, or Contextual.create()
returns a null value.
The get()
method may not create a new instance of the given contextual type unless a CreationalContext
is given.
The destroy()
method destroys an existing contextual instance, removing it from the context instance.
The AlterableContext
interface was introduced in CDI 1.1 to allow bean instances to be destroyed by the application. Extensions providing context implementations for normal scopes should implement AlterableContext
instead of Context
.
If the context object is inactive, the get()
and destroy()
methods must throw a ContextNotActiveException
.
When the container calls get()
or destroy()
for a context that is associated with a passivating scope it must ensure that the given instance of Contextual
and the instance of CreationalContext
, if given, are serializable.
The context object is responsible for destroying any contextual instance it creates by passing the instance to the destroy()
method of the Contextual
object representing the contextual type. A destroyed instance must not subsequently be returned by the get()
method.
The context object must pass the same instance of CreationalContext
to Contextual.destroy()
that it passed to Contextual.create()
when it created the instance.
6.3. Normal scopes and pseudo-scopes
a) There may be no more than one mapped instance of a context object per contextual type per thread
Note: Not testable through API
b) A context may be associated with one or more threads
Note: A statement of intent
c) The get() operation of the Context object for an active normal scope returns the current instance of the given contextual type.
- NormalContextTest.testGetReturnsExistingInstance()
d) When a context is destroyed, all mapped instances belonging to that context are destroyed by passing them to the Contextual.destroy() method.
- ContextDestroysBeansTest.testContextDestroysBeansWhenDestroyed()
e) Contexts with normal scopes must obey the following rule: Suppose beans A, B and Z all have normal scopes. Suppose A has an injection point x, and B has an injection point y. Suppose further that both x and y resolve to bean Z according to the typesafe resolution algorithm. If a is the current instance of A, and b is the current instance of B, then both a.x and b.y refer to the same instance of Z. This instance is the current instance of Z.
- NormalContextTest.testSameNormalScopeBeanInjectedEverywhere()
ea) All normal scopes must be explicitly declared @NormalScope, to indicate to the container that a client proxy is required.
Note: A statement of intent
fa) All pseudo-scopes must be explicitly declared @Scope, to indicate to the container that no client proxy is required.
Note: A statement of intent
g) All scopes defined by this specification, except for the @Dependent pseudo-scope, are normal scopes
Note: A statement of intent
Most scopes are normal scopes. The context object for a normal scope type is a mapping from each contextual type with that scope to an instance of that contextual type. There may be no more than one mapped instance per contextual type per thread. The set of all mapped instances of contextual types with a certain scope for a certain thread is called the context for that scope associated with that thread.
A context may be associated with one or more threads. A context with a certain scope is said to propagate from one point in the execution of the program to another when the set of mapped instances of contextual types with that scope is preserved.
The context associated with the current thread is called the current context for the scope. The mapped instance of a contextual type associated with a current context is called the current instance of the contextual type.
The get()
operation of the context object for an active normal scope returns the current instance of the given contextual type.
At certain points in the execution of the program a context may be destroyed. When a context is destroyed, all mapped instances belonging to that context are destroyed by passing them to the Contextual.destroy()
method.
Contexts with normal scopes must obey the following rule:
Suppose beans A, B and Z all have normal scopes. Suppose A has an injection point x, and B has an injection point y. Suppose further that both x and y resolve to bean Z according to the rules of typesafe resolution. If a is the current instance of A, and b is the current instance of B, then both a.x and b.y refer to the same instance of Z. This instance is the current instance of Z.
Any scope that is not a normal scope is called a pseudo-scope. The concept of a current instance is not well-defined in the case of a pseudo-scope.
All normal scopes must be explicitly declared @NormalScope
, to indicate to the container that a client proxy is required.
All pseudo-scopes must be explicitly declared @Scope
, to indicate to the container that no client proxy is required.
All scopes defined by this specification, except for the @Dependent
pseudo-scope, are normal scopes.
6.4. Dependent pseudo-scope
a) When a bean is declared to have @Dependent scope, no injected instance of the bean is ever shared between multiple injection points.
- DependentContextTest.testInstanceNotSharedBetweenInjectionPoints()
b) When a bean is declared to have @Dependent scope, any instance of the bean injected into an object that is being created by the container is bound to the lifecycle of the newly created object.
- DependentContextTest.testDestroyingSimpleParentDestroysDependents()
- DependentContextTest.testDestroyingManagedParentDestroysDependentsOfSameBean()
When a bean is declared to have @Dependent scope, any instance of the bean that receives a producer method, producer field, disposer method or observer method invocation exists to service that invocation only
da) Test with a producer method.
- DependentContextTest.testInstanceUsedForProducerMethodNotShared()
db) Test with a producer field.
- DependentContextTest.testInstanceUsedForProducerFieldNotShared()
dc) Test with a disposer method.
- DependentContextTest.testInstanceUsedForDisposalMethodNotShared()
dd) Test with an observer method.
- DependentContextTest.testInstanceUsedForObserverMethodNotShared()
dg) When a bean is declared to have @Dependent scope, any instance of the bean injected into method parameters of a disposer method or observer method exists to service the method invocation only (except for observer methods of container lifecycle events).
- DependentContextTest.testInstanceUsedForDisposalMethodNotShared()
- DependentContextTest.testInstanceUsedForObserverMethodNotShared()
e) Every invocation of the get() operation of the Context object for the @Dependent scope with a CreationalContext returns a new instance of the given bean.
- DependentContextTest.testContextGetWithCreationalContextReturnsNewInstance()
f) Every invocation of the get() operation of the Context object for the @Dependent scope with no CreationalContext returns a null value.
- DependentContextTest.testContextGetWithCreateFalseReturnsNull()
g) The @Dependent scope is always active.
- DependentContextTest.testContextIsActive()
- DependentContextTest.testContextIsActiveWhenInvokingProducerMethod()
- DependentContextTest.testContextIsActiveWhenInvokingDisposalMethod()
- DependentContextTest.testContextIsActiveWhenInvokingProducerField()
- DependentContextTest.testContextIsActiveWhenCreatingObserverMethodInstance()
- DependentContextTest.testContextIsActiveWhenEvaluatingElExpression()
- DependentContextTest.testContextIsActiveDuringBeanCreation()
- DependentContextTest.testContextIsActiveDuringInjection()
The @Dependent
scope type is a pseudo-scope. Beans declared with scope type @Dependent
behave differently to beans with other built-in scope types.
When a bean is declared to have @Dependent
scope:
-
No injected instance of the bean is ever shared between multiple injection points.
-
Any instance of the bean injected into an object that is being created by the container is bound to the lifecycle of the newly created object.
-
Any instance of the bean that receives a producer method, producer field, disposer method or observer method invocation exists to service that invocation only.
-
Any instance of the bean injected into method parameters of a disposer method or observer method exists to service the method invocation only (except for observer methods of container lifecycle events).
Every invocation of the get()
operation of the Context
object for the @Dependent
scope with a CreationalContext
returns a new instance of the given bean.
Every invocation of the get()
operation of the Context
object for the @Dependent
scope with no CreationalContext
returns a null value.
The @Dependent
scope is always active.
6.4.1. Dependent objects
Instances of interceptors or decorators with scope @Dependent are dependent objects of the bean instance they decorate.
aa) Test with a @Dependent-scoped interceptor.
- DependentContextTest.testDependentScopedInterceptorsAreDependentObjectsOfBean()
ab) Test with a @Dependent-scoped decorator.
- DependentContextTest.testDependentScopedDecoratorsAreDependentObjectsOfBean()
An instance of a bean with scope @Dependent injected into a field, bean constructor or initializer method is a dependent object of the bean into which it was injected.
ga) Test with @Dependent-scoped bean injected into field.
- DependentContextTest.testInstanceNotSharedBetweenInjectionPoints()
- DependentContextTest.testDependentBeanIsDependentObjectOfBeanInjectedInto()
gb) Test with @Dependent-scoped bean injected into bean constructor.
- DependentContextTest.testDependentBeanIsDependentObjectOfBeanInjectedInto()
gc) Test with @Dependent-scoped bean injected into initializer method.
- DependentContextTest.testDependentBeanIsDependentObjectOfBeanInjectedInto()
h) An instance of a bean with scope @Dependent injected into a producer method is a dependent object of the producer method bean instance that is being produced.
- DependentContextTest.testDependentsDestroyedWhenProducerMethodCompletes()
i) An instance of a bean with scope @Dependent obtained by direct invocation of an Instance is a dependent object of the instance of Instance.
- BuiltinInstanceDependentObjectTest.testInstanceDependentObject()
Many instances of beans with scope @Dependent
belong to some other bean and are called dependent objects.
-
Instances of decorators and interceptors are dependent objects of the bean instance they decorate.
-
An instance of a bean with scope
@Dependent
injected into a field, bean constructor or initializer method is a dependent object of the bean into which it was injected. -
An instance of a bean with scope
@Dependent
injected into a producer method is a dependent object of the producer method bean instance that is being produced. -
An instance of a bean with scope
@Dependent
obtained by direct invocation of anInstance
is a dependent object of the instance ofInstance
.
6.4.2. Destruction of objects with scope @Dependent
The container must ensure that all dependent objects of a non-contextual instance of a bean are destroyed when the instance is destroyed by the container.
aaaa) Test with a managed bean.
- DependentContextTest.testDestroyingSimpleParentDestroysDependents()
- DependentContextTest.testDestroyingManagedParentDestroysDependentsOfSameBean()
The container must ensure that all @Dependent scoped contextual instances injected into method parameters of a disposer method or observer method of any other event are destroyed when the invocation completes.
ccc) Check disposer method.
- DependentContextTest.testDependentsDestroyedWhenDisposerMethodCompletes()
- DependentContextTest.testDependentsDestroyedWhenDisposerMethodCompletes()
ccd) Check observer method.
- DependentContextTest.testDependentsDestroyedWhenObserverMethodEvaluationCompletes()
- BuiltinInstanceDependentObjectTest.testInstanceDependentObject()
- DependentContextTest.testDependentsDestroyedWhenObserverMethodEvaluationCompletes()
The container must ensure that all @Dependent scoped contextual instances injected into method or constructor parameters that are annotated with @TransientReference are destroyed when the invocation completes.
fa) Test producer method parameter.
- DependentTransientReferenceDestroyedTest.testProducerMethod()
fb) Test initializer method parameter.
- DependentTransientReferenceDestroyedTest.testConstructorAndInitializer()
fc) Test bean constructor parameter.
- DependentTransientReferenceDestroyedTest.testConstructorAndInitializer()
The container must ensure that any @Dependent scoped contextual instance created to receive a producer method, producer field, disposer method or observer method invocation is destroyed when the invocation completes.
ddd) Check producer method.
- DependentContextTest.testDependentsDestroyedWhenProducerMethodCompletes()
dde) Check producer field.
- DependentContextTest.testDependentsDestroyedWhenProducerFieldCompletes()
ddf) Check disposer method.
- DependentContextTest.testDependentsDestroyedWhenDisposerMethodCompletes()
- DependentContextTest.testDependentsDestroyedWhenDisposerMethodCompletes()
ddg) Check observer method.
- DependentContextTest.testDependentsDestroyedWhenObserverMethodEvaluationCompletes()
- BuiltinInstanceDependentObjectTest.testInstanceDependentObject()
- DependentContextTest.testDependentsDestroyedWhenObserverMethodEvaluationCompletes()
e) The container is permitted to destroy any @Dependent scoped contextual instance at any time if the instance is no longer referenced by the application (excluding weak, soft and phantom references).
Note: In other words this is unspecified
Dependent objects of a contextual instance are destroyed when Contextual.destroy()
calls CreationalContext.release()
, as defined in The CreationalContext
interface.
Additionally, the container must ensure that:
-
all dependent objects of a non-contextual instance of a bean are destroyed when the instance is destroyed by the container,
-
all
@Dependent
scoped contextual instances injected into method parameters of a disposer method or an observer method are destroyed when the invocation completes, -
all
@Dependent
scoped contextual instances injected into method or constructor parameters that are annotated with@TransientReference
are destroyed when the invocation completes, and -
any
@Dependent
scoped contextual instance created to receive a producer method, producer field, disposer method or observer method invocation is destroyed when the invocation completes.
Finally, the container is permitted to destroy any @Dependent
scoped contextual instance at any time if the instance is no longer referenced by the application (excluding weak, soft and phantom references).
6.5. Contextual instances and contextual references
The Context
object is the ultimate source of the contextual instances that underly contextual references.
6.5.1. The active context object for a scope
a) From time to time, the container must obtain an active context object for a certain scope type. The container must search for an active instance of Context associated with the scope type. If no active context object exists for the scope type, the container throws a ContextNotActiveException.
- ContextTest.testGetContextWithNoRegisteredContextsFails()
b) If more than one active context object exists for the given scope type, the container must throw an IllegalStateException.
- ContextTest.testGetContextWithTooManyActiveContextsFails()
From time to time, the container must obtain an active context object for a certain scope type. The container must search for an active instance of Context
associated with the scope type.
-
If no active context object exists for the scope type, the container throws a
ContextNotActiveException
. -
If more than one active context object exists for the given scope type, the container must throw an
IllegalStateException
.
If there is exactly one active instance of Context
associated with the scope type, we say that the scope is active.
6.5.2. Contextual instance of a bean
a) From time to time, the container must obtain a contextual instance of a bean. The container must obtain the active context object for the bean scope, then obtain an instance of the bean by calling Context.get(), passing the Bean instance representing the bean and an instance of CreationalContext.
- ResolutionByNameTest.testContextCreatesNewInstanceForInjection()
b) From time to time, the container attempts to obtain a contextual instance of a bean that already exists, without creating a new contextual instance. The container must determine if the scope of the bean is active and if it is, obtain the active context object for the bean scope, then attempt to obtain an instance of the bean by calling Context.get(), passing the Bean instance representing the bean without passing any instance of CreationalContext.
- ResolutionByNameTest.testContextCreatesNewInstanceForInjection()
c) If the scope is not active, or if Context.get() returns a null value, there is no contextual instance that already exists.
Note: Statement of intent
e) For a custom implementation of the Bean interface defined in Section 11.1, "The Bean interface", the container calls getScope() to determine the bean scope.
- CustomBeanImplementationTest.testGetScopeTypeCalled()
From time to time, the container must obtain a contextual instance of a bean. The container must:
-
obtain the active context object for the bean scope, then
-
obtain an instance of the bean by calling
Context.get()
, passing theBean
instance representing the bean and an instance ofCreationalContext
.
From time to time, the container attempts to obtain a contextual instance of a bean that already exists, without creating a new contextual instance. The container must determine if the scope of the bean is active and if it is:
-
obtain the active context object for the bean scope, then
-
attempt to obtain an existing instance of the bean by calling
Context.get()
, passing theBean
instance representing the bean without passing any instance ofCreationalContext
.
If the scope is not active, or if Context.get()
returns a null value, there is no contextual instance that already exists.
A contextual instance of any of the built-in kinds of bean defined in Programming model is considered an internal container construct, and it is therefore not strictly required that a contextual instance of a built-in kind of bean directly implement the bean types of the bean. However, in this case, the container is required to transform its internal representation to an object that does implement the bean types expected by the application before injecting or returning a contextual instance to the application.
For a custom implementation of the Bean
interface defined in The Bean
interface, the container calls getScope()
to determine the bean scope.
6.5.3. Contextual reference for a bean
aa) Contextual references must be obtained with a given CreationalContext, allowing any instance of scope @Dependent that is created to be later destroyed.
- SimpleBeanLifecycleTest.testContextualDestroyDisposesWhenNecessary()
a) If the bean has a normal scope and the given bean type cannot be proxied by the container, as defined in Section 5.4.1, "Unproxyable bean types", the container throws an UnproxyableResolutionException.
- UnproxyableManagedBeanTest.testNormalScopedUnproxyableBeanResolution()
b) If the bean has a normal scope, then the contextual reference for the bean is a client proxy, as defined in Section 5.4, "Client proxies", created by the container, that implements the given bean type and all bean types of the bean which are Java interfaces.
- EnterpriseBeanLifecycleTest.testCreateSFSB()
c) If the bean has a pseudo-scope, the container must obtain a contextual instance of the bean. If the bean has scope @Dependent, the container must associate it with the CreationalContext.
- SimpleBeanLifecycleTest.testContextualDestroyDisposesWhenNecessary()
The container must ensure that every injection point of type InjectionPoint and qualifier @Default of any dependent object instantiated during this process receives an instance of InjectionPoint representing the injection point into which the dependent object will be injected, or a null value if it is not being injected into any injection point.
da) Test an injected dependent object.
- InjectionPointTest.testGetBean()
db) Test a non-injected dependent object.
- InjectionPointTest.testNullInjectionPointInjectedIntoNonInjectedObject()
From time to time, the container must obtain a contextual reference for a bean and a given bean type of the bean. A contextual reference implements the given bean type and all bean types of the bean which are Java interfaces. A contextual reference is not, in general, required to implement all concrete bean types of the bean.
Contextual references must be obtained with a given CreationalContext
, allowing any instance of scope @Dependent
that is created to be later destroyed.
-
If the bean has a normal scope and the given bean type cannot be proxied by the container, as defined in Unproxyable bean types, the container throws an
UnproxyableResolutionException
. -
If the bean has a normal scope, then the contextual reference for the bean is a client proxy, as defined in Client proxies, created by the container, that implements the given bean type and all bean types of the bean which are Java interfaces.
-
Otherwise, if the bean has a pseudo-scope, the container must obtain a contextual instance of the bean. If the bean has scope
@Dependent
, the container must associate it with theCreationalContext
.
The container must ensure that every injection point of type InjectionPoint
and qualifier @Default
of any dependent object instantiated during this process receives:
-
an instance of
InjectionPoint
representing the injection point into which the dependent object will be injected, or -
a null value if it is not being injected into any injection point.
6.5.4. Contextual reference validity
a) Any reference to a bean with a normal scope is valid as long as the application maintains a hard reference to it. However, it may only be invoked when the context associated with the normal scope is active. If it is invoked when the context is inactive, a ContextNotActiveException is thrown by the container.
- ClientProxyTest.testInactiveScope()
b) Any reference to a bean with a pseudo-scope (such as @Dependent) is valid until the bean instance to which it refers is destroyed. It may be invoked even if the context associated with the pseudo-scope is not active. If the application invokes a method of a reference to an instance that has already been destroyed, the behavior is undefined.
Note: Describes unspecified behavior
A contextual reference for a bean is valid only for a certain period of time. The application should not invoke a method of an invalid reference.
The validity of a contextual reference for a bean depends upon whether the scope of the bean is a normal scope or a pseudo-scope.
-
Any reference to a bean with a normal scope is valid as long as the application maintains a hard reference to it. However, it may only be invoked when the context associated with the normal scope is active. If it is invoked when the context is inactive, a
ContextNotActiveException
is thrown by the container. -
Any reference to a bean with a pseudo-scope (such as
@Dependent
) is valid until the bean instance to which it refers is destroyed. It may be invoked even if the context associated with the pseudo-scope is not active. If the application invokes a method of a reference to an instance that has already been destroyed, the behavior is undefined.
6.5.5. Injectable references
a) From time to time, the container must obtain an injectable reference for an injection point. The container must identify a bean according to the rules defined in Section 5.2, "Typesafe resolution" and resolving ambiguities according to Section 5.2.1, "Unsatisfied and ambiguous dependencies", then obtain a contextual reference for this bean and the type of the injection point according to Section 6.5.3, "Contextual reference for a bean".
- InjectableReferenceTest.testGetInjectableReferenceOnBeanManager()
b) For certain combinations of scopes, the container is permitted to optimize the procedure for obtaining an injectable reference for an injection point - the container is permitted to directly inject a contextual instance of the bean, as defined in Section 6.5.2, "Contextual instance of a bean", and if an incompletely initialized instance of the bean is registered with the current CreationalContext, as defined in Section 6.1, "The Contextual interface", the container is permitted to directly inject this instance.
From time to time, the container must obtain an injectable reference for an injection point. The container must:
-
Identify a bean according to the rules defined in Typesafe resolution and resolving ambiguities according to Unsatisfied and ambiguous dependencies.
-
Obtain a contextual reference for this bean and the type of the injection point according to Contextual reference for a bean.
For certain combinations of scopes, the container is permitted to optimize the above procedure:
-
The container is permitted to directly inject a contextual instance of the bean, as defined in Contextual instance of a bean.
-
If an incompletely initialized instance of the bean is registered with the current
CreationalContext
, as defined in TheContextual
interface, the container is permitted to directly inject this instance.
However, in performing these optimizations, the container must respect the rules of injectable reference validity.
6.5.6. Injectable reference validity
a) Injectable references to a bean must respect the rules of contextual reference validity, with the following exceptions - a reference to a bean injected into a field, bean constructor or initializer method is only valid until the object into which it was injected is destroyed, a reference to a bean injected into a producer method is only valid until the producer method bean instance that is being produced is destroyed, and a reference to a bean injected into a disposer method or observer method is only valid until the invocation of the method completes.
b) The application should not invoke a method of an invalid injected reference. If the application invokes a method of an invalid injected reference, the behavior is undefined.
Note: Behavior is undefined.
Injectable references to a bean must respect the rules of contextual reference validity, with the following exceptions:
-
A reference to a bean injected into a field, bean constructor or initializer method is only valid until the object into which it was injected is destroyed.
-
A reference to a bean injected into a producer method is only valid until the producer method bean instance that is being produced is destroyed.
-
A reference to a bean injected into a disposer method or observer method is only valid until the invocation of the method completes.
The application should not invoke a method of an invalid injected reference. If the application invokes a method of an invalid injected reference, the behavior is undefined.
6.6. Passivation and passivating scopes
a) Test that passivation occurs.
- PassivatingContextTest.testManagedBeanWithSerializableInterceptorClassOK()
- PassivatingContextTest.testPassivationOccurs()
The temporary transfer of the state of an idle object held in memory to some form of secondary storage is called passivation. The transfer of the passivated state back into memory is called activation.
6.6.1. Passivation capable beans
A managed bean is passivation capable if and only if the bean class is serializable and all interceptors and decorators of the bean are passivation capable.
ba) Tests with a serializable bean class.
- PassivatingContextTest.testManagedBeanWithSerializableImplementationClassOK()
bb) Tests with a serializable interceptor.
- PassivatingContextTest.testManagedBeanWithSerializableInterceptorClassOK()
bc) Tests with a serializable decorator.
- PassivatingContextTest.testManagedBeanWithSerializableDecoratorOK()
c) A producer method is passivation capable if and only if it never returns a value which is not passivation capable at runtime.
Note: Tested in "Validation of passivation capable beans and dependencies" section
d) A producer field is passivation capable if and only if it never refers to a value which is not passivation capable at runtime.
Note: Tested in "Validation of passivation capable beans and dependencies" section
A producer method is passivation capable if and only if it never returns a value which is not passivation capable at runtime.
caa) Test that a producer method with a primitive return type is passivation capable.
ca) Test that a producer method with a serializable return type is passivation capable.
- PassivatingContextTest.testPassivationCapableProducerMethodIsOK()
A producer field is passivation capable if and only if it never refers to a value which is not passivation capable at runtime.
daa) Test that a producer field with a primitive type is passivation capable.
- ProducerWithPrimitiveFieldTypePassivationTest.testProducerFieldWithPrimitiveType()
da) Test that a producer field with a serializable type is passivation capable.
- PassivatingContextTest.testPassivationCapableProducerFieldIsOK()
ea) A custom implementation of Bean is passivation capable if it implements the interface PassivationCapable.
- CustomBeanImplementationTest.testCustomBeanIsPassivationCapable()
f) An implementation of Contextual that is not a bean is passivation capable if it implements both PassivationCapable and Serializable.
g) The getId() method of the PassivationCapable implementation must return a value that uniquely identifies the instance of Bean or Contextual.
Note: This is a requirement of the implementation
h) The getId() method of the PassivationCapable implementation must return a value that uniquely identifies the instance of Bean or Contextual. It is recommended that the string contain the package name of the class that implements Bean or Contextual.
Note: Recommendation only
A bean is called passivation capable if the container is able to temporarily transfer the state of any idle instance to secondary storage.
-
A managed bean is passivation capable if and only if the bean class is serializable and all interceptors and decorators of the bean are passivation capable.
-
A producer method is passivation capable if and only if it never returns a value which is not passivation capable at runtime.
-
A producer field is passivation capable if and only if it never refers to a value which is not passivation capable at runtime.
A custom implementation of Bean
is passivation capable if it implements the interface PassivationCapable
. An implementation of Contextual
that is not a bean is passivation capable if it implements both PassivationCapable
and Serializable
.
public interface PassivationCapable {
public String getId();
}
The getId()
method must return a value that uniquely identifies the instance of Bean
or Contextual
. It is recommended that the string contain the package name of the class that implements Bean
or Contextual
.
6.6.2. Passivation capable injection points
a) An injection point of a bean is passivation capable if the injection point is a transient field.
- PassivatingContextTest.testBeanWithNonSerializableImplementationInjectedIntoTransientFieldOK()
b) An injection point of a bean is passivation capable if the injection point is a non-transient field which resolves to a bean that is a passivation capable dependency.
- PassivationCapableInjectionPointTest.testPassivationCapableInjectionPoints()
- NonPassivatingInjectedFieldTest.testBeanWithNonSerializableImplementationInjectedIntoNonTransientFieldOfBeanWithPassivatingScopeFails()
c) An injection point of a bean is passivation capable if the injection point is a bean constructor parameter which is annotated with @TransientReference.
- TransientReferenceParameterTest.testParamInjectionPoints()
d) An injection point of a bean is passivation capable if the injection point is a bean constructor parameter which resolves to a bean that is a passivation capable dependency.
- PassivationCapableInjectionPointTest.testPassivationCapableInjectionPoints()
- NonPassivatingConstructorParamTest.testBeanWithNonSerializableImplementationInjectedIntoNonTransientFieldOfBeanWithPassivatingScopeFails()
e) An injection point of a bean is passivation capable if the injection point is a method parameter which is annotated with @TransientReference.
- TransientReferenceParameterTest.testParamInjectionPoints()
f) An injection point of a bean is passivation capable if the injection point is a method parameter which resolves to a bean that is a passivation capable dependency.
- NonPassivatingInitParamTest.testBeanWithNonSerializableImplementationInjectedIntoNonTransientFieldOfBeanWithPassivatingScopeFails()
- PassivationCapableInjectionPointTest.testPassivationCapableInjectionPoints()
We call an injection point of a bean passivation capable if the injection point is:
-
a transient field, or
-
a non-transient field which resolves to a bean that is a passivation capable dependency, or
-
a bean constructor parameter which is annotated with
@TransientReference
, or -
a bean constructor parameter which resolves to a bean that is a passivation capable dependency, or
-
a method parameter which is annotated with
@TransientReference
, or -
a method parameter which resolves to a bean that is a passivation capable dependency.
6.6.3. Passivation capable dependencies
b) The container must guarantee that all beans with normal scope are passivation capable dependencies.
- SimpleBeanLifecycleTest.testSerializeRequestScoped()
- SimpleBeanLifecycleTest.testSerializeSessionScoped()
c) The container must guarantee that all passivation capable beans with scope @Dependent are passivation capable dependencies.
- PassivatingContextTest.testInjectionOfDependentPrimitiveProductIntoNormalBean()
- PassivatingContextTest.testInjectionOfDependentSerializableProductIntoNormalBean()
The container must guarantee that the built-in beans of type Instance, Event, InjectionPoint and BeanManager are passivation capable dependencies.
ea) Test built-in Instance.
- BuiltinBeanPassivationDependencyTest.testInstance()
eb) Test built-in Event.
- ImplicitEventTest.testImplicitEventIsPassivationCapable()
ec) Test built-in InjectionPoint.
- BuiltinBeanPassivationDependencyTest.testInjectionPoint()
ed) Test built-in BeanManager.
- BuiltinBeanPassivationDependencyTest.testBeanManager()
fa) A custom implementation of Bean is a passivation capable dependency if it implements PassivationCapable.
- CustomBeanImplementationTest.testCustomBeanIsPassivationCapableDependency()
A bean is called a passivation capable dependency if any contextual reference for that bean is preserved when the object holding the reference is passivated and then activated.
The container must guarantee that:
-
all beans with normal scope are passivation capable dependencies,
-
all passivation capable beans with scope
@Dependent
are passivation capable dependencies, -
the built-in beans of type
Instance
,Event
,InjectionPoint
andBeanManager
are passivation capable dependencies.
A custom implementation of Bean
is a passivation capable dependency if it implements PassivationCapable
.
6.6.4. Passivating scopes
A passivating scope requires that beans with the scope are passivation capable, and implementations of Contextual passed to any context object for the scope are passivation capable.
a) Test that a bean with the scope is passivation capable.
- NonPassivationManagedBeanHasPassivatingScopeTest.testSimpleWebBeanWithNonSerializableImplementationClassFails()
- PassivatingContextTest.testManagedBeanWithSerializableImplementationClassOK()
b) Test that an implementation of Contextual passed to the context object for the scope is passivation capable.
Note: This is in essence enforced by the stuff in 6.6.4
b) Passivating scopes must be explicitly declared @NormalScope(passivating=true).
Note: A statement of intent
A passivating scope requires that:
-
beans with the scope are passivation capable, and
-
implementations of
Contextual
passed to any context object for the scope are passivation capable.
Passivating scopes must be explicitly declared @NormalScope(passivating=true)
.
For example, the built-in session and conversation scopes defined in Context management for built-in scopes are passivating scopes. No other built-in scopes are passivating scopes.
6.6.5. Validation of passivation capable beans and dependencies
If a managed bean which declares a passivating scope, or a built-in bean is not passivation capable then the container automatically detects the problem and treats it as a deployment problem.
a) Test managed bean.
- AddingPassivatingScopeTest.testAddingScopeType()
- PassivationCapabilityErrorTest.test()
- NonPassivationManagedBeanHasPassivatingScopeTest.testSimpleWebBeanWithNonSerializableImplementationClassFails()
If a managed bean which declares a passivating scope, or a built-in bean has has an injection point that is not passivation capable, then the container automatically detects the problem and treats it as a deployment problem.
aa) Test non-transient injected field.
- PassivationCapableDependencyErrorTest.test()
- NonPassivatingInjectedFieldTest.testBeanWithNonSerializableImplementationInjectedIntoNonTransientFieldOfBeanWithPassivatingScopeFails()
ab) Test transient injected field.
- PassivatingContextTest.testBeanWithNonSerializableImplementationInjectedIntoTransientFieldOK()
ac) Test bean constructor parameter which is not annotated with @TransientReference.
- NonPassivatingConstructorParamTest.testBeanWithNonSerializableImplementationInjectedIntoNonTransientFieldOfBeanWithPassivatingScopeFails()
ad) Test bean constructor parameter which is annotated with @TransientReference.
- TransientReferenceParameterTest.testParamInjectionPoints()
ae) Test initializer method parameter which is not annotated with @TransientReference.
- NonPassivatingInitParamTest.testBeanWithNonSerializableImplementationInjectedIntoNonTransientFieldOfBeanWithPassivatingScopeFails()
af) Test initializer method parameter which is annotated with @TransientReference.
- TransientReferenceParameterTest.testParamInjectionPoints()
ag) If a managed bean which declares a passivating scope, or a built-in bean has a non-transient injected field, bean constructor parameter or initializer method parameter that resolves to a bean that is not a dependent scoped bean and that is not a passivation capable dependency then the container automatically detects the problem and treats it as a deployment problem.
Note: It's not defined which non-dependent bean is not a passivation capable dependency.
If a managed bean which declares a passivating scope, or a built-in bean has an interceptor or decorator with a non-transient injected field that does not resolve to a passivation capable dependency, then the container automatically detects the problem and treats it as a deployment problem.
aac) Test interceptor with a non-transient injected field that does not resolve to a passivation capable dependency.
- PassivationCapableBeanWithNonPassivatingInterceptorTest.testPassivationCapableBeanWithNonPassivatingInterceptorFails()
aaf) Test decorator with a non-transient injected field that does not resolve to a passivation capable dependency.
- DecoratorWithNonPassivatingInjectedFieldTest.testPassivationCapableBeanWithNonPassivatingDecoratorInjectedFieldFails()
ca) If a producer method declares a passivating scope and has a return type that is declared final and does not implement or extend Serializable then the container automatically detects the problem and treats it as a deployment problem.
- NonPassivationCapableProducerMethodTest.testNonPassivationCapableProducerMethodNotOk()
ea) If a producer method declares a passivating scope and doesn't only return Serializable types at runtime, then the container must throw an IllegalProductException.
- PassivatingContextTest.testPassivatingScopeProducerMethodReturnsUnserializableObjectNotOk()
d) If a producer field declares a passivating scope and has a type that is declared final and does not implement or extend Serializable then the container automatically detects the problem and treats it as a deployment problem.
- NonPassivationCapableProducerFieldTest.testNonPassivationCapableProducerFieldNotOk()
eb) If a producer field declares a passivating scope and doesn't only contain Serializable values at runtime then the container must throw anIllegalProductException.
- PassivatingContextTest.testNonSerializableProducerFieldDeclaredPassivatingThrowsIllegalProductException()
If a producer method or field of scope @Dependent returns an unserializable object for injection into an injection point that requires a passivation capable dependency, the container must throw an IllegalProductException
fab) Test for a runtime exception with a producer method.
- ManagedBeanWithIllegalDependencyTest.testFieldInjectionPointRequiringPassivationCapableDependency()
- ManagedBeanWithIllegalDependencyTest.testSetterInjectionPointRequiringPassivationCapableDependency()
- ManagedBeanWithIllegalDependencyTest.testConstructorInjectionPointRequiringPassivationCapableDependency()
- ManagedBeanWithIllegalDependencyTest.testProducerMethodParamInjectionPointRequiringPassivationCapableDependency()
fbb) Test for a runtime exception with a producer field.
- ManagedBeanWithIllegalDependencyTest.testFieldInjectionPointRequiringPassivationCapableDependency()
- ManagedBeanWithIllegalDependencyTest.testSetterInjectionPointRequiringPassivationCapableDependency()
- ManagedBeanWithIllegalDependencyTest.testConstructorInjectionPointRequiringPassivationCapableDependency()
For a custom implementation of Bean, the container calls getInjectionPoints() to determine the injection points, and InjectionPoint.isTransient() to determine whether the injected point is a transient field.
ga) Test calling getInjectionPoints().
- CustomBeanImplementationTest.testGetInjectionPointsCalled()
gb) Test calling InjectionPoint.isTransient().
- CustomBeanImplementationTest.testGetInjectionPointsCalled()
If a bean which declares a passivating scope type has a decorator or interceptor which is not a passivation capable dependency, the container automatically detects the problem and treats it as a deployment problem.
ha) Test a bean with decorator which is not a passivation capable dependency.
- ManagedBeanWithNonPassivatingDecoratorTest.testManagedBeanWithNonPassivatingDecoratorFails()
hc) Test a bean with interceptor which is not a passivation capable dependency.
- ManagedBeanWithNonSerializableInterceptorClassTest.testManagedBeanWithNonSerializableInterceptorClassNotOK()
k) Passivation capable interceptor with non-passivation capable dependencies is allowed unless it intercepts a bean declaring passivation scope.
l) Passivation capable decorator with non-passivation capable dependencies is allowed unless it decorates a bean declaring passivation scope.
- DecoratorWithNonPassivationCapableDependenciesTest.testDeploymentValid()
For every bean which declares a passivating scope, the container must validate that the bean truly is passivation capable and that, in addition, its dependencies are passivation capable.
If a managed bean which declares a passivating scope, or a built-in bean:
-
is not passivation capable,
-
has an injection point that is not passivation capable,
-
has an interceptor or decorator that is not passivation capable
-
has an interceptor or decorator with an injection point that is not passivation capable
then the container automatically detects the problem and treats it as a deployment problem.
If a producer method declares a passivating scope and:
-
has a return type that is declared final and does not implement or extend
Serializable
, or, -
has an injection point that is not passivation capable
then the container automatically detects the problem and treats it as a deployment problem.
If a producer method declares a passivating scope and doesn’t only return Serializable
types at runtime, then the container must throw an IllegalProductException
.
If a producer field declares a passivating scope and has a type that is declared final and does not implement or extend Serializable
then the container automatically detects the problem and treats it as a deployment problem.
If a producer field declares a passivating scope and doesn’t only contain Serializable
values at runtime then the container must throw an IllegalProductException
.
If a producer method or field of scope @Dependent
returns an unserializable object for injection into an injection point that requires a passivation capable dependency, the container must throw an IllegalProductException
For a custom implementation of Bean
, the container calls getInjectionPoints()
to determine the injection points, and InjectionPoint.isTransient()
to determine whether the injection point is a transient field.
If a managed bean which declares a passivating scope type, has a decorator or interceptor which is not a passivation capable dependency, the container automatically detects the problem and treats it as a deployment problem.
6.7. Context management for built-in scopes
The container must provide an implementation of the Context
interface for each of the built-in scopes defined in Built-in scope types. These implementations depend on the platform the container is running.
A portable extension may define a custom context object for any or all of the built-in scopes. For example, a remoting framework might provide a request context object for the built-in request scope.
The context associated with a built-in normal scope propagates across local, synchronous Java method calls. The context does not propagate across remote method invocations or to asynchronous processes.
Portable extensions are encouraged to fire an event with qualifier @Initialized(X.class)
when a custom context is initialized, and an event with qualifier @Destroyed(X.class)
when a custom context is destroyed, where X is the scope type associated with the context. A suitable event payload should be chosen.
6.7.1. Request context lifecycle
The request context is provided by a built-in context object for the built-in scope type @RequestScoped
.
An event with qualifier @Initialized(RequestScoped.class) is fired when the request context is initialized and an event with qualifier @Destroyed(RequestScoped.class) when the request context is destroyed.
6.7.2. Session context lifecycle
The session context is provided by a built-in context object for the built-in passivating scope type @SessionScoped
.
6.7.3. Application context lifecycle
The application context is provided by a built-in context object for the built-in scope type @ApplicationScoped
.
An event with qualifier @Initialized(ApplicationScoped.class) is fired when the application context is initialized and an event with qualifier @Destroyed(ApplicationScoped.class) is fired when the application is destroyed.
6.7.4. Conversation context lifecycle
The conversation context is provided by a built-in context object for the built-in passivating scope type @ConversationScoped
.
6.7.5. The Conversation
interface
The container provides a built-in bean with bean type Conversation, scope @RequestScoped, and qualifier @Default, named javax.enterprise.context.conversation.
iaa) Test the bean type is correct.
- ClientConversationContextTest.testBeanWithRequestScope()
ib) Test the scope is correct.
- ClientConversationContextTest.testBeanWithRequestScope()
id) Test the qualifier is correct.
- ClientConversationContextTest.testBeanWithDefaultQualifier()
ie) Test the bean name is correct.
- ClientConversationContextTest.testBeanWithNameJavaxEnterpriseContextConversation()
j) begin() marks the current transient conversation long-running. A conversation identifier may, optionally, be specified. If no conversation identifier is specified, an identifier is generated by the container.
- ClientConversationContextTest.testConversationIdMayBeSetByApplication()
- ClientConversationContextTest.testConversationIdMayBeSetByContainer()
k) end() marks the current long-running conversation transient.
- ClientConversationContextTest.testConversationEndMakesConversationTransient()
l) getId() returns the identifier of the current long-running conversation, or a null value if the current conversation is transient.
- ClientConversationContextTest.testTransientConversationHasNullId()
m) getTimeout() returns the timeout, in milliseconds, of the current conversation.
- ClientConversationContextTest.testSetConversationTimeoutOverride()
- ClientConversationContextTest.testConversationHasDefaultTimeout()
n) setTimeout() sets the timeout of the current conversation.
- ClientConversationContextTest.testSetConversationTimeoutOverride()
o) isTransient() returns true if the conversation is marked transient, or false if it is marked long-running.
- ClientConversationContextTest.testConversationEndMakesConversationTransient()
p) If any method of Conversation is called when the conversation scope is not active, a ContextNotActiveException is thrown.
- InactiveConversationTest.testContextNotActiveExceptionThrown()
q) If end() is called, and the current conversation is marked transient, an IllegalStateException is thrown.
- ClientConversationContextTest.testEndTransientConversationThrowsException()
r) If begin() is called, and the current conversation is already marked long-running, an IllegalStateException is thrown.
- ClientConversationContextTest.testBeginAlreadyLongRunningConversationThrowsException()
s) If begin() is called with an explicit conversation identifier, and a long-running conversation with that identifier already exists, an IllegalArgumentException is thrown.
- ClientConversationContextTest.testBeginConversationWithExplicitIdAlreadyUsedByDifferentConversation()
The container provides a built-in bean with bean type Conversation
, scope @RequestScoped
, and qualifier @Default
, named javax.enterprise.context.conversation
.
public interface Conversation {
public void begin();
public void begin(String id);
public void end();
public String getId();
public long getTimeout();
public void setTimeout(long milliseconds);
public boolean isTransient();
}
-
begin()
marks the current transient conversation long-running. A conversation identifier may, optionally, be specified. If no conversation identifier is specified, an identifier is generated by the container. -
end()
marks the current long-running conversation transient. -
getId()
returns the identifier of the current long-running conversation, or a null value if the current conversation is transient. -
getTimeout()
returns the timeout, in milliseconds, of the current conversation. -
setTimeout()
sets the timeout of the current conversation. -
isTransient()
returnstrue
if the conversation is marked transient, orfalse
if it is marked long-running.
If any method of Conversation
is called when the conversation scope is not active, a ContextNotActiveException
is thrown.
If end()
is called, and the current conversation is marked transient, an IllegalStateException
is thrown.
If begin()
is called, and the current conversation is already marked long-running, an IllegalStateException
is thrown.
If begin()
is called with an explicit conversation identifier, and a long-running conversation with that identifier already exists, an IllegalArgumentException
is thrown.
7. Lifecycle of contextual instances
The lifecycle of a contextual instance of a bean is managed by the context object for the bean’s scope, as defined in Scopes and contexts.
Every bean in the system is represented by an instance of the Bean
interface defined in The Bean
interface. This interface is a subtype of Contextual
. To create and destroy contextual instances, the context object calls the create()
and destroy()
operations defined by the interface Contextual
, as defined in The Contextual
interface.
7.1. Restriction upon bean instantiation
There are very few programming restrictions upon the bean class of a bean. In particular, the class is a concrete class and is not required to implement any special interface or extend any special superclass. Therefore, bean classes are easy to instantiate and unit test.
However, if the application directly instantiates a bean class, instead of letting the container perform instantiation, the resulting instance is not managed by the container and is not a contextual instance as defined by Contextual instance of a bean. Furthermore, the capabilities listed in Functionality provided by the container to the bean will not be available to that particular instance. In a deployed application, it is the container that is responsible for instantiating beans and initializing their dependencies.
If the application requires more control over instantiation of a contextual instance, a producer method or field may be used. Any Java object may be returned by a producer method or field. It is not required that the returned object be a contextual reference for a bean. However, if the object is not a contextual reference for another bean, the object will be contextual instance of the producer method bean, and therefore available for injection into other objects and use in name resolution, but the other capabilities listed in Functionality provided by the container to the bean will not be available to the object.
In the following example, a producer method returns instances of other beans:
@SessionScoped
public class PaymentStrategyProducer implements Serializable {
private PaymentStrategyType paymentStrategyType;
public void setPaymentStrategyType(PaymentStrategyType type) {
paymentStrategyType = type;
}
@Produces PaymentStrategy getPaymentStrategy(@CreditCard PaymentStrategy creditCard,
@Cheque PaymentStrategy cheque,
@Online PaymentStrategy online) {
switch (paymentStrategyType) {
case CREDIT_CARD: return creditCard;
case CHEQUE: return cheque;
case ONLINE: return online;
default: throw new IllegalStateException();
}
}
}
In this case, any object returned by the producer method has already had its dependencies injected, receives lifecycle callbacks and event notifications and may have interceptors.
But in this example, the returned objects are not contextual instances:
@SessionScoped
public class PaymentStrategyProducer implements Serializable {
private PaymentStrategyType paymentStrategyType;
public void setPaymentStrategyType(PaymentStrategyType type) {
paymentStrategyType = type;
}
@Produces PaymentStrategy getPaymentStrategy() {
switch (paymentStrategyType) {
case CREDIT_CARD: return new CreditCardPaymentStrategy();
case CHEQUE: return new ChequePaymentStrategy();
case ONLINE: return new OnlinePaymentStrategy();
default: throw new IllegalStateException();
}
}
}
In this case, any object returned by the producer method will not have any dependencies injected by the container, receives no lifecycle callbacks or event notifications and does not have interceptors or decorators.
7.2. Container invocations and interception
aa) When the application invokes a method of a bean via a contextual reference to the bean, as defined in Section 6.5.3, "Contextual reference for a bean", the invocation is treated as a business method invocation.
- InterceptorInvocationTest.testManagedBeanIsIntercepted()
- DecoratorInvocationTest.testDecoratorInvocation()
- SessionBeanInterceptorDefinitionTest.testSessionBeanIsIntercepted()
ab) When the application invokes a method of a bean via a non-contextual reference to the bean, if the instance was created by the container, the invocation is treated as a business method invocation.
- SessionBeanInterceptorOnNonContextualEjbReferenceTest.testNonContextualSessionBeanReferenceIsIntercepted()
ad) Invocations of initializer methods by the container are not business method invocations.
- InterceptorInvocationTest.testInitializerMethodsNotIntercepted()
Invocations of producer, disposer and observer methods by the container are business method invocations are are intercepted by method interceptors and decorators.
ia) Verify producer methods are intercepted
- InterceptorInvocationTest.testProducerMethodsAreIntercepted()
ib) Verify producer methods are decorated
- DecoratorInvocationTest.testDecoratorInvocation()
ic) Verify disposer methods are intercepted
- InterceptorInvocationTest.testDisposerMethodsAreIntercepted()
id) Verify disposer methods are decorated
- DecoratorInvocationTest.testDecoratorInvocation()
ie) Verify observer methods are intercepted
- InterceptorInvocationTest.testObserverMethodsAreIntercepted()
if) Verify observer methods are decorated
- DecoratorInvocationTest.testDecoratorInvocation()
j) Invocation of lifecycle callbacks by the container are not business method invocations, but are intercepted by interceptors for lifecycle callbacks.
- InterceptorInvocationTest.testLifecycleCallbacksAreIntercepted()
Invocations of interceptors and decorator methods during method or lifecycle callback interception are not business method invocations, and therefore no recursive interception occurs.
ka) Verify decorators callbacks are not intercepted
- DecoratorAndInterceptorTest.testMethodCallbacks()
kb) Verify decorators callbacks are not decorated
- DecoratorAndInterceptorTest.testMethodCallbacks()
- DecoratorInvocationTest.testChainedDecoratorInvocation()
kc) Verify interceptor callbacks are not intercepted
- DecoratorAndInterceptorTest.testMethodCallbacks()
- DecoratorAndInterceptorTest.testLifecycleCallbacks()
kd) Verify interceptor callbacks are not decorated
- DecoratorAndInterceptorTest.testMethodCallbacks()
- DecoratorAndInterceptorTest.testLifecycleCallbacks()
m) Invocations of methods declared by java.lang.Object are not business method invocations.
- InterceptorInvocationTest.testObjectMethodsAreNotIntercepted()
If, and only if, the invocation is a business method invocation it passes through method interceptors and decorators.
a) Verify that a managed bean's business methods are intercepted
- InterceptorInvocationTest.testManagedBeanIsIntercepted()
b) Verify that a managed bean's business methods are decorated
- DecoratorInvocationTest.testDecoratorInvocation()
g) If the invocation is not a business method invocation, it is treated as a normal Java method call and is not intercepted by the container.
- InterceptorInvocationTest.testObjectMethodsAreNotIntercepted()
When the application invokes:
-
a method of a bean via a contextual reference to the bean, as defined in Contextual reference for a bean, or
-
a method of a bean via a non-contextual reference to the bean, if the instance was created by the container (e.g. using
InjectionTarget.produce()
orUnmanagedInstance.produce()
),
the invocation is treated as a business method invocation.
When the container invokes a method of a bean, the invocation may or may not be treated as a business method invocation:
-
Invocations of initializer methods by the container are not business method invocations.
-
Invocations of producer, disposer and observer methods by the container are business method invocations and are intercepted by method interceptors and decorators.
-
Invocation of lifecycle callbacks by the container are not business method invocations, but are intercepted by interceptors for lifecycle callbacks.
-
Invocations of interceptors and decorator methods during method or lifecycle callback interception are not business method invocations, and therefore no recursive interception occurs.
-
Invocations of methods declared by java.lang.Object are not business method invocations.
A method invocation passes through method interceptors and decorators if, and only if, it is a business method invocation.
Otherwise, the invocation is treated as a normal Java method call and is not intercepted by the container.
7.3. Lifecycle of contextual instances
The actual mechanics of bean creation and destruction varies according to what kind of bean is being created or destroyed.
7.3.1. Lifecycle of managed beans
aa) When the create() method of the Bean object that represents a managed bean is called, the container obtains an instance of the bean, as defined by the Managed Beans specification, calling the bean constructor as defined by Section 5.5.1, "Injection using the bean constructor", and performing dependency injection as defined in Section 5.5.2, "Injection of fields and initializer methods".
- SimpleBeanLifecycleTest.testBeanCreateInjectsDependenciesAndInvokesInitializerToInstantiateInstance()
- SimpleBeanLifecycleTest.testCreateInjectsFieldsDeclaredInJava()
- SimpleBeanLifecycleTest.testPostConstructPreDestroy()
ba) When the destroy() method is called, the container destroys the instance, as defined by the Managed Beans specification, and any dependent objects, as defined in Section 5.5.3, "Destruction of dependent objects".
- SimpleBeanLifecycleTest.testPostConstructPreDestroy()
- SimpleBeanLifecycleTest.testContextualDestroyDisposesWhenNecessary()
When the create()
method of the Bean
object that represents a managed bean is called, the container obtains an instance of the bean, as defined by the Managed Beans specification, calling the bean constructor as defined by Injection using the bean constructor, and performing dependency injection as defined in Injection of fields and initializer methods.
When the destroy()
method is called, the container destroys the instance, as defined by the Managed Beans specification, and any dependent objects, as defined in Destruction of dependent objects.
7.3.2. Lifecycle of producer methods
ea) When the create() method of a Bean object that represents a producer method is called, the container must invoke the producer method as defined by Section 5.5.4, "Invocation of producer or disposer methods". The return value of the producer method, after method interception completes, is the new contextual instance to be returned by Bean.create().
- ProducerMethodLifecycleTest.testProducerMethodInvokedOnCreate()
- ProducerMethodLifecycleTest.testProducerMethodBeanCreate()
k) If the producer method returns a null value and the producer method bean has the scope @Dependent, the create() method returns a null value.
- ProducerMethodLifecycleTest.testCreateReturnsNullIfProducerDoesAndDependent()
l) If the producer method returns a null value, and the scope of the producer method is not @Dependent, the create() method throws an IllegalProductException.
- ProducerMethodLifecycleTest.testCreateFailsIfProducerReturnsNullAndNotDependent()
ma) When the destroy() method is called, and if there is a disposer method for this producer method, the container must invoke the disposer method as defined by Section 5.5.4, "Invocation of producer or disposer methods", passing the instance given to destroy() to the disposed parameter.
- ProducerMethodLifecycleTest.testProducerMethodBeanDestroy()
r) Finally, the container destroys dependent objects, as defined in Section 5.5.3, "Destruction of dependent objects".
- ProducerMethodLifecycleTest.testProducerMethodBeanDestroy()
When the create()
method of a Bean
object that represents a producer method is called, the container must invoke the producer method as defined by Invocation of producer or disposer methods. The return value of the producer method, after method interception completes, is the new contextual instance to be returned by Bean.create()
.
If the producer method returns a null value and the producer method bean has the scope @Dependent
, the create()
method returns a null value.
Otherwise, if the producer method returns a null value, and the scope of the producer method is not @Dependent
, the create()
method throws an IllegalProductException
.
When the destroy()
method is called, and if there is a disposer method for this producer method, the container must invoke the disposer method as defined by Invocation of producer or disposer methods, passing the instance given to destroy()
to the disposed parameter. Finally, the container destroys dependent objects, as defined in Destruction of dependent objects.
7.3.3. Lifecycle of producer fields
ga) When the create() method of a Bean object that represents a producer field is called, the container must access the producer field as defined by Section 5.5.5, "Access to producer field values" to obtain the current value of the field. The value of the producer field is the new contextual instance to be returned by Bean.create().
- ProducerFieldLifecycleTest.testProducerFieldBeanCreate()
m) If the producer field contains a null value and the producer field bean has the scope @Dependent, the create() method returns a null value.
- ProducerFieldLifecycleTest.testProducerFieldReturnsNullIsDependent()
n) If the producer field contains a null value, and the scope of the producer method is not @Dependent, the create() method throws an IllegalProductException.
- ProducerFieldLifecycleTest.testProducerFieldForNullValueNotDependent()
- ProducerFieldLifecycleTest.testProducerFieldReturnsNullIsNotDependent()
o) When the destroy() method is called, and if there is a disposer method for this producer field, the container must invoke the disposer method as defined by Section 5.5.4, "Invocation of producer or disposer methods", passing the instance given to destroy() to the disposed parameter.
- DisposalMethodDefinitionTest.testDisposalMethodCalledForProducerField()
- ProducerFieldLifecycleTest.testProducerFieldBeanDestroy()
When the create()
method of a Bean
object that represents a producer field is called, the container must access the producer field as defined by Access to producer field values to obtain the current value of the field. The value of the producer field is the new contextual instance to be returned by Bean.create()
.
If the producer field contains a null value and the producer field bean has the scope @Dependent
, the create()
method returns a null value.
Otherwise, if the producer field contains a null value, and the scope of the producer field is not @Dependent
, the create()
method throws an IllegalProductException
.
When the destroy()
method is called, and if there is a disposer method for this producer field, the container must invoke the disposer method as defined by Invocation of producer or disposer methods, passing the instance given to destroy()
to the disposed parameter.
8. Decorators
a) Decorators may be associated with any managed bean that is not itself an interceptor or decorator, with any EJB session bean or with any built-in bean other than the built-in bean with type BeanManager and qualifier @Default.
Note: Tested elsewhere.
b) Decorators are not applied to the return value of a producer method or the current value of a producer field.
- DecoratorNotAppliedToResultOfProducerTest.testDecoratorNotAppliedToResultOfProducerMethod()
- DecoratorNotAppliedToResultOfProducerTest.testDecoratorNotAppliedToResultOfProducerField()
c) A decorator instance is a dependent object of the object it decorates.
- DecoratorInstanceIsDependentObjectTest.testDecoratorInstanceIsDependentObject()
A decorator implements one or more bean types and intercepts business method invocations of beans which implement those bean types. These bean types are called decorated types.
Decorators are superficially similar to interceptors, but because they directly implement operations with business semantics, they are able to implement business logic and, conversely, unable to implement the cross-cutting concerns for which interceptors are optimized.
Decorators may be associated with any managed bean that is not itself an interceptor or decorator, or with any built-in bean other than the built-in bean with type BeanManager
and qualifier @Default
. Decorators are not applied to the return value of a producer method or the current value of a producer field. A decorator instance is a dependent object of the object it decorates.
8.1. Decorator beans
a) A decorator is a managed bean.
Note: Statement of intent
b) The set of decorated types of a decorator includes all bean types of the managed bean which are Java interfaces, except for java.io.Serializable.
- DecoratorDefinitionTest.testDecoratedTypes()
c) The decorator bean class and its superclasses are not decorated types of the decorator.
- DecoratorDefinitionTest.testDecoratedTypes()
d) The decorator class may be abstract.
- DecoratorDefinitionTest.testDecoratorIsManagedBean()
- DecoratorDefinitionTest.testAbstractDecoratorNotImplementingMethodOfDecoratedType()
e) If the set of decorated types of a decorator is empty, the container automatically detects the problem and treats it as a definition error.
- DecoratorWithNoDecoratedTypes3Test.testDeploymentFails()
- DecoratorWithNoDecoratedTypes2Test.testDeploymentFails()
- DecoratorWithNoDecoratedTypes1Test.testDeploymentFails()
f) Decorators of a session bean must comply with the bean provider programming restrictions defined by the EJB specification.
g) Decorators of a stateful session bean must comply with the rules for instance passivation and conversational state defined by the EJB specification.
A decorator is a managed bean. The set of decorated types of a decorator includes all bean types of the managed bean which are Java interfaces, except for java.io.Serializable
. The decorator bean class and its superclasses are not decorated types of the decorator. The decorator class may be abstract.
If the set of decorated types of a decorator is empty, the container automatically detects the problem and treats it as a definition error.
8.1.1. Declaring a decorator
a) A decorator is declared by annotating the bean class with the @javax.decorator.Decorator stereotype.
- DecoratorDefinitionTest.testDecoratorIsManagedBean()
A decorator is declared by annotating the bean class with the @javax.decorator.Decorator
stereotype.
@Decorator @Priority(APPLICATION)
class TimestampLogger implements Logger { ... }
8.1.2. Decorator delegate injection points
a) All decorators have a delegate injection point. A delegate injection point is an injection point of the bean class. The type and qualifiers of the injection point are called the delegate type and delegate qualifiers. The decorator applies to beans that are assignable to the delegate injection point. The delegate injection point must be be declared by annotating the injection point with the annotation @javax.decorator.Delegate.
- DecoratorDefinitionTest.testDelegateInjectionPoint()
A decorator must have exactly one delegate injection point. If a decorator has more than one delegate injection point, or does not have a delegate injection point, the container automatically detects the problem and treats it as a definition error.
ca) Test with more than one delegate injection point.
- CustomDecoratorWithTooManyDelegateInjectionPointsTest.testDeploymentFails()
- MultipleDelegateInjectionPointsTest.testMultipleDelegateInjectionPoints()
cb) Test a decorator without a delegate injection point.
- CustomDecoratorWithNoDelegateInjectionPointTest.testDeploymentFails()
- NoDelegateInjectionPointsTest.testNoDelegateInjectionPoints()
The delegate injection point must be an injected field, initializer method parameter or bean constructor method parameter. If an injection point that is not an injected field, initializer method parameter or bean constructor method parameter is annotated @Delegate, the container automatically detects the problem and treats it as a definition error.
cc) Check an injected field is ok
- EnterpriseDecoratorInvocationTest.testContextualDecorated()
- DelegateFieldInjectionPointTest.testDecoratorDelegateInjectionPoints()
cd) Check an initializer method parameter is ok
- DelegateInjectionPointTest.testDecoratorDelegateInjectionPoints()
ce) Check a bean constructor method parameter is ok
- DelegateInjectionPointTest.testDecoratorDelegateInjectionPoints()
cf) Check that a producer method parameter is not ok
cg) If a bean class that is not a decorator has an injection point annotated @Delegate, the container automatically detects the problem and treats it as a definition error.
- NonDecoratorWithDecoratesTest.testNonDecoratorWithDecoratesAnnotationNotOK()
f) The container must inject a delegate object to the delegate injection point. The delegate object implements the delegate type and delegates method invocations to the remaining uninvoked decorators and eventually to the bean. When the container calls a decorator during business method interception, the decorator may invoke any method of the delegate object.
- DecoratorInvocationTest.testDecoratorInvocation()
- DecoratorInvocationTest.testChainedDecoratorInvocation()
g) If a decorator invokes the delegate object at any other time, the invoked method throws an IllegalStateException.
All decorators have a delegate injection point. A delegate injection point is an injection point of the bean class. The type and qualifiers of the injection point are called the delegate type and delegate qualifiers. The decorator applies to beans that are assignable to the delegate injection point.
The delegate injection point must be declared by annotating the injection point with the annotation @javax.decorator.Delegate
:
@Decorator @Priority(APPLICATION)
class TimestampLogger implements Logger {
@Inject @Delegate @Any Logger logger;
...
}
@Decorator @Priority(APPLICATION)
class TimestampLogger implements Logger {
private Logger logger;
@Inject
public TimestampLogger(@Delegate @Debug Logger logger) {
this.logger=logger;
}
...
}
A decorator must have exactly one delegate injection point. If a decorator has more than one delegate injection point, or does not have a delegate injection point, the container automatically detects the problem and treats it as a definition error.
The delegate injection point must be an injected field, initializer method parameter or bean constructor method parameter. If an injection point that is not an injected field, initializer method parameter or bean constructor method parameter is annotated @Delegate
, the container automatically detects the problem and treats it as a definition error.
If a bean class that is not a decorator has an injection point annotated @Delegate
, the container automatically detects the problem and treats it as a definition error.
The container must inject a delegate object to the delegate injection point. The delegate object implements the delegate type and delegates method invocations to remaining uninvoked decorators and eventually to the bean. When the container calls a decorator during business method interception, the decorator may invoke any method of the delegate object.
@Decorator @Priority(APPLICATION)
class TimestampLogger implements Logger {
@Inject @Delegate @Any Logger logger;
void log(String message) {
logger.log( timestamp() + ": " + message );
}
...
}
If a decorator invokes the delegate object at any other time, the invoked method throws an IllegalStateException
.
8.1.3. Decorated types of a decorator
a) The delegate type of a decorator must implement or extend every decorated type (with exactly the same type parameters). If the delegate type does not implement or extend a decorated type of the decorator (or specifies different type parameters), the container automatically detects the problem and treats it as a definition error.
- TypeParametersNotTheSameTest.testDeploymentFails()
- DelegateTypeImplementsParameterizedDecoratedTypeTest.testDelegateTypeIsValid()
- NotAllDecoratedTypesImplementedTest.testNotAllDecoratedTypesImplemented()
ab) If a decorated type is a parameterized type and the delegate type does not have exactly the same type parameters as the decorated type, the container automatically detects the problem and treats it as a definition error.
- DifferentTypeParametersTest.testTypeParametersOnDecoratedTypeAndDelegateTypeDoNotMatch()
b) A decorator is not required to implement the delegate type.
- DecoratorDefinitionTest.testDecoratorDoesNotImplementDelegateType()
c) A decorator may be an abstract Java class, and is not required to implement every method of every decorated type.
- DecoratorDefinitionTest.testDecoratorIsManagedBean()
- DecoratorDefinitionTest.testAbstractDecoratorNotImplementingMethodOfDecoratedType()
ca) Whenever the decorator does not implement a method of the decorated type, the container will provide an implicit implementation that calls the method on the delegate.
- DecoratorDefinitionTest.testAbstractDecoratorNotImplementingMethodOfDecoratedType()
cb) If a decorator has abstract methods that are not declared by a decorated type, the container automatically detects the problem and treats it as a definition error.
- DecoratorWithInvalidAbstractMethodTest.testAbstractMethodsNotDeclaredByDecoratedTypeNotOk()
d) The decorator intercepts every method which is declared by a decorated type of the decorator and is implemented by the bean class of the decorator.
- DecoratorInvocationTest.testDecoratorInvocation()
- DecoratorInvocationTest.testChainedDecoratorInvocation()
The delegate type of a decorator must implement or extend every decorated type (with exactly the same type parameters). If the delegate type does not implement or extend a decorated type of the decorator (or specifies different type parameters), the container automatically detects the problem and treats it as a definition error.
A decorator is not required to implement the delegate type.
A decorator may be an abstract Java class, and is not required to implement every method of every decorated type. Whenever the decorator does not implement a method of the decorated type, the container will provide an implicit implementation that calls the method on the delegate. If a decorator has abstract methods that are not declared by a decorated type, the container automatically detects the problem and treats it as a definition error.
The decorator intercepts every method which is declared by a decorated type of the decorator and is implemented by the bean class of the decorator.
8.2. Decorator enablement and ordering
a) This specification defines two methods of enabling and ordering decorators. From Contexts and Dependency Injection 1.1 onwards the @Priority annotation allows a decorator to be enabled and ordered for an entire application. Contexts and Dependency Injection 1.0 allowed only for a decorator to be enabled and ordered for a bean archive.
Note: Statement of intent
b) Decorators are called after interceptors.
- InterceptorCalledBeforeDecoratorTest.testInterceptorCalledBeforeDecorator()
- DecoratorAndInterceptorTest.testMethodCallbacks()
c) Decorators enabled using @Priority are called before decorators enabled using beans.xml.
- GlobalDecoratorOrderingTest.testDecoratorsInWebInfClasses()
This specification defines two methods of enabling and ordering decorators. From Contexts and Dependency Injection 1.1 onwards the @Priority
annotation allows a decorator to be enabled and ordered for an entire application. Contexts and Dependency Injection 1.0 allowed only for a decorator to be enabled and ordered for a bean archive.
Decorators are called after interceptors. Decorators enabled using @Priority
are called before decorators enabled using beans.xml
.
A decorator is said to be enabled if it is enabled in at least one bean archive or is listed in the final list of decorators for the application, as defined in AfterTypeDiscovery
event.
8.2.1. Decorator enablement and ordering for an application
a) A decorator may be enabled for the entire application by applying the @Priority annotation, along with a priority value, on the decorator class.
- GlobalDecoratorOrderingTest.testDecoratorsInWebInfClasses()
b) Decorators with the smaller priority values are called first.
- GlobalDecoratorOrderingTest.testDecoratorsInWebInfClasses()
c) The order of more than one decorator with the same priority is undefined.
Note: Undefined behaviour.
d) The priority value ranges defined in the Java Interceptors specification section 5.5 should be used when defining decorator priorities.
Note: No explicit requirement.
A decorator may be enabled for the entire application by applying the @Priority
annotation, along with a priority value, on the decorator class. Decorators with the smaller priority values are called first. The order of more than one decorator with the same priority is undefined.
@Decorator @Priority(APPLICATION)
class TimestampLogger implements Logger {
...
}
The priority value ranges defined in the Java Interceptors specification section 5.5 should be used when defining decorator priorities.
8.2.2. Decorator enablement and ordering for a bean archive
a) A decorator may be explicitly enabled by listing its bean class under the <decorators> element of the beans.xml file of the bean archive.
- EnterpriseArchiveModulesTest.testDecoratorEnablement()
- GlobalDecoratorOrderingTest.testDecoratorsInWebInfClasses()
- WebArchiveModulesTest.testDecoratorAndCrossModuleEventObserver()
- DecoratorDefinitionTest.testNonEnabledDecoratorNotResolved()
b) The order of the decorator declarations determines the decorator ordering. Decorators which occur earlier in the list are called first.
- DecoratorDefinitionTest.testDecoratorOrdering()
Each child
ca) Test with a nonexistent class name.
- NonExistantDecoratorClassInBeansXmlTest.testNonExistantDecoratorClassInBeansXmlNotOK()
cb) Test with a non-decorator class.
- EnabledDecoratorNotADecoratorTest.testEnabledDecoratorNotADecoratorTest()
d) If the same class is listed twice under the <decorators> element, the container automatically detects the problem and treats it as a deployment problem.
- DecoratorListedTwiceInBeansXmlTest.testDecoratorListedTwiceInBeansXmlNotOK()
A decorator may be explicitly enabled by listing its bean class under the <decorators>
element of the beans.xml
file of the bean archive.
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">
<decorators>
<class>com.acme.myfwk.TimestampLogger</class>
<class>com.acme.myfwk.IdentityLogger</class>
</decorators>
</beans>
The order of the decorator declarations determines the decorator ordering. Decorators which occur earlier in the list are called first.
Each child <class>
element must specify the name of a decorator bean class. If there is no class with the specified name, or if the class with the specified name is not a decorator bean class, the container automatically detects the problem and treats it as a deployment problem.
If the same class is listed twice under the <decorators>
element, the container automatically detects the problem and treats it as a deployment problem.
8.3. Decorator resolution
aa) The process of matching decorators to a certain bean is called decorator resolution. A decorator is bound to a bean if the bean is assignable to the delegate injection point according to the rules defined in Section 5.2, "Typesafe resolution", and the decorator is enabled in the bean archive containing the bean.
- BuiltinHttpSessionDecoratorTest.testDecoratorIsResolved()
- BuiltinConversationDecoratorTest.testDecoratorIsResolved()
- BuiltinEventDecoratorTest.testDecoratorIsResolved()
- WebArchiveModulesTest.testDecoratorAndCrossModuleEventObserver()
- DecoratorDefinitionTest.testDecoratorIsManagedBean()
- DecoratorDefinitionTest.testDecoratorOrdering()
ab) If a decorator matches a managed bean, and the managed bean class is declared final, the container automatically detects the problem and treats it as a deployment problem.
- FinalBeanClassTest.testAppliesToFinalManagedBeanClass()
- CustomDecoratorMatchingBeanWithFinalClassTest.testCustomDecoratorDecoratingFinalBean()
ac) If a decorator matches a managed bean with a non-static, non-private, final method, and the decorator also implements that method, the container automatically detects the problem and treats it as a deployment problem.
- FinalBeanMethodTest.testAppliesToFinalMethodOnManagedBeanClass()
b) For a custom implementation of the Decorator interface defined in Section 11.1.1, "The Decorator interface", the container calls getDelegateType(), getDelegateQualifiers() and getDecoratedTypes() to determine the delegate type and qualifiers and decorated types of the decorator.
- CustomDecoratorTest.testCustomImplementationOfDecoratorInterface()
The process of matching decorators to a certain bean is called decorator resolution. A decorator is bound to a bean if:
-
The bean is assignable to the delegate injection point according to the rules defined in Typesafe resolution (using Assignability of raw and parameterized types for delegate injection points).
-
The decorator is enabled in the bean archive containing the bean.
If a decorator matches a managed bean, the managed bean class must be a proxyable bean type, as defined in Unproxyable bean types.
For a custom implementation of the Decorator
interface defined in The Decorator
interface, the container calls getDelegateType()
, getDelegateQualifiers()
and getDecoratedTypes()
to determine the delegate type and qualifiers and decorated types of the decorator.
8.3.1. Assignability of raw and parameterized types for delegate injection points
A raw bean type is considered assignable to a parameterized delegate type if the raw types are identical and all type parameters of the delegate type are either unbounded type variables or java.lang.Object.
aa) Check all type parameters are unbounded type variables
- DecoratorResolutionTest.testUnboundedTypeVariables()
ab) Check all type parameters are Object
- DecoratorResolutionTest.testObject()
ac) Check mix
- DecoratorResolutionTest.testUnboundedTypeVariablesAndObject()
A parameterized bean type is considered assignable to a parameterized delegate type if they have identical raw type and for each parameter: the delegate type parameter and the bean type parameter are actual types with identical raw type, and, if the type is parameterized, the bean type parameter is assignable to the delegate type parameter according to these rules, or the delegate type parameter is a wildcard, the bean type parameter is an actual type and the actual type is assignable to the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or the delegate type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable to the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or the delegate type parameter and the bean type parameter are both type variables and the upper bound of the bean type parameter is assignable to the upper bound, if any, of the delegate type parameter, or the delegate type parameter is a type variable, the bean type parameter is an actual type, and the actual type is assignable to the upper bound, if any, of the type variable.
c) Check both have identical type parameters
- DecoratorResolutionTest.testIdenticalTypeParamerters()
d) Check nested identical type parameters
- DecoratorResolutionTest.testNestedIdenticalTypeParamerters()
e) Check delegate type parameter is a wildcard, the bean type parameter is an actual type and the actual type is assignable to the upper bound of the wildcard and assignable from the lower bound of the wildcard
- DecoratorResolutionTest.testDelegateWildcardBeanActualType()
f) Check delegate type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable to the upper bound of the wildcard and assignable from the lower bound of the wildcard
- DecoratorResolutionTest.testDelegateWildcardBeanTypeVariable()
g) Check the delegate type parameter and the bean type parameter are both type variables and the upper bound of the bean type parameter is assignable to the upper bound of the delegate type parameter
- DecoratorResolutionTest.testDelegateTypeVariableBeanTypeVariable()
h) Check the delegate type parameter is a type variable, the bean type parameter is an actual type, and the actual type is as- signable to the upper bound of the type variable
- DecoratorResolutionTest.testDelegateTypeVariableBeanActualType()
Decorator delegate injection points have a special set of rules for determining assignability of raw and parameterized types, as an exception to Assignability of raw and parameterized types.
A raw bean type is considered assignable to a parameterized delegate type if the raw types are identical and all type parameters of the delegate type are either unbounded type variables or java.lang.Object
.
A parameterized bean type is considered assignable to a parameterized delegate type if they have identical raw type and for each parameter:
-
the delegate type parameter and the bean type parameter are actual types with identical raw type, and, if the type is parameterized, the bean type parameter is assignable to the delegate type parameter according to these rules, or
-
the delegate type parameter is a wildcard, the bean type parameter is an actual type and the actual type is assignable to the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or
-
the delegate type parameter is a wildcard, the bean type parameter is a type variable and the upper bound of the type variable is assignable to the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or
-
the delegate type parameter and the bean type parameter are both type variables and the upper bound of the bean type parameter is assignable to the upper bound, if any, of the delegate type parameter, or
-
the delegate type parameter is a type variable, the bean type parameter is an actual type, and the actual type is assignable to the upper bound, if any, of the type variable.
8.4. Decorator invocation
Whenever a business method is invoked on an instance of a bean with decorators, the container intercepts the business method invocation and, after processing all interceptors of the method, invokes decorators of the bean. The container searches for the first decorator of the instance that implements the method that is being invoked as a business method. If such decorator exists, the container calls the method of the decorator.
aa) Test decorator of managed bean is called.
- DecoratorInvocationTest.testDecoratorInvocation()
aca) Test injected Event
- ComplexEventDecoratorTest.testOrderedEvents()
- BuiltinEventDecoratorTest.testDecoratorIsResolved()
- BuiltinEventDecoratorTest.testDecoratorIsInvoked()
- BuiltinEventDecoratorTest.testMultipleDecorators()
acb) Test injected Instance
- BuiltinInstanceDecoratorTest.testDecoratorIsResolved()
- BuiltinInstanceDecoratorTest.testDecoratorIsInvoked()
ach) Test injected Conversation
- BuiltinConversationDecoratorTest.testDecoratorIsResolved()
- BuiltinConversationDecoratorTest.testDecoratorIsInvoked()
b) If no such decorator exists, the container invokes the business method of the intercepted instance.
- DecoratorInvocationTest.testDecoratorInvocation()
- DecoratorInvocationTest.testChainedDecoratorInvocation()
d) When any decorator is invoked by the container, it may in turn invoke a method of the delegate. The container intercepts the delegate invocation and searches for the first decorator of the instance such that the decorator occurs after the decorator invoking the delegate, and the decorator implements the method that is being invoked upon the delegate.
- DecoratorInvocationTest.testChainedDecoratorInvocation()
e) If no such decorator exists, the container invokes the business method of the intercepted instance.
- DecoratorInvocationTest.testDecoratorInvocation()
- DecoratorInvocationTest.testChainedDecoratorInvocation()
f) Otherwise, the container calls the method of the decorator.
- DecoratorInvocationTest.testChainedDecoratorInvocation()
Whenever a business method is invoked on an instance of a bean with decorators, the container intercepts the business method invocation and, after processing all interceptors of the method, invokes decorators of the bean.
The container searches for the first decorator of the instance that implements the method that is being invoked as a business method. If no such decorator exists, the container invokes the business method of the intercepted instance. Otherwise, the container calls the method of the decorator.
When any decorator is invoked by the container, it may in turn invoke a method of the delegate. The container intercepts the delegate invocation and searches for the first decorator of the instance such that:
-
the decorator occurs after the decorator invoking the delegate, and
-
the decorator implements the method that is being invoked upon the delegate.
If no such decorator exists, the container invokes the business method of the intercepted instance. Otherwise, the container calls the method of the decorator.
9. Interceptor bindings
Managed beans support interception. Interceptors are used to separate cross-cutting concerns from business logic. The Java Interceptors specification defines the basic programming model and semantics, and how to associate interceptors with target classes. This specification defines various extensions to the Java Interceptors specification, including how to override the interceptor order defined by the @Priority
annotation.
9.1. Interceptor binding types
This specification extends the Java Interceptors specification and allows interceptor bindings to be applied to CDI stereotypes.
9.1.1. Interceptor bindings for stereotypes
a) Interceptor bindings may be applied to a stereotype by annotating the stereotype annotation.
- InterceptorDefinitionTest.testStereotypeInterceptorBindings()
b) An interceptor binding declared by a stereotype is inherited by any bean that declares that stereotype.
- InterceptorDefinitionTest.testStereotypeInterceptorBindings()
c) If a stereotype declares interceptor bindings, it must be defined as @Target(TYPE).
Note: Undefined behaviour.
Interceptor bindings may be applied to a stereotype by annotating the stereotype annotation:
@Transactional
@Secure
@RequestScoped
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface Action {}
An interceptor binding declared by a stereotype is inherited by any bean that declares that stereotype.
If a stereotype declares interceptor bindings, it must be defined as @Target(TYPE)
.
9.2. Declaring the interceptor bindings of an interceptor
This specification extends the Java Interceptors specification and defines how the container must behave if a definition error is encountered.
9.3. Binding an interceptor to a bean
c) Interceptor bindings may be used to associate interceptors with any managed bean that is not a decorator.
- SyntheticBeanTest.testSyntheticBeanIntercepted()
- InterceptorDefinitionTest.testInterceptorBindingAnnotation()
- InterceptorDefinitionTest.testInterceptorBindingsCanDeclareOtherInterceptorBindings()
a) The set of interceptor bindings for a method are those declared at class level includes those declared on stereotypes. An interceptor binding declared on a bean class replaces an interceptor binding of the same type declared by a stereotype that is applied to the bean class.
- StereotypeWithMultipleInterceptorBindingsTest.testMultipleInterceptorBindings()
b) If a managed bean has a class-level or method-level interceptor binding, the managed bean must be a proxyable bean type, as defined in Section "unproxyable".
- FinalMethodWithInheritedClassLevelInterceptorTest.testFinalMethodWithInheritedClassLevelInterceptor()
- FinalClassWithInheritedClassLevelInterceptorTest.testFinalClassWithInheritedClassLevelInterceptor()
- DependentBeanFinalMethodInterceptorTest.testFinalMethodWithClassLevelInterceptor()
- FinalClassClassLevelInterceptorTest.testFinalClassWithClassLevelInterceptor()
- FinalClassMethodLevelInterceptorTest.testFinalClassWithMethodLevelInterceptor()
- NormalScopedBeanFinalClassInterceptorTest.testFinalClassWithClassLevelInterceptor()
- FinalMethodClassLevelInterceptorTest.testFinalMethodWithClassLevelInterceptor()
- FinalMethodWithInheritedStereotypeInterceptorTest.testFinalClassWithInheritedStereotypeInterceptor()
- NormalScopedBeanFinalMethodInterceptorTest.testFinalMethodWithClassLevelInterceptor()
- FinalMethodMethodLevelInterceptorTest.testFinalMethodWithMethodLevelInterceptor()
- FinalClassWithInheritedStereotypeInterceptorTest.testFinalMethodWithInheritedStereotypeInterceptor()
This specification extends the Java Interceptors specification and defines:
-
additional restrictions about the type of bean to which an interceptor can be bound, and
-
how the container must behave if a definition error is encountered, and
-
how interceptors are bound using stereotypes.
Interceptor bindings may be used to associate interceptors with any managed bean that is not a decorator.
The set of interceptor bindings for a method declared at class level includes those declared on stereotypes. An interceptor binding declared on a bean class replaces an interceptor binding of the same type declared by a stereotype that is applied to the bean class.
The set of interceptor bindings for a producer method is not used to associate interceptors with the return value of the producer method.
If a managed bean has a class-level or method-level interceptor binding, the managed bean must be a proxyable bean type, as defined in Unproxyable bean types.
9.4. Interceptor enablement and ordering
a) This specification extends the Java Interceptors specification and defines support for enabling interceptors only for a bean archive, as defined by Contexts and Dependency Injection 1.0, and the ability to override the interceptor order using the portable extension SPI, defined in Section "atd".
Note: Statement of intent.
b) An interceptor may be explicitly enabled for a bean archive by listing its class under the <interceptors> element of the beans.xml file of the bean archive.
- InterceptorOrderTest.testInterceptorsCalledInOrderDefinedByBeansXml()
c) The order of the interceptor declarations determines the interceptor ordering. Interceptors which occur earlier in the list are called first.
- InterceptorOrderTest.testInterceptorsCalledInOrderDefinedByBeansXml()
Each child
da) Test with a non-existant class.
- NonExistantClassInBeansXmlTest.testNonExistantClassInBeansXmlNotOk()
db) Test with a class that isn't an interceptor.
- NonInterceptorClassInBeansXmlTest.testNonInterceptorClassInBeansXmlNotOk()
e) If the same class is listed twice under the <interceptors> element, the container automatically detects the problem and treats it as a deployment problem.
- SameClassListedTwiceInBeansXmlTest.testSameInterceptorClassListedTwiceInBeansXmlNotOk()
f) Interceptors enabled using @Priority are called before interceptors enabled using beans.xml.
- EnterpriseInterceptorOrderingTest.testDecoratorsInWebInfClasses()
- GlobalInterceptorOrderingTest.testOrderingInWebInfClasses()
g) Interceptors declared using interceptor bindings are called after interceptors declared using the Interceptors annotation (or using the corresponding element of a deployment descriptor).
- InterceptorCalledBeforeDecoratorTest.testInterceptorCalledBeforeDecorator()
- SessionBeanInterceptorOrderTest.testInterceptorsDeclaredUsingInterceptorsCalledBeforeInterceptorBinding()
- EnterpriseLifecycleInterceptorDefinitionTest.testLifecycleInterception()
- LifecycleInterceptorOrderTest.testLifecycleCallbackInvocationOrder()
- InterceptorOrderTest.testInterceptorsInvocationOrder()
h) Interceptors declared using interceptor bindings are called before any around-invoke, around-timeout, or lifecycle event callback methods declared on the target class or any superclass of the target class.
- SessionBeanInterceptorOrderTest.testInterceptorsDeclaredUsingInterceptorsCalledBeforeInterceptorBinding()
- EnterpriseLifecycleInterceptorDefinitionTest.testLifecycleInterception()
- LifecycleInterceptorOrderTest.testLifecycleCallbackInvocationOrder()
i) By default, a bean archive has no enabled interceptors.
- EnterpriseInterceptorOrderingTest.testDecoratorsInWebInfClasses()
- DecoratorAndInterceptorTest.testMethodCallbacks()
- GlobalInterceptorOrderingTest.testOrderingInLib()
- InterceptorNotListedInBeansXmlNotEnabledTest.testInterceptorNotListedInBeansXmlNotInvoked()
This specification extends the Java Interceptors specification and defines:
-
support for enabling interceptors only for a bean archive, as defined by Contexts and Dependency Injection 1.0, and
-
the ability to override the interceptor order using the portable extension SPI, defined in
AfterTypeDiscovery
event.
An interceptor may be explicitly enabled for a bean archive by listing its class under the <interceptors>
element of the beans.xml
file of the bean archive.
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"">
<interceptors>
<class>com.acme.myfwk.TransactionInterceptor</class>
<class>com.acme.myfwk.LoggingInterceptor</class>
</interceptors>
</beans>
The order of the interceptor declarations determines the interceptor ordering. Interceptors which occur earlier in the list are called first.
Each child <class>
element must specify the name of an interceptor class. If there is no class with the specified name, or if the class with the specified name is not an interceptor class, the container automatically detects the problem and treats it as a deployment problem.
If the same class is listed twice under the <interceptors>
element, the container automatically detects the problem and treats it as a deployment problem.
Interceptors enabled using @Priority
are called before interceptors enabled using beans.xml
.
An interceptor is said to be enabled if it is enabled in at least one bean archive or is listed in the final list of interceptors for the application, as defined in AfterTypeDiscovery
event.
9.5. Interceptor resolution
a) This specification extends the Java Interceptors specification and defines the effect of applying @Nonbinding to an interceptor binding member, and how the interceptor bindings of a custom implementation of the Interceptor interface are determined.
Note: Statement of intent.
b) If any interceptor binding has a member annotated @javax.enterprise.util.Nonbinding, the member is ignored when performing interceptor resolution, and the method does not need to have the same annotation member value.
- InterceptorBindingTypeWithMemberTest.testInterceptorBindingTypeWithNonBindingMember()
For a custom implementation of the Interceptor interface defined in Section "interceptor", the container calls getInterceptorBindings() to determine the interceptor bindings of the interceptor and intercepts() to determine if the interceptor intercepts a given kind of lifecycle callback or business method.
ca) Check for @PostConstruct
- CustomInterceptorTest.testCustomPostConstructInterceptor()
cb) Check for @PreDestroy
- CustomInterceptorTest.testCustomPreDestroyInterceptor()
cc) Check for @PostActivate
- CustomInterceptorTest.testCustomPostActivateInterceptor()
cd) Check for @PrePassivate
- CustomInterceptorTest.testCustomPrePassivateInterceptor()
ce) Check for @AroundInvoke
- CustomInterceptorTest.testCustomAroundInvokeInterceptor()
cf) Check for @AroundTimeout
- CustomInterceptorTest.testCustomAroundTimeoutInterceptor()
This specification extends the Java Interceptors specification and defines:
-
the effect of applying
@Nonbinding
to an interceptor binding member, and -
how the interceptor bindings of a custom implementation of the
Interceptor
interface are determined.
If any interceptor binding has a member annotated @javax.enterprise.util.Nonbinding
, the member is ignored when performing interceptor resolution, and the method does not need to have the same annotation member value.
For a custom implementation of the Interceptor
interface defined in The Interceptor
interface, the container calls getInterceptorBindings()
to determine the interceptor bindings of the interceptor and intercepts()
to determine if the interceptor intercepts a given kind of lifecycle callback or business method.
10. Events
Beans may produce and consume events. This facility allows beans to interact in a completely decoupled fashion, with no compile-time dependency between the interacting beans. Most importantly, it allows stateful beans in one architectural tier of the application to synchronize their internal state with state changes that occur in a different tier.
An event comprises:
-
A Java object - the event object
-
A set of instances of qualifier types - the event qualifiers
The event object acts as a payload, to propagate state from producer to consumer. The event qualifiers act as topic selectors, allowing the consumer to narrow the set of events it observes.
An observer method acts as event consumer, observing events of a specific type - the observed event type - with a specific set of qualifiers - the observed event qualifiers. An observer method will be notified of an event if the event object is assignable to the observed event type, and if the set of observed event qualifiers is a subset of all the event qualifiers of the event.
10.1. Event types and qualifier types
aa) An event object is an instance of a concrete Java class with no unresolvable type variables.
- EventTypesTest.testEventTypeIsConcreteTypeWithNoTypeVariables()
c) The event types of the event include all superclasses and interfaces of the runtime class of the event object.
- EventTypesTest.testEventTypeIncludesAllSuperclassesAndInterfacesOfEventObject()
cb) An event type may not contain an unresolvable type variable.
d) An event qualifier type is a Java annotation defined as @Target({FIELD, PARAMETER}) or @Target({METHOD, FIELD, PARAMETER, TYPE})
- EventBindingTypesTest.testEventBindingTypeTargetsMethodFieldParameterElementTypes()
- EventBindingTypesTest.testEventBindingTypeTargetsFieldParameterElementTypes()
- EventBindingTypesTest.testNonRuntimeBindingTypeIsNotAnEventBindingType()
- EventBindingTypesTest.testFireEventWithNonRuntimeBindingTypeFails()
g) All event qualifier types must specify the @javax.inject.Qualifier meta-annotation
- EventBindingTypesTest.testFireEventWithNonBindingAnnotationsFails()
i) Every event has the qualifier @javax.enterprise.inject.Any, even if it does not explicitly declare this qualifier.
- EventBindingTypesTest.testEventAlwaysHasAnyBinding()
- ImplicitEventTest.testImplicitEventHasAnyBinding()
j) Any Java type may be an observed event type.
- EventTypesTest.testEventTypeIsConcreteTypeWithNoTypeVariables()
- EventTypesTest.testEventTypeIsArray()
An event object is an instance of a concrete Java class with no unresolvable type variables. The event types of the event include all superclasses and interfaces of the runtime class of the event object.
An event type may not contain an unresolvable type variable.
An event qualifier type is just an ordinary qualifier type as specified in Defining new qualifier types, typically defined as @Target({METHOD, FIELD, PARAMETER, TYPE})
or @Target({FIELD, PARAMETER})
.
Every event has the qualifier @javax.enterprise.inject.Any
, even if it does not explicitly declare this qualifier.
Any Java type may be an observed event type.
10.2. Firing events
a) Beans fire events via an instance of the javax.enterprise.event.Event interface, which may be injected.
- FireEventTest.testInjectedAnyEventCanFireEvent()
c) Any combination of qualifiers may be specified at the injection point.
- FireEventTest.testInjectedEventCanHaveBindings()
d) Or, the @Any qualifier may be used, allowing the application to specify qualifiers dynamically.
- FireEventTest.testInjectedEventCanSpecifyBindingsDynamically()
Beans fire events via an instance of the javax.enterprise.event.Event
interface, which may be injected:
@Inject Event<LoggedInEvent> loggedInEvent;
Any combination of qualifiers may be specified at the injection point:
@Inject @Admin Event<LoggedInEvent> adminLoggedInEvent;
Or the application may specify qualifiers dynamically:
@Inject Event<LoggedInEvent> loggedInEvent;
...
LoggedInEvent event = new LoggedInEvent(user);
if ( user.isAdmin() ) {
loggedInEvent.select( new AdminQualifier() ).fire(event);
}
else {
loggedInEvent.fire(event);
}
In this example, the event sometimes has the qualifier @Admin
, depending upon the value of user.isAdmin()
.
10.2.1. Firing events synchronously
b) The method fire() accepts an event object.
- FireEventTest.testInjectedEventAcceptsEventObject()
e) Event fired with the fire() method is fired synchronously. All the resolved synchronous observers are called in the thread in which fire() was called.
- FireSyncEventTest.testSyncObservesCalledInSameThread()
f) A synchronous observer notification blocks the calling thread until it completes.
- FireSyncEventTest.testSyncObservesCalledInSameThread()
The method fire()
accepts an event object:
public void login() {
...
loggedInEvent.fire( new LoggedInEvent(user) );
}
Event fired with the fire()
method is fired synchronously. All the resolved synchronous observers are called in the thread in which fire()
was called. A synchronous observer notification blocks the calling thread until it completes.
10.2.2. Firing events asynchronously
a) Event fired with the fireAsync() method is fired asynchronously. All resolved synchronous observers are called in the same thread in which fireAsync() was called, and all the resolved asynchronous observers are called in one or more different thread.
- MixedObserversTest.testAsyncObserversCalledInDifferentThread()
b) The method fireAsync accepts an event object which can be qualified with the rules defined in Section 10.2, “Firing events synchronously”.
- MixedObserversTest.testQualifiedAsyncEventIsDelivered()
Events may also be fired asynchronously using one of the methods fireAsync()
@Inject Event<LoggedInEvent> loggedInEvent;
public void login() {
...
loggedInEvent.fireAsync( new LoggedInEvent(user) );
}
Event fired with the fireAsync()
method is fired asynchronously. All resolved synchronous observers are called in the same thread in which fireAsync()
was called, and all the resolved asynchronous observers are called in one or more different threads.
If synchronous observer have to be notified, fireAsync
returns immediately after the last synchronous observer has returned. Otherwise it returns immediately.
The method fireAsync
accepts an event object which can be qualified with the rules defined in Firing events.
10.2.3. The Event
interface
ca) The Event interface provides a method for firing events with a specified combination of type and qualifiers.
- FireEventTest.testEventProvidesMethodForFiringEventsWithCombinationOfTypeAndBindings()
cb) For an injected Event, the specified type is the type parameter specified at the injection point, and the specified qualifiers are the qualifiers specified at the injection point.
- FireEventTest.testInjectedEventAcceptsEventObject()
- FireEventTest.testInjectedEventCanHaveBindings()
eaa) The select() method returns a child Event for a given specified type and additional specified qualifiers. If no specified type is given, the specified type is the same as the parent.
- SelectEventTest.testEventSelectReturnsEventOfSameType()
eab) If the specified type contains a type variable, an IllegalArgumentException is thrown.
- SelectEventTest.testEventSelectThrowsExceptionIfEventTypeHasTypeVariable()
eba) If two instances of the same qualifier type are passed to select(), an IllegalArgumentException is thrown.
- SelectEventTest.testEventSelectThrowsExceptionForDuplicateBindingType()
- SelectEventTest.testEventSelectWithSubtypeThrowsExceptionForDuplicateBindingType()
ec) If an instance of an annotation that is not a qualifier type is passed to select(), an IllegalArgumentException is thrown.
- SelectEventTest.testEventSelectThrowsExceptionIfAnnotationIsNotBindingType()
- SelectEventTest.testEventSelectWithSubtypeThrowsExceptionIfAnnotationIsNotBindingType()
eda) The method fire() and fireAsync() fire an event with the specified qualifiers and notifies observers, as defined by Section 10.5, "Observer notification".
- MixedObserversTest.testQualifiedAsyncEventIsDelivered()
- FireEventTest.testEventSelectedFiresAndObserversNotified()
edb) If the container is unable to resolve the parameterized type of the event object, it uses the specified type to infer the parameterized type of the event types.
- ParameterizedEventTest.testSelectedEventTypeUsedForResolvingEventTypeArguments()
- ParameterizedEventTest.testSelectedEventTypeUsedForResolvingEventTypeArguments2()
- ParameterizedEventTest.testSelectedEventTypeCombinedWithEventObjectRuntimeTypeForResolvingEventTypeArguments()
- ParameterizedEventTest.testSelectedEventTypeCombinedWithEventObjectRuntimeTypeForResolvingEventTypeArguments2()
ee) The method fireAsync() may be called with a specific Executor object to be used to invoke observers method.
- FireAsyncWithCustomExecutorTest.testCustomExecutor()
ef) The container should provide a default Executor when fireAsync() is called without specifying one.
- MixedObserversTest.testQualifiedAsyncEventIsDelivered()
f) If the runtime type of the event object contains an unresolvable type variable, an IllegalArgumentException is thrown.
- ParameterizedEventTest.testUnresolvedTypeVariableDetected1()
- ParameterizedEventTest.testUnresolvedTypeVariableDetected2()
- ParameterizedEventTest.testUnresolvedTypeVariableDetected3()
- FireEventTest.testEventFireThrowsExceptionIfEventObjectTypeContainsUnresovableTypeVariable()
g) If the runtime type of the event object is assignable to the type of a container lifecycle event, IllegalArgumentException is thrown.
- FireEventTest.testFireContainerLifecycleEvent()
h) If the provided executor cannot execute observers notification, an IllegalArgumentException is thrown.
The Event
interface provides a method for firing events with a specified combination of type and qualifiers:
public interface Event<T> {
public void fire(T event);
public <U extends T> CompletionStage<U> fireAsync(U event);
public <U extends T> CompletionStage<U> fireAsync(U event, Executor executor);
public Event<T> select(Annotation... qualifiers);
public <U extends T> Event<U> select(Class<U> subtype, Annotation... qualifiers);
public <U extends T> Event<U> select(TypeLiteral<U> subtype, Annotation... qualifiers);
}
For an injected Event
:
-
the specified type is the type parameter specified at the injection point, and
-
the specified qualifiers are the qualifiers specified at the injection point.
For example, this injected Event
has specified type LoggedInEvent
and specified qualifier @Admin
:
@Inject @Admin Event<LoggedInEvent> any;
The select()
method returns a child Event
for a given specified type and additional specified qualifiers. If no specified type is given, the specified type is the same as the parent.
For example, this child Event
has required type AdminLoggedInEvent
and additional specified qualifier @Admin
:
Event<AdminLoggedInEvent> admin = any.select(
AdminLoggedInEvent.class,
new AdminQualifier() );
If the specified type contains a type variable, an IllegalArgumentException
is thrown.
If two instances of the same qualifier type are passed to select()
, an IllegalArgumentException
is thrown.
If an instance of an annotation that is not a qualifier type is passed to select()
, an IllegalArgumentException
is thrown.
The methods fire()
and fireAsync()
fire an event with the specified qualifiers and notify observers, as defined by Observer notification. If the container is unable to resolve the parameterized type of the event object, it uses the specified type to infer the parameterized type of the event types.
The method fireAsync()
may be called with a specific Executor
object to be used to invoke observers method. The container should provide a default Executor
when fireAsync()
is called without specifying one.
If the runtime type of the event object contains an unresolvable type variable, an IllegalArgumentException
is thrown.
If the runtime type of the event object is assignable to the type of a container lifecycle event, an IllegalArgumentException
is thrown.
If the provided executor cannot execute observers notification, an IllegalArgumentException
is thrown.
10.2.4. The built-in Event
a) The container must provide a built-in bean with Event<X> in its set of bean types, for every Java type x that does not contain a type variable.
- ImplicitEventTest.testImplicitEventExistsForEachEventType()
b) The container must provide a built-in bean with every event qualifier type in its set of qualifier types.
- ImplicitEventTest.testImplicitEventHasAllExplicitBindingTypes()
d) The container must provide a built-in bean with scope @Dependent.
- ImplicitEventTest.testImplicitEventHasDependentScope()
e) The container must provide a built-in bean with no bean name.
- RawEventInitMethodInjectionTest.testDefinitionError()
- RawEventProducerMethodInjectionTest.testDefinitionError()
- RawEventDisposerInjectionTest.testDefinitionError()
- RawEventProcessInjectionPointTest.testDefinitionError()
- RawEventFieldInjectionTest.testDefinitionError()
- RawEventCustomBeanTest.testDefinitionError()
- RawEventObserverInjectionTest.testDefinitionError()
- RawEventConstructorInjectionTest.testDefinitionError()
- ImplicitEventTest.testImplicitEventHasNoName()
- RawEventInitMethodInjectionTest.testDefinitionError()
- RawEventProducerMethodInjectionTest.testDefinitionError()
- RawEventDisposerInjectionTest.testDefinitionError()
- RawEventProcessInjectionPointTest.testDefinitionError()
- RawEventFieldInjectionTest.testDefinitionError()
- RawEventCustomBeanTest.testDefinitionError()
- RawEventObserverInjectionTest.testDefinitionError()
- RawEventConstructorInjec