A Web Bean implementation implements the API types of the Web Bean. The developer must follow certain rules when defining a Web Bean implementation. However, the rules depend upon what kind of Web Bean it is. The Web Bean manager provides built-in support for the following kinds of Web Bean:
Simple Web Beans (Java classes)
Enterprise Web Beans (EJB session and singleton beans)
Producer methods
JMS endpoints (topics and queues)
An application or third-party framework may support other kinds of Web Beans by implementing the Bean interface and registering the implementation with the Web Bean manager, as defined in Section 10.2, “Web Bean registration”.
Open issue: should the functionality that is currently defined for JMS endpoints be generalized to support other Java EE resources such as Web Service endpoints, connectors and JDBC datasources?
Most Web Beans are implemented by an annotated Java class, possibly an EJB bean class, called the implementation class of the Web Bean. Implementation classes are defined in Section 3.2, “Simple Web Beans” and Section 3.3, “Enterprise Web Beans”.
This specification places very few restrictions upon the implementation class of a Web Bean. In particular, the class is a concrete class and is not required to implement any special interface or extend any special superclass. Therefore, Web Bean implementation classes are easy to instantiate and unit test.
However, if the application directly instantiates an implementation class of a Web Bean, instead of letting the Web Bean manager perform instantiation, the capabilities listed in Section 2.1, “Functionality provided by the Web Bean manager to the Web Bean” will not be available to that particular class instance. In a deployed application, it is the Web Beans implementation that is responsible for instantiating Web Beans and initializing their dependencies.
If the application requires full control over instantiation of a Web Bean, a producer method may be used. A producer method is just an annotated method of another Web Bean that is invoked by the Web Bean manager to instantiate the Web Bean. Producer methods are defined in Section 3.4, “Producer methods”. However, a similar restriction exists for producer methods: if the application calls the producer method directly, instead of letting the Web Bean manager call it, the capabilities listed in Section 2.1, “Functionality provided by the Web Bean manager to the Web Bean” will not be available to the returned instance.
A simple Web Bean is a Web Bean that is implemented by a Java class. This class is called the implementation class of the simple Web Bean.
The implementation class of a simple Web Bean may not be a non-static inner class or a parameterized type.
The implementation class of a simple Web Bean may not be an abstract class, unless the simple Web Bean is a Web Beans decorator.
If the implementation class of a simple Web Bean is annotated with both the @Interceptor and @Decorator stereotypes, a DefinitionException is thrown by the Web Bean manager at initialization time.
Note that multiple simple Web Beans may share the same implementation class. This occurs when Web Beans are defined using XML. Only one simple Web Bean per implementation class may be defined using annotations.
A top-level Java class is a simple Web Bean if it meets the following conditions:
It is not a parameterized type.
It is not a non-static inner class.
It is a concrete class, or is annotated @Decorator.
It is not annotated with any of the following annotations:
the JPA @Entity annotation,
the EJB component-defining annotations.
It does not implement any of the following interfaces:
javax.servlet.Servlet
javax.servlet.Filter
javax.servlet.ServletContextListener
javax.servlet.HttpSessionListener
javax.servlet.ServletRequestListener
javax.ejb.EnterpriseBean
It does not extend javax.faces.component.UIComponent.
It is not declared as an EJB bean class in ejb-jar.xml.
It is not declared as a JPA entity in orm.xml.
It has an appropriate constructor—either:
the class has a constructor with no parameters, or
the class declares a constructor annotated @Initializer.
All Java classes that meet these conditions are simple Web Beans and thus no special declaration is required to define a simple Web Bean. Additional simple Web Beans for the class may be defined using XML, by specifying the class in web-beans.xml.
The set of API types for a simple Web Bean contains the implementation class, every superclass and all interfaces it implements directly or indirectly.
Note the additional restrictions upon API types of Web Beans with normal scope types defined in Section 4.4.1, “Unproxyable API types”.
A simple Web Bean with a constructor that takes no parameters does not require any special annotations. The following classes are Web Beans:
public class Shop { .. }
class PaymentProcessorImpl implements PaymentProcessor { ... }
An implementation class may also specify a scope type, name, deployment type, stereotypes and/or binding annotations:
@ConversationScoped @Current public class ShoppingCart { ... }
A simple Web Bean may extend another simple Web Bean:
@Named("loginAction") public class LoginAction { ... }
@Mock @Named("loginAction") public class MockLoginAction extends LoginAction { ... }
The second Web Bean is a "mock object" that overrides the implementation of LoginAction when running in an embedded EJB Lite based integration testing environment.
Simple Web Beans may be declared in web-beans.xml using the implementation class name.
<myapp:Order> <deployment:Staging/> <ConversationScoped/> ... </myapp:Order>
A simple Web Bean declared using XML must explicitly declare all producer, disposal and observer methods in XML. Any annotations of the implementation class that define producer, disposal or observer methods are ignored.
A simple Web Bean may even be declared at any injection point declared in XML, as defined in Section 9.6, “Inline Web Bean declarations”, in which case no binding types are specified.
If the implementation class of a simple Web Bean defined in XML is a parameterized type or a non-static inner class, a DefinitionException is thrown by the Web Bean manager at initialization time.
If the implementation class of a simple Web Bean defined in XML is an abstract class, and the simple Web Bean is not a Web Beans decorator, a DefinitionException is thrown by the Web Bean manager at initialization time.
If the implementation class of a simple Web Bean defined in XML is annotated @Interceptor, then the Web Bean must be explicitly declared as an interceptor in XML, as defined in Section 6.2.5.2, “Declaring a Web Beans interceptor using XML”. If a simple Web Bean defined in XML has an implementation class annotated @Interceptor and is not declared as an interceptor in XML, a DefinitionExceptionis thrown by the Web Bean manager at initialization time.
If the implementation class of a simple Web Bean defined in XML is annotated @Decorator, then the Web Bean must be explicitly declared as a decorator in XML, as defined in Section 6.3.2, “Declaring a decorator using XML”. If a simple Web Bean defined in XML has an implementation class annotated @Decorator and is not declared as a decorator in XML, a DefinitionException is thrown by the Web Bean manager at initialization time.
When the Web Bean manager instantiates a simple Web Bean, it calls the Web Bean constructor.
The application may call Web Bean constructors directly. However, if the application directly instantiates the Web Bean, no parameters are passed to the constructor by the Web Bean manager; the returned object is not bound to any context; no dependencies are injected by the Web Bean manager; and the lifecycle of the new instance is not managed by the Web Bean manager.
The Web Bean constructor may be identified by annotating the constructor @Initializer.
@SessionScoped public class ShoppingCart { private User customer; @Initializer 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; @Initializer 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 simple Web Bean defined using annotations does not explicitly declare a constructor using @Initializer, the constructor that accepts no parameters is the Web Bean constructor.
If a simple Web Bean defined using annotations has more than one constructor annotated @Initializer, a DefinitionException is thrown by the Web Bean manager at initialization time.
If a Web Bean constructor has a parameter annotated @Disposes, or @Observes, a DefinitionException is thrown by the Web Bean manager at initialization time.
For a simple Web Bean defined using XML, the Web Bean constructor may be specified by listing the parameter types of the constructer, in order, as direct children of the element that declares the Web Bean.
<myapp:ShoppingCart> <ConversationScoped/> <myapp:User/> </myapp:ShoppingCart>
<myapp:Order> <ConversationScoped/> <myapp:Product> <Selected/> </myapp:Product> <myapp:User/> </myapp:Order>
If a simple Web Bean defined using XML does not explicitly declare constructor parameters in XML, the constructor that accepts no parameters is the Web Bean constructor.
If a simple Web Bean declared in XML does not have a constructor with the parameter types declared in XML, a NonexistentConstructorException is thrown by the Web Bean manager at initialization time.
When a Web Bean constructor is declared in XML, the Web Bean manager ignores binding annotations applied to Java constructor parameters.
Open issue: should it default to use the constructor annotated @Initializer?
If the Web Bean constructor has parameters, the Web Bean manager calls the method Manager.getInstanceByType() defined in Section 4.9, “Instance resolution” to determine a value for each parameter and calls the constructor with those parameter values.
If an implementation class of a simple Web Bean X defined using annotations is annotated @Specializes, then the implementation class of X must directly extend the implementation class of another simple Web Bean Y defined using annotations. Then:
X inherits all binding types of Y, and
if Y has a name, X has the same name as Y.
We say that X directly specializes Y, and we can be certain that Y will never be instantiated or called by the Web Bean manager if X is enabled.
If the implementation class of X does not directly extend the implementation class of another simple Web Bean, a DefinitionException is thrown by the Web Bean manager at initialization time.
For example, MockLoginAction directly specializes LoginAction:
public class LoginAction { ... }
@Mock @Specializes public class MockLoginAction extends LoginAction { ... }
If a simple Web Bean X defined in XML declares the <Specializes> element, then the implementation class of X must be the implementation class of another simple Web Bean Y defined using annotations. Then:
X inherits all binding types of Y, and
if Y has a name, X has the same name as Y.
We say that X directly specializes Y, and we can be certain that Y will never be instantiated or called by the Web Bean manager if X is enabled.
The default name for a simple Web Bean is the unqualified class name of the Web Bean implementation class, after converting the first character to lower case.
For example, if the implementation class is named ProductList, the default Web Bean name is productList.
An enterprise Web Bean is a Web Bean that is implemented by an EJB 3 style session or singleton bean. The bean class is called the implementation class of the enterprise Web Bean.
An EJB stateless session bean must belong to the @Dependent pseudo-scope. An EJB singleton bean must belong to either the @ApplicationScoped scope or to the @Dependent pseudo-scope. If an enterprise Web Bean specifies an illegal scope, a DefinitionException is thrown by the Web Bean manager at initialization time.
Note that multiple enterprise Web Beans may share the same implementation class. This occurs when Web Beans are defined using XML. Only one Web Bean per implementation class may be defined using annotations.
However, in any deployment, there may be at most one most specialized enabled enterprise Web Bean for any particular EJB enterprise bean. Therefore, for each distinct EJB name in a module, there is at most one Web Bean that may be called at runtime. If there is more than one most specialized enabled enterprise Web Bean for a particular EJB enterprise bean, a DeploymentException is thrown by the Web Bean manager at initialization time. This restriction exists because the Web Bean manager is not aware of the binding types of the client injection point when the Web Bean manager intercepts the lifecycle callbacks of the EJB bean, as defined in Section 5.8, “Lifecycle of EJB beans”.
If the implementation class of an enterprise Web Bean is annotated @Interceptor or @Decorator, a DefinitionException is thrown by the Web Bean manager at initialization time.
All EJB 3 style session and singleton beans declared via an EJB component defining annotation on the EJB bean class are Web Beans, and thus no special declaration is required. Additional enterprise Web Beans for these EJBs may be defined using XML, by specifying the bean class in web-beans.xml.
All EJB 3 style session and singleton beans declared in ejb-jar.xml are also Web Beans. Additional enterprise Web Beans for these EJBs may be defined using XML, by specifying the bean class and EJB name in web-beans.xml.
However, when a plugin Web Bean manager is used in a Java EE 5 environment, support for injection of enterprise Web Beans that implement multiple local interfaces and have any scope other than @Dependent is not required.
The set of API types for an enterprise Web Bean contains all local interfaces of the bean that do not have wildcard type parameters or type variables and their superinterfaces. If the EJB bean has a bean class local view and the bean class is not a parameterized type, the set of API types contains the bean class and all superclasses. In addition, java.lang.Object is an API type of every enterprise Web Bean.
Remote interfaces are not included in the set of API types.
An enterprise Web Bean does not require any special annotations. The following EJBs are Web Beans:
@Singleton class Shop { .. }
@Stateless class PaymentProcessorImpl implements PaymentProcessor { ... }
An implementation class may also specify a scope type, name, deployment type, stereotypes and/or binding annotations:
@ConversationScoped @Stateful @Current @Model public class ShoppingCart { ... }
An enterprise Web Bean implementation class may extend another Web Bean implementation class:
@Stateless @Named("loginAction") public class LoginActionImpl implements LoginAction { ... }
@Stateless @Mock @Named("loginAction") public class MockLoginActionImpl extends LoginActionImpl { ... }
Enterprise Web Beans may be declared in web-beans.xml using the bean class name (for EJBs defined using a component-defining annotation) or bean class and EJB name (for EJBs defined in ejb-jar.xml).
<myapp:OrderBean> <deployment:Staging/> <ConversationScoped/> ... </myapp:OrderBean>
<myapp:OrderBean ejbName="RushOrder"> <myapp:Rush/> <ConversationScoped/> ... </myapp:OrderBean>
The ejbName attribute declares the EJB name of an EJB defined in ejb-jar.xml.
An enterprise Web Bean declared using XML must explicitly declare all producer, disposal and observer methods in XML. Any annotations of the implementation class that define producer, disposal or observer methods are ignored.
Enterprise Web Beans declared in XML may not be singleton beans. If an enterprise Web Bean declared in XML is a singleton bean, a DefinitionException is thrown by the Web Bean manager at initialization time.
Enterprise Web Beans may not be message-driven beans. If an enterprise Web Bean declared in XML is a message-driven bean, a DefinitionException is thrown by the Web Bean manager at initialization time.
When the Web Bean manager destroys an enterprise Web Bean instance that is an EJB stateful session bean, it calls the Web Bean remove method.
If an enterprise Web Bean that is a stateful session bean does not have a Web Bean remove method, it must be scoped @Dependent and the application must explicitly destroy every instance of the Web Bean by calling an EJB remove method before the Web Bean manager attempts to destroy the instance as specified by Section 8.3.4, “Dependent object destruction”.
If an enterprise Web Bean that is a stateful session bean and does not have a Web Bean remove method declares any scope other than @Dependent, a DefinitionException is thrown by the Web Bean manager at initialization time.
If an instance of an enterprise Web Bean that is a stateful session bean and does not have a Web Bean remove method is not explicitly destroyed by the application before the Web Bean manager attempts to destroy the instance, an UnremovedException is thrown by the Web Bean manager, as defined in Section 5.4, “Lifecycle of stateful session enterprise Web beans”.
The application may call any EJB remove method, at any time, but then no parameters will be passed to the method by the Web Bean manager. However, whenever any remove method of a Web Bean instance is called by the application, the Web Bean manager must remove the instance from the context with which it is associated.
Open issue: what restrictions exist upon invoking dependencies from the remove method?
The Web Bean remove method may be identified by annotating an EJB remove method @Destructor.
@ConversationScoped @Stateful public class Order { @Destructor @Remove public remove(Log log) { ... } }
If an enterprise Web Bean defined using annotations does not explicitly declare a Web Bean remove method using @Destructor, and a remove method that accepts no parameters exists, then that remove method is the Web Bean remove method. Otherwise, if no remove method that accepts no parameters exists, the enterprise Web Bean has no Web Bean remove method.
If an enterprise Web Bean defined using annotations has more than one method annotated @Destructor, a DefinitionException is thrown by the Web Bean manager at initialization time.
If an enterprise Web Bean defined using annotations has a method annotated @Destructor, and that method is not an EJB remove method, a DefinitionException is thrown by the Web Bean manager at initialization time.
If a Web Bean remove method is annotated @Initializer or @Produces, has a parameter annotated @Disposes, or has a parameter annotated @Observes, a DefinitionException is thrown by the Web Bean manager at initialization time.
For an enterprise Web Bean defined using XML, the Web Bean remove method may be specified using the name of the remove method, and the <Destructor> element.
<myapp:Order> <ConversationScoped/> <myapp:remove> <Destructor/> <myfwk:Log/> </myapp:remove> </myapp:ShoppingCart>
If an enterprise Web Bean defined using XML does not explicitly declare a Web Bean remove method, and a remove method that accepts no parameters exists, the remove method that accepts no parameters is the Web Bean remove method. Otherwise, if no remove method that accepts no parameters exists, the enterprise Web Bean has no Web Bean remove method.
If the implementation class of an enterprise Web Bean declared in XML does not have an EJB remove method with the name and parameter types declared in XML, a NonexistentMethodException is thrown by the Web Bean manager at initialization time.
If an enterprise Web Bean defined using XML declares more than one Web Bean remove method in XML, a DefinitionException is thrown by the Web Bean manager at initialization time.
When a Web Bean remove method is declared in XML, the Web Bean manager ignores binding annotations applied to the Java method parameters.
Open issue: should it default to use the remove method annotated @Destructor?
If an implementation class of an enterprise Web Bean X defined using annotations is annotated @Specializes, then the implementation class of X must directly extend the implementation class of another enterprise Web Bean Y defined using annotations. Then:
X inherits all binding types of Y, and
if Y has a name, X has the same name as Y.
Furthermore:
X must support all local interfaces supported by Y, and
if Y supports a bean-class local view, X must also support a bean-class local view.
Otherwise, a DefinitionException is thrown by the Web Bean manager at initialization time.
We say that X directly specializes Y, and we can be certain that Y will never be instantiated or called by the Web Bean manager if X is enabled.
If the implementation class of X does not directly extend the implementation class of another enterprise Web Bean, a DefinitionException is thrown by the Web Bean manager at initialization time.
For example, MockLoginActionBean directly specializes LoginActionBean:
@Stateless public class LoginActionBean implements LoginAction { ... }
@Stateless @Mock @Specializes public class MockLoginActionBean extends LoginActionBean { ... }
If an enterprise Web Bean X defined in XML declares the <Specializes> element, then the implementation class of X must be the implementation class of another enterprise Web Bean Y defined using annotations. Then:
X inherits all binding types of Y, and
if Y has a name, X has the same name as Y.
We say that X directly specializes Y, and we can be certain that Y will never be instantiated or called by the Web Bean manager if X is enabled.
The default name for an enterprise Web Bean is the unqualified class name of the Web Bean implementation class, after converting the first character to lower case.
For example, if the bean class is named ProductList, the default Web Bean name is productList.
EJB local object references do not implement all local interfaces of the EJB. A local object reference may not be typecast to different local interface type, as required by Section 2.2, “Web Bean API types”. Therefore, the Web Bean manager proxies the local object reference. An enterprise bean proxy implements all local interfaces of the EJB.
When the proxy object is invoked, the proxy obtains the appropriate EJB local object reference from JNDI or using internal container APIs, and delegates the invocation to the local object reference. In either case, the Web Bean manager should follow the procedure defined in Section 10.3, “EJB lookup”.
When an enterprise Web Bean is invoked via the enterprise bean proxy, the interface returned by SessionContext.getInvokedBusinessInterface() will be specific to the Web Bean manager implementation. Portable applications should not rely upon the interface returned by this method.
A Web Beans producer method acts as a source of objects to be injected, where:
the objects to be injected are not required to be instances of Web 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 Web Bean constructor.
A producer method must be a non-static method of a simple Web Bean implementation class or enterprise Web Bean implementation class. If the Web Bean is an enterprise Web Bean, the producer method must be a business method of the EJB.
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 Web Bean manager. This restriction allows the Web Beans manager to use a client proxy, as defined in Section 4.4, “Client proxies”.
If the producer method return type is a parameterized type, it must specify actual type parameters for each type parameter. If a producer method return type contains a wildcard type parameter or type variable, a DefinitionException is thrown by the Web Bean manager at initialization time.
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 Web Beans implementation; the returned object is not bound to any context; and its lifecycle is not managed by the Web Bean manager.
A Web Bean may declare multiple producer methods.
The API types of a producer method depend upon the method return type:
If the return type is an interface, the set of API 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 set of API types contains exactly two types: the method return type and java.lang.Object.
If the return type is a class, the set of API types contains the return type, every superclass and all interfaces it implements directly or indirectly.
Note the additional restrictions upon API types of Web Beans with normal scope types defined in Section 4.4.1, “Unproxyable API types”.
A producer method may be declared by annotating a method with the @Produces annotation.
public class Shop { @Produces PaymentProcessor getPaymentProcessor() { ... } @Produces List<Product> getProducts() { ... } }
A producer method may also specify scope, name, deployment type, stereotypes and/or binding annotations.
public class Shop { @Produces @ApplicationScoped @Catalog @Named("catalog") List<Product> getProducts() { ... } }
If a producer method is annotated @Initializer or @Destructor, has a parameter annotated @Disposes, or has a parameter annotated @Observes, a DefinitionException is thrown by the Web Bean manager at initialization time.
For a Web Beans defined in XML, a producer method may be declared using the method name, the <Produces> element, the return type, and the parameter types of the method:
<myapp:Shop> <myapp:getProducts> <Produces> <ApplicationScoped/> <util:List> <myapp:Product/> <myapp:Catalog/> </util:List> <Named>catalog</Named> </Produces> </myapp:getProducts> </myapp:Shop>
When a producer method is declared in XML, the Web Bean manager ignores binding annotations applied to the Java method or method parameters.
If the implementation class of a Web Bean declared in XML does not have a method with the name and parameter types declared in XML, a NonexistentMethodException is thrown by the Web Bean manager at initialization time.
If the producer method has parameters, the Web Bean manager calls Manager.getInstanceByType() to determine a value for each parameter and calls the producer method with those parameter values.
public class OrderFactory { @Produces @ConversationScoped public Order createCurrentOrder(@New Order order, @Selected Product product) { order.setProduct(product); return order; } }
<myapp:OrderFactory> <myapp:createCurrentOrder> <Produces> <ConversationScoped/> <myapp:Order/> </Produces> <myapp:Order> <New/> </myapp:Order> <myapp:Product> <myapp:Selected/> </myapp:Product> </myapp:createCurrentOrder> </myapp:OrderFactory>
If a producer method X is annotated @Specializes, then it must directly override another producer method Y. Then:
X inherits all binding type of Y, and
if Y has a name, X has the same name as Y.
We say that X directly specializes Y, and we can be certain that Y will never be called by the Web Bean manager if X is enabled.
If the method does not directly override another producer method, a DefinitionException is thrown by the Web Bean manager at initialization time.
For example:
@Mock public class MockShop extends Shop { @Override @Specializes @Produces PaymentProcessor getPaymentProcessor() { return new MockPaymentProcessor(); } @Override @Specializes @Produces List<Product> getProducts() { return PRODUCTS; } ... }
A disposal method allows the application to perform customized cleanup of an object returned by a producer method.
A disposal method must be a non-static method of a simple Web Bean implementation class or enterprise Web Bean implementation class. If the Web Bean is an enterprise Web Bean, the disposal method must be a business method of the EJB.
A Web Bean may declare multiple disposal methods.
Each disposal method must have exactly one disposed parameter, of the same type as the corresponding producer method return type. When searching for disposal methods for a producer method, the Web Bean manager considers the type and binding types of the disposed parameter. If a disposed parameter resolves to a producer method according to the typesafe resolution algorithm, the Web Bean manager must call this method when destroying an instance returned by that producer method.
If the disposed parameter does not resolve to any producer method according to the typesafe resolution algorithm, an UnsatisfiedDependencyException is thrown by the Web Bean manager at initialization time.
A disposal method may be declared using annotations by annotating a parameter @Disposes. That parameter is 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(); } }
If a method has more than one parameter annotated @Disposes, a DefinitionException is thrown by the Web Bean manager.
If a disposal method is annotated @Produces, @Initializer or @Destructor, or has a parameter annotated @Observes, a DefinitionException is thrown by the Web Bean manager at initialization time.
For a Web Beans defined in XML, a disposal method may be declared using the method name, the <Disposes> element, and the parameter types of the method:
<myfwk:UserDatabaseEntityManager> <myfwk:create> <Produces> <ConversationScoped/> <jpa:EntityManager> <myapp:UserDatabase/> </jpa:EntityManager> </Produces> <jpa:EntityManagerFactory/> </myfwk:create> <myfwk:close> <Disposes> <jpa:EntityManager> <myapp:UserDatabase/> </jpa:EntityManager> </Disposes> </myfwk:close> </mmyfwk:UserDatabaseEntityManager>
When a disposal method is declared in XML, the Web Bean manager ignores binding annotations applied to the Java method parameters.
If the implementation class of a Web Bean declared in XML does not have a method with the name and parameter types declared in XML, a NonexistentMethodException is thrown by the Web Bean manager at initialization time.
In addition to the disposed parameter, a disposal method may declare additional parameters, which may also specify binding types. The Web Bean manager calls Manager.getInstanceByType() to determine a value for each parameter of a disposal method and calls the disposal method with those parameter values.
public void close(@Disposes @UserDatabase EntityManager em, @Logger Log log) { ... }
<myfwk:close> <Disposes> <jpa:EntityManager> <myapp:UserDatabase/> </jpa:EntityManager> </Disposes> <myfwk:Log> <myfwk:Logger/> <myfwk:Log> </myfwk:close>
When searching for disposal methods for a producer method, the Web Bean manager searches for disposal methods which satisfy the following rules:
The disposal method must be declared by an enabled Web Bean.
The disposed parameter must resolve to the producer method, according to the typesafe resolution algorithm.
If there are multiple disposal methods for a producer method, a DefinitionException is thrown by the Web Bean manager at initialization time.
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:
public class Shop { @Produces @Named public List<Product> getProducts() { ... } }
This producer method is named paymentProcessor:
public class Shop { @Produces @Named public PaymentProcessor paymentProcessor() { ... } }
Web Beans that send JMS messages must interact with at least two different objects defined by the JMS API:
to send a message to a queue, the Web Bean must interact with a QueueSession and the QueueSender, or
to send a message to a topic, the Web Bean must interact with a TopicSession and the TopicPublisher.
A Web Beans JMS endpoint is a Web Bean that represents a JMS queue or topic. JMS endpoints may be declared in web-beans.xml, and allow direct injection of any of the following JMS objects:
For a queue, the Queue, QueueConnection, QueueSession and/or QueueSender may be injected.
For a topic, the Topic, TopicConnection, TopicSession and/or TopicPublisher may be injected.
The lifecycles of the injected objects are managed by the Web Beans manager, and therefore the application need not explicitly close() any injected JMS object. If the application calls close() on an instance of a JMS endpoint, an UnsupportedOperationException is thrown by the Web Bean manager.
For example:
@PaymentProcessor QueueSender paymentSender; @PaymentProcessor QueueSession paymentSession; public void sendMessage() { MapMessage msg = paymentSession.createMapMessage(); ... paymentSender.send(msg); }
@Prices TopicPublisher pricePublisher; @Prices TopicSession priceSession; public void sendMessage(String price) { priceSender.send( priceSession.createTextMessage(price) ); }
A JMS endpoint must belong to the @Dependent pseudo-scope. If a JMS endpoint specifies any other scope, a DefinitionException is thrown by the Web Bean manager at initialization time.
Web Beans JMS endpoints must explicitly declare at least one binding type, and must not declare the @Current binding type.
A JMS endpoint may not declare a Web Beans name.
JMS endpoints are always declared using XML.
The API types of a JMS endpoint depend upon whether it represents a queue or topic.
If the JMS endpoint represents a queue, the API types are Queue, QueueConnection, QueueSession and QueueSender.
If the JMS endpoint represents a topic, the API types are Topic, TopicConnection, TopicSession and TopicPublisher.
In addition, java.lang.Object is an API type of every JMS endpoint.
A JMS endpoint may be declared using the <Topic> or <Queue> elements in web-beans.xml. The JNDI name of the queue or topic must be specified using <destination> and the JNDI name of the JMS connection factory must be specified using <connectionFactory>.
<Queue> <destination>java:comp/env/jms/PaymentQueue</destination> <connectionFactory>java:comp/env/jms/QueueConnectionFactory</connectionFactory> <myapp:PaymentProcessor/> </Queue>
<Topic> <destination>java:comp/env/jms/Prices</destination> <connectionFactory>java:comp/env/jms/TopicConnectionFactory</connectionFactory> <myapp:Prices/> </Topic>
Open issue: do we need to allow specification of transacted and acknowledgeMode for the session?
An injected field is a non-static, non-final field of a Web Bean implementation class, of a Servlet, or of any EJB session, singleton or message driven bean class.
Injected fields are initialized by the Web Bean manager immediately after instantiation and before any methods of the instance are invoked. The Web Bean implementation calls Manager.getInstanceByType() to determine a value for each injected field.
Any EJB session, singleton or message driven bean running in the context of a Web Beans application may declare injected fields and have those fields injected by the Web Bean manager. The EJB bean is not required to be the implementation class of a Web Bean to take advantage of this functionality.
Open issue: are injected fields allowed to be declared transient? If so, should they be reinjected after deserialization (activation)?
An injected field may be declared by annotating the field with any binding type.
@ConversationScoped public class Order { @Selected Product product; @Current User customer; }
For a Web Beans defined in XML, an injected field may be declared using the field name and a child element representing the type of the field:
<myapp:Order> <ConversationScoped/> <myapp:product> <myapp:Product> <myapp:Selected/> </myapp:Product/> </myapp:product> <myapp:customer> <myapp:User/> </myapp:customer> </myapp:Order>
When an injected field is declared in XML, the Web Bean manager ignores binding annotations applied to the Java field.
If the type element does not declare any binding type, the default binding type @Current is assumed.
If the implementation class of a Web Bean declared in XML does not have a field with the name and type declared in XML, a NonexistentFieldException is thrown by the Web Bean manager at initialization time.
A Web Bean declared using XML has the following injected fields:
all injected fields declared using XML, together with
any injected fields declared using annotations, that were not also declared using XML.
An initializer method is a non-static method of a Web Bean implementation class, of a Servlet, or of any EJB session, singleton or message driven bean class.
Initializer methods are called by the Web Bean manager immediately after injected fields have been initialized by the Web Bean manager and before any other methods of the instance are invoked.
If the Web Bean is an enterprise Web Bean, the initializer method is not required to be a business method of the session bean.
Method interceptors are never called when the Web Bean manager calls an initializer method.
A Web Bean implementation class may declare multiple (or zero) initializer methods.
The application may call initializer methods directly, but then no parameters will be passed to the method by the Web Bean manager.
Any EJB session, singleton or message driven bean running in the context of a Web Beans application may declare initializer methods and have the methods called by the Web Bean manager. The EJB bean is not required to be the implementation class of a Web Bean to take advantage of this functionality.
An initializer method may be declared by annotating the method @Initializer.
@ConversationScoped public class Order { private Product product; private User customer; @Initializer void setProduct(@Selected Product product) { this.product = product; } @Initializer public void setCustomer(User customer) { this.customer = customer; } }
If an initializer method is annotated @Produces or @Destructor, has a parameter annotated @Disposes, or has a parameter annotated @Observes, a DefinitionException is thrown by the Web Bean manager at initialization time.
For a Web Beans defined in XML, an initializer method may be declared using the method name, the <Initializer> element and the parameter types of the method.
<myapp:Order> <ConversationScoped/> <myapp:setProduct> <Initializer/> <myapp:Product> <myapp:Selected/> </myapp:Product> </myapp:setOrder> <myapp:setCustomer> <Initializer/> <myapp:User/> </myapp:setCustomer> </myapp:Order>
When an initializer method is declared in XML, the Web Bean manager ignores binding annotations applied to the Java method parameters.
If the implementation class of a Web Bean declared in XML does not have a method with the name and parameter types declared in XML, a NonexistentMethodException is thrown by the Web Bean manager at initialization time.
A Web Bean declared using XML has the following injected fields and initializer methods:
all initializer methods declared using XML, together with
any initializer methods declared using annotations, that were not also declared using XML.
If an initializer method of a Web Bean declared in XML is declared using both XML and annotations, the annotations are ignored.
Sometimes, the scope of a Web Bean is inconvenient for a particular usecase. One solution to this problem is to obtain an independent instance of the Web Bean implementation and inject it as a dependent object of some other Web Bean, or even bind it to a different context using a producer method.
When the built-in binding type @New is applied to an injection point, a Web Bean is implicitly defined with:
scope @Dependent,
deployment type @Standard,
@New as the only binding annotation,
no Web Bean name,
no stereotypes, and such that
the implementation class is the declared type of the injection point.
If the parameter type satisfies the definition of a simple Web Bean implementation class, Section 3.2.1, “Which Java classes are simple Web Beans?”, then the Web Bean is a simple Web Bean. If the parameter type satisfies the definition of an enterprise Web Bean implementation class, Section 3.3.1, “Which EJBs are enterprise Web Beans?”, then the Web Bean is an enterprise Web Bean.
Furthermore, this Web Bean:
has the same Web Bean constructor, Web Bean remove method, initializer methods and injected fields as a Web Bean defined using annotations—that is, it has any Web Bean constructor, Web Bean remove method, initializer method or injected field declared by annotations that appear on the implementation class,
has the same interceptors as a Web Bean defined using annotations—that is, it has all the interceptor binding types declared by annotations that appear on the implementation class, and
has no decorators.
The @New annotation or <New> element may be applied to any field of a Web Bean implementation class or to any parameter of a producer method, initializer method, disposal method, Web Bean remove method or Web Bean constructor where the type of the field or parameter is a concrete Java type which satisfies the requirements of a simple Web Bean implementation class or enterprise Web Bean implementation class.
@Produces @RequestScoped Payment createPayment(@New Payment payment, Order order) { payment.setOrder(order); return payment; }
<myapp:createPayment> <Produces> <RequestScoped/> <myapp:Payment/> </Produces> <myapp:Payment> <New/> </myapp:Payment> <myapp:Order/> </myapp:createPayment>
In this example, the Payment is created as a dependent object of the producer method Web Bean and is bound to the request context when returned by the method. It is now the current instance of the producer method Web Bean. When the request context ends, the Payment is passed to the corresponding disposal method (if any), and then finally destroyed when all dependent objects of the producer method are destroyed.
The @New annotation and <New> element may not appear in conjunction with any other binding type. They may not be applied to a field or method parameter of a type which does not satisfy the definition of a simple Web Bean implementation class or enterprise Web Bean implementation class.
If the @New binding type appears in conjunction with some other binding type, or is specified for a field or parameter of a type which does not satisfy the definition of a simple Web Bean implementation class or enterprise Web Bean implementation class, a DefinitionException is thrown by the Web Bean manager at initialization time.
No Web Bean defined using annotations or XML may explicitly declare @New as a binding type.
In addition to the capabilities defined by this specification, simple Web Beans also support certain functionality defined by the Common Annotations for the Java Platform and Enterprise JavaBeans specifications.
The following functionality is provided by the Web Bean manager when annotations are applied to the implementation class of a simple Web Bean:
dependency injection via @EJB, @PersistenceContext and @Resource
JNDI lookup of resource references declared via @Resource and @Resources
@PostConstruct and @PreDestroy callbacks
interception, as defined in javax.interceptor
@PersistenceContext(type=EXTENDED) is not supported for simple Web Beans.
Open issue: should @PrePassivate and @PostActivate be supported for simple Web Beans?
Open issue: what restrictions exist upon invoking dependencies from @PreDestroy?
Open issue: we need an additional API in Java EE to delegate EE injection back to the Java EE container for simple Web Beans.
Support for @EJB, @PersistenceContext, @Resource and @Resources is not required when a plugin Web Bean manager is used in a Java EE 5 environment.
This simple Web Bean makes use of annotations defined by the Common Annotations and EJB specifications:
@SessionScoped @Interceptors(MyTransactionInterceptor.class) public class ShoppingCart { private User customer; private Order order; private @Resource Connection connection; private @EJB PaymentProcessor paymentProcessor; private @PersistenceContext(type=EXTENDED) EntityManager entityManager; @Initializer ShoppingCart(User customer) { this.customer = customer; } @PostConstruct void retrieveOrder() { order = entityManager.find( Order.class, customer.getId() ); } ... @PreDestroy void updateOrder() { entityManager.merge(order); } }
Of course, enterprise Web Beans may take advantage of all functionality defined by the EJB specification.
The abstract class Bean provides everything the Web Bean manager needs to manage instances of a certain Web Bean.
public abstract class Bean<T> { private final Manager manager; protected Bean(Manager manager) { this.manager=manager; } protected Manager getManager() { return manager; } public abstract Set<Class> getTypes(); public abstract Set<Annotation> getBindingTypes(); public abstract Class<? extends Annotation> getScopeType(); public abstract Class<? extends Annotation> getDeploymentType(); public abstract String getName(); public abstract boolean isSerializable(); public abstract boolean isNullable(); public abstract T create(); public abstract void destroy(T instance); }
An instance of Bean exists for every enabled Web Bean in a deployment.
An application or third party framework may add support for new kinds of Web Beans beyond those defined by the Web Beans specification (simple Web Beans, enterprise Web Beans, producer methods and JMS endpoints) by extending Bean and registering Web Beans with the Web Bean manager, using the mechanism defined in Section 10.2, “Web Bean registration”.