How to expose an EJB 3.1 as a REST Web Service?

2019-03-19 04:22发布

问题:

I discovered a new feature in java restful when using EJB 3.1 while reading an article at Adam Bien's blog.

The thing is that Stateless and Singleton beans can be exposed as root resources. But how? I tried to do it this way:

@Stateless
@LocalBean
@Path("Hybrid")
public class RESTEJBSample {

    @GET
    @Path("/demo")
    @Produces(MediaType.TEXT_PLAIN)
    public String something() {
        return "I am a Hybrid!!!";
    }

}

When i call the URL http://localhost:8080/HybridSample/resources/Hybrid/demo i get a 404 error.

Appart of this and just to make sure that JAXRS is is working in my project, i created a simple pojo resource just to test if it works fine.

@Path("/genericresource")
public class GenericResource {
    @GET
    @Path("/samplemethod")
    @Produces(MediaType.TEXT_PLAIN)
    public String saySomething() {
        return "Something!";
    }
}

Here when i call the URL http://localhost:8080/HybridSample/resources/genericresource/samplemethod It works fine!

So my questions are:

  • what is missing in my EJB so it can work as a web service resource such as the class GenericResource is doing?

  • Is there some extra configuration needed?

  • What are the limitations when using EJB as a web service?

回答1:

According to this NetBeans tutorial about Jersey RESTFul web services, you can decide whether to

create a subclass of javax.ws.rs.core.Application, all Rest resources will be registered by this class automatically (Java EE 6)

or

create default Jersey REST servlet adaptor in web.xml.

I have always used the second choice, which consists in adding this to your web.xml:

<servlet>
    <servlet-name>ServletAdaptor</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>ServletAdaptor</servlet-name>
    <url-pattern>/resources/*</url-pattern>
</servlet-mapping>

Exposing your REST Web service as an EJB is, to my experience, extremely useful. You can inject it wherever you like, you can inject in it your EntityManager, and you can even use it as a DAO in some simple situations.

Concerning your question / comment about features and limitations: enterprise beans run in the EJB container, whether they are deployed in a war file or not. You can inject into them a JMS ConnectionFactory as a resource as explained in this section of the Java EE 6 Tutorial. Thanks to the injection of a ConnectionFactory, you can send JMS messages. If you want to receive JMS messages asynchronously, you need to define a Message-Driven Bean as explained in this section of the above mentioned tutorial. I have never tried to extend the same EJB used for a Jersey web-service in order to implement the MessageListener interface, but I think that should be possible as well (if not, you can inject a MDB into your Jersey root Stateless bean).

Finally, you can use Container-Managed transactions as explained here. Moreover, from this NetBeans tutorial:

In order to have you can see that the application will use the Java Transaction API (JTA) (transaction-type="JTA"). This specifies that the responsibility for managing the lifecycle of entities in the persistence context is assigned to the container.

<persistence-unit name="em" transaction-type="JTA">