SeamFramework.orgCommunity Documentation

Chapter 13. Java EE integration

13.1. Injecting Java EE resources into a Web Bean
13.2. Calling a Web Bean from a Servlet
13.3. Calling a Web Bean from a Message-Driven Bean
13.4. JMS endpoints
13.5. Packaging and deployment

Web Beans is fully integrated into the Java EE environment. Web 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 some objects, such as Servlets and Message-Driven Beans, which are not Web Beans.

All simple and enterprise Web Beans may take advantage of Java EE dependency injection using @Resource, @EJB and @PersistenceContext. 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 Transaction transaction;
    @AroundInvoke public Object manageTransaction(InvocationContext ctx) { ... }
    
}
@SessionScoped

public class Login {
    @Current Credentials credentials;
    @PersistenceContext EntityManager userDatabase;
    
    ...
}

The Java EE @PostConstruct and @PreDestroy callbacks are also supported for all simple and enterprise Web Beans. The @PostConstruct method is called after all injection has been performed.

There is one restriction to be aware of here: @PersistenceContext(type=EXTENDED) is not supported for simple Web Beans.

It's easy to use a Web Bean from a Servlet in Java EE 6. Simply inject the Web Bean using Web Beans field or initializer method injection.

public class Login extends HttpServlet {


    @Current Credentials credentials;
    @Current Login login;
    @Override
    public void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        credentials.setUsername( request.getAttribute("username") ):
        credentials.setPassword( request.getAttribute("password") ):
        login.login();
        if ( login.isLoggedIn() ) {
            response.sendRedirect("/home.jsp");
        }
        else {
            response.sendRedirect("/loginError.jsp");
        }
    }
            
}

The Web Beans 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.

Web Beans injection applies to all EJBs, even when they aren't under the control of the Web Bean manager (if they were obtained by direct JNDI lookup, or injection using @EJB, for example. In particular, you can use Web Beans injection in Message-Driven Beans, which are not considered Web Beans because you can't inject them.

You can even use Web Beans interceptor bindings for Message-Driven Beans.

@Transactional @MessageDriven

public class ProcessOrder implements MessageListener {
    @Current Inventory inventory;
    @PersistenceContext EntityManager em;
    public void onMessage(Message message) {
        ...
    }
            
}

Thus, receiving messages is super-easy in a Web Beans environment. But beware that there is no session or conversation context available when a message is delivered to a Message-Driven Bean. Only @RequestScoped and @ApplicationScoped Web Beans are available.

It's also easy to send messages using Web Beans.

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.

Web Beans takes care of all this for us. All we need to do is declare the queue or topic in web-beans.xml, specifying an associated binding type and connection factory.


<Queue>
    <destination>java:comp/env/jms/OrderQueue</destination>
    <connectionFactory>java:comp/env/jms/QueueConnectionFactory</connectionFactory>
    <myapp:OrderProcessor/>    
</Queue>

<Topic>
    <destination>java:comp/env/jms/StockPrices</destination>
    <connectionFactory>java:comp/env/jms/TopicConnectionFactory</connectionFactory>
    <myapp:StockPrices/>    
</Topic>

Now we can just inject the Queue, QueueConnection, QueueSession or QueueSender for a queue, or the Topic, TopicConnection, TopicSession or TopicPublisher for a topic.

@OrderProcessor QueueSender orderSender;

@OrderProcessor QueueSession orderSession;
public void sendMessage() {
    MapMessage msg = orderSession.createMapMessage();
    ...
    orderSender.send(msg);
}
@StockPrices TopicPublisher pricePublisher;

@StockPrices TopicSession priceSession;
public void sendMessage(String price) {
    pricePublisher.send( priceSession.createTextMessage(price) );
}

The lifecycle of the injected JMS objects is completely controlled by the Web Bean manager.

Web Beans doesn't define any special deployment archive. You can package Web Beans in JARs, EJB-JARs or WARs—any deployment location in the application classpath. However, each archive that contains Web Beans must include a file named web-beans.xml in the META-INF or WEB-INF directory. The file may be empty. Web Beans deployed in archives that do not have a web-beans.xml file will not be available for use in the application.

For Java SE execution, Web Beans may be deployed in any location in which EJBs may be deployed for execution by the embeddable EJB Lite container. Again, each location must contain a web-beans.xml file.