Implement RESTful views of a no-interface EJB
If we have EJB applications exposed using a no-interface view, we can expose a RESTful interface to the enterprise bean using Java API for RESTful Web Services (JAX-RS). By implementing JAX-RS annotated enterprise beans, you keep the EJB functionality including transaction support, injection of Java EE components and resources, and other EJB session bean capabilities.
Before EJB 3.1, enterprise beans that required an EJB local client view also needed a separate Java interface, usually located in a separate file, that declared the local view methods. The enterprise bean specified that it implemented the EJB local view interface using deployment descriptors or EJB annotations.
Use the EJB 3.1 specification, we have the option of exposing a local view of an enterprise bean without an explicit EJB local interface. Instead, the enterprise bean has a no-interface client view that is based on the public methods of our bean class. No-interface view enterprise beans can be more simple to develop than a local view enterprise bean for the following reasons:
- No-interface view enterprise beans do not require a separate Java interface declaration.
- No-interface view enterprise beans do not require specifying additional metadata in the deployment descriptor or when using EJB annotations.
See the EJB 3.1 specification for more details on no-interface views of an enterprise bean.
JAX-RS supports the use of enterprise beans that declare a local business interface and no-interface view enterprise beans.
Although we can declare enterprise beans in different ways, it is a best practice to directly implement the EJB business local interface and to always declare the @javax.ejb.Local annotation. By using this method, the EJB bean is required to implement the local business interface, which eliminates errors in typing method names and changes to argument types. By always using the @javax.ejb.Local annotation, if there are ever multiple business interfaces, we can simply add the business interface to the annotation value. We can also use this approach to modify the enterprise bean using a deployment descriptor.bprac
This task describes implementing RESTful views of a no-interface view enterprise bean.
Create a simple enterprise bean with JAX-RS annotations. Even though this task specifically describes how to implement RESTful views of a no-interface view enterprise bean, it is important that you consider the full scope of the application architecture and how we want to expose resources as we decide your resource model and determine which RESTful views are appropriate for our enterprise beans application. These considerations are beyond the scope of this task.
JAX-RS supports stateless and singleton session beans. We can add JAX-RS annotations to the local interface of a session bean. Also, with EJB 3.1, we can add JAX-RS annotations directly to an EJB class if the enterprise bean exposes a no-interface view.
With the EJB 3.1 packaging rules, we can add JAX-RS enterprise beans in the web application archive (WAR) file either directly in the WEB-INF/classes directory or using a Java archive (JAR) file in the WEB-INF/lib directory. We can declare an enterprise bean using annotations, or using an EJB deployment descriptor, or using both annotations and a deployment descriptor.
JAX-RS annotated enterprise beans in a stand-alone file or in a separate ejb-jar file that is included in an EAR is not supported.
Tasks
- Create an enterprise bean. In the following example, there is a simple EJB class called Organization. This class takes advantage of the no-interface view class feature introduced in the EJB 3.1 specification.
public class Organization { public String getInformation() { // return information via a String } }- To expose an enterprise bean as a JAX-RS resource, complete one of the following steps:
- In the WEB-INF/ ejb-jar.xml deployment descriptor file for your enterprise bean, change the JAX-RS plain Java classes to become JAX-RS enabled enterprise beans. For example, we can add the following code snippet to the WEB-INF/ejb-jar.xml deployment descriptor:
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" version="3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"> <!-- This file must exist in the WEB-INF/ directory of our WAR file. See EJB 3.1 spec 20.4 for more details. --> <enterprise-beans> <session> <ejb-name>Organization</ejb-name> <ejb-class>com.example.jaxrs.Organization</ejb-class> <session-type>Stateless</session-type> </session> </enterprise-beans> </ejb-jar>To make the enterprise bean a singleton using the deployment descriptor, use <session-type>Singleton</ session-type> instead of <session-type>Stateless</session-type>.
- Add a @javax.ejb.Stateless annotation to the Java class of our enterprise bean. The following example demonstrates a simple JAX-RS annotated enterprise bean:
package com.example.jaxrs; @javax.ejb.Stateless @javax.ws.rs.Path("/organization/") public class Organization { @javax.ws.rs.GET @javax.ws.rs.Produces("text/plain") public String getInformation() { // return information via a String } }To make the enterprise bean a singleton using annotations, use the EJB 3.1 @javax.ejb.Singleton annotation instead of the @javax.ejb.Stateless annotation.
- Add JAX-RS annotations to the methods to expose as a RESTful interface to the enterprise bean. The following example demonstrates adding JAX-RS annotations to the @javax.ejb.Stateless enterprise bean.
package com.example.jaxrs; @javax.ejb.Stateless @javax.ws.rs.Path("/organization/") public class Organization { @javax.ws.rs.GET @javax.ws.rs.Produces("text/plain") public String getInformation() { // return information via a String } }- (optional) Add @javax.annotation.Resource annotated Java EE resource fields and properties to the JAX-RS EJB classes to access resources in the application. The Java EE injections do not work in plain Java classes with JAX-RS annotations. Injecting @javax.annotation.Resource annotated Java EE resource fields and properties to the JAX-RS EJB classes only works if the JAX-RS annotated classes are either an enterprise bean or a Java Context and Dependency Injection (JCDI) (JSR-299) managed bean; for example:
@javax.ejb.Stateless @javax.ws.rs.Path("/organization/") public class Organization { @javax.annotation.Resource(name="jdcb/TestDataSource") private javax.sql.DataSource datasource; @javax.ws.rs.GET @javax.ws.rs.Produces("text/plain") public String getInformation() { // read from the datasource // return information via a String } }In this example, if a data source is properly configured with the correct JNDI name, a DataSource object is injected into the resource class.- (optional) Use JAX-RS @javax.ws.rs.core.Context injection to obtain access to information about the request. You can add a @javax.ws.rs.core.Context UriInfo field to the JAX-RS EJB class to access information about the request URI; for example:
@javax.ejb.Stateless @javax.ws.rs.Path("/organization/") public class Organization { @javax.ws.rs.core.Context private UriInfo uriInfo; @javax.ws.rs.GET @javax.ws.rs.Produces("text/plain") public String getInformation() { // return information via a String } }To read parameters from the request such as @javax.ws.rs.HeaderParam, @javax.ws.rs.QueryParam, and @javax.ws.rs.PathParam, add a parameter to your resource method; for example:
@javax.ejb.Stateless @javax.ws.rs.Path("/organization/") public class Organization { @javax.ws.rs.GET @javax.ws.rs.Produces("text/plain") public String getInformation(@javax.ws.rs.QueryParam("page") String page) { /* The QueryParam in the method parameter list will be set correctly. */ // Return information using a String } /* The following field will not be set. */ @javax.ws.rs.QueryParam("q") private String willNotWork; @javax.ws.rs.QueryParam("q") public void setMyQueryParam(String q) { /* This property will not be set. */ } }JAX-RS field and property parameter injection, such as @javax.ws.rs.QueryParam, is not supported.
- Add the EJB class to the WEB-INF/classes directory of our WAR file or to a JAR located in your WEB-INF/lib directory. When a client makes a request to a JAX-RS annotated enterprise bean, the JAX-RS runtime environment looks up and uses an EJB instance of the class to invoke the resource method.
We have enabled an existing enterprise bean with no-interface view so that JAX-RS resources are exposed for consumption.
Implement RESTful views of an EJB with local interfaces Implement RESTful views of EJB applications using JAX-RS Developing a session bean to have a No-Interface Local view Developing singleton session beans Web services specifications and APIs EJB application specifications and APIs