Weld SiteCommunity Documentation

Chapter 14. Java EE integration

14.1. Built-in beans
14.2. Injecting Java EE resources into a bean
14.3. Calling a bean from a servlet
14.4. Calling a bean from a message-driven bean
14.5. JMS endpoints
14.6. Packaging and deployment
14.6.1. Explicit bean archive
14.6.2. Implicit bean archive
14.6.3. Which archive is not a bean archive
14.6.4. Embeddable EJB container

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:

Note

The FacesContext is not injectable. You can get at it by calling FacesContext.getCurrentInstance(). Alternatively you may define the following producer method:

import javax.enterprise.inject.Produces;


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, @PersistenceUnit 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. Simply inject the bean using field or initializer method injection.

public class LoginServlet 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 CDI beans. In particular, you can use CDI injection in message-driven beans, which are by nature not contextual objects.

You can even use 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?

Sending messages using JMS can be quite complex, because of the number of different objects you need to deal with. For queues we have Queue, QueueConnectionFactory, QueueConnection, QueueSession and QueueSender. For topics we have Topic, TopicConnectionFactory, TopicConnection, TopicSession and TopicPublisher. Each of these objects has its own lifecycle and threading model that we need to worry about.

You can use producer fields and methods to prepare all of these resources for injection into a bean:

import javax.jms.ConnectionFactory;

import javax.jms.Queue;
public class OrderResources {
   @Resource(name="jms/ConnectionFactory")
   private ConnectionFactory connectionFactory;
   @Resource(name="jms/OrderQueue")
   private Queue orderQueue;
   @Produces @Order
   public Connection createOrderConnection() throws JMSException {
    return connectionFactory.createConnection();
   }
   public void closeOrderConnection(@Disposes @Order Connection connection)
         throws JMSException {
      connection.close();
   }
   @Produces @Order
   public Session createOrderSession(@Order Connection connection)
         throws JMSException {
      return connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
   }
   public void closeOrderSession(@Disposes @Order Session session)
         throws JMSException {
      session.close();
   }
   @Produces @Order
   public MessageProducer createOrderMessageProducer(@Order Session session)
         throws JMSException {
      return session.createProducer(orderQueue);
   }
   public void closeOrderMessageProducer(@Disposes @Order MessageProducer producer)
         throws JMSException {
      producer.close();
   }
}

In this example, we can just inject the prepared MessageProducer, Connection or QueueSession:

@Inject Order order;

@Inject @Order MessageProducer producer;
@Inject @Order Session 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 CDI beans in JARs, EJB JARs or WARs—any deployment location in the application classpath. However, the archive must be a "bean archive".

Unlike CDI 1.0, the CDI 1.1 specification recognizes two types of bean archives. The type determines the way the container discovers CDI beans in the archive.