SeamFramework.orgCommunity Documentation
CDI is fully integrated into the Java EE environment. Beans have access to Java EE resources and JPA persistence contexts. They may be used in Unified EL expressions in JSF and JSP pages. They may even be injected into other platform components, such as servlets and message-driven Beans, which are not beans themselves.
In the Java EE environment, the container provides the following built-in beans, all with the qualifier @Default
:
the current JTA UserTransaction
,
a Principal
representing the current caller identity,
the default Bean Validation ValidationFactory
, and
a Validator
for the default ValidationFactory
.
The CDI specification does not require the servlet context objects, HttpServletRequest
, HttpSession
and ServletContext
to be exposed as injectable beans. If you really want to be able to inject these objects, it's easy to create a portable extension to expose them as beans. However, we recommend that direct access to these objects be limited to servlets, servlet filters and servlet event listeners, where they may be obtained in the usual way as defined by the Java Servlets spec. The FacesContext
is also not injectable. You can get at it by calling FacesContext.getCurrentInstance()
.
Oh, you really want to inject the FacesContext
? Alright then, try this producer method:
class FacesContextProducer {
@Produces @RequestScoped FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
}
All managed beans may take advantage of Java EE component environment injection using @Resource
, @EJB
, @PersistenceContext
, @PeristenceUnit
and @WebServiceRef
. We've already seen a couple of examples of this, though we didn't pay much attention at the time:
@Transactional @Interceptor
public class TransactionInterceptor {
@Resource UserTransaction transaction;
@AroundInvoke public Object manageTransaction(InvocationContext ctx) throws Exception { ... }
}
@SessionScoped
public class Login implements Serializable {
@Inject Credentials credentials;
@PersistenceContext EntityManager userDatabase;
...
}
The Java EE @PostConstruct
and @PreDestroy
callbacks are also supported for all managed beans. The @PostConstruct
method is called after all injection has been performed.
Of course, we advise that component environment injection be used to define CDI resources, and that typesafe injection be used in application code.
It's easy to use a bean from a servlet in Java EE 6. Simply inject the bean using field or initializer method injection.
public class Login extends HttpServlet {
@Inject Credentials credentials;
@Inject Login login;
@Override
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
credentials.setUsername(request.getParameter("username")):
credentials.setPassword(request.getParameter("password")):
login.login();
if ( login.isLoggedIn() ) {
response.sendRedirect("/home.jsp");
}
else {
response.sendRedirect("/loginError.jsp");
}
}
}
Since instances of servlets are shared across all incoming threads, the bean client proxy takes care of routing method invocations from the servlet to the correct instances of Credentials
and Login
for the current request and HTTP session.
CDI injection applies to all EJBs, even when they aren't managed beans. In particular, you can use CDI injection in message-driven beans, which are by nature not contextual objects.
You can even use CDI interceptor bindings for message-driven Beans.
@Transactional @MessageDriven
public class ProcessOrder implements MessageListener {
@Inject Inventory inventory;
@PersistenceContext EntityManager em;
public void onMessage(Message message) {
...
}
}
Please note that there is no session or conversation context available when a message is delivered to a message-driven bean. Only @RequestScoped
and @ApplicationScoped
beans are available.
But how about beans which send JMS messages?
使用JMS发送消息有点复杂,因为你需要处理很多不同的对象。对于队列(Queue),我们有Queue
, QueueConnectionFactory
, QueueConnection
, QueueSession
和 QueueSender
。对于主题(Topic)有Topic
, TopicConnectionFactory
, TopicConnection
, TopicSession
和 TopicPublisher
。这些对象每个都有自己的生命周期和线程模型,我们都需要考虑这些问题。
You can use producer fields and methods to prepare all of these resources for injection into a bean:
public class OrderResources {
@Resource(name="jms/ConnectionFactory")
private ConnectionFactory connectionFactory;
@Resource(name="jms/OrderQueue")
private Queue orderQueue;
@Produces @OrderConnection
public Connection createOrderConnection() throws JMSException {
return connectionFactory.createConnection();
}
public void closeOrderConnection(@Disposes @OrderConnection Connection connection)
throws JMSException {
connection.close();
}
@Produces @OrderSession
public Session createOrderSession(@OrderConnection Connection connection)
throws JMSException {
return connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
}
public void closeOrderSession(@Disposes @OrderSession Session session)
throws JMSException {
session.close();
}
@Produces @OrderMessageProducer
public MessageProducer createOrderMessageProducer(@OrderSession Session session)
throws JMSException {
return session.createProducer(orderQueue);
}
public void closeOrderMessageProducer(@Disposes @OrderMessageProducer MessageProducer producer)
throws JMSException {
producer.close();
}
}
In this example, we can just inject the prepared MessageProducer
, Connection
or QueueSession
:
@Inject Order order;
@Inject @OrderMessageProducer MessageProducer producer;
@Inject @OrderSession QueueSession orderSession;
public void sendMessage() {
MapMessage msg = orderSession.createMapMessage();
msg.setLong("orderId", order.getId());
...
producer.send(msg);
}
The lifecycle of the injected JMS objects is completely controlled by the container.
CDI doesn't define any special deployment archive. You can package beans in jars, ejb jars or wars—any deployment location in the application classpath. However, the archive must be a "bean archive". That means each archive that contains beans must include a file named beans.xml
in the META-INF
directory of the classpath or WEB-INF
directory of the web root (for war archives). The file may be empty. Beans deployed in archives that do not have a beans.xml
file will not be available for use in the application.
In an embeddable EJB container, beans may be deployed in any location in which EJBs may be deployed. Again, each location must contain a beans.xml
file.