Milan has posted 4 posts at DZone. View Full User Profile

How to Combine REST Services with EJB 3.1

12.01.2009
| 62388 views |
  • submit to reddit

REST services (JAX-RS) technology became a part of the Java EE 6 platform, which is great news for REST developers.

In a very simple web application, I'll demonstrate how REST services can be combined with other Java EE technologies, specifically EJB 3.1.

  1. First of all, we need to specify a REST resources path. Previously, in Java EE 5, the only way to do this was to register a specific servlet adaptor in 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>

    JAX-RS API (from version 1.1.4) introduced  a specific annotation ( @javax.ws.rs.ApplicationPath ), that provides an alternative to web.xml configuration:

     package org.netbeans.rest.application.config;
    /**
    * This class is generated by the Netbeans IDE,
    * and registers all REST root resources created in the project.
    * Please, DO NOT EDIT this class !
    */
    @javax.ws.rs.ApplicationPath("resources")
    public class ApplicationConfig extends javax.ws.rs.core.Application {
    }

    Note: The ApplicationConfig class extends javax.ws.rs.core.Application. There are 2 methods that may be implemented from the super class:

         public Set<Class<?>> getClasses();
    public Set<Object> getSingletons();

    These methods specify a set of root resources and providers accessible from this application path. This way users may specify several groups of REST resources (not necessarily disjunctive), in a single web application. 

    NetBeans IDE 6.8 provides a default implementation of javax.ws.rs.core.Application containing all REST root resources and providers specified in a web application. Users can specify a URL string (e.g. "resources") that will be used to access these resources. Users can also implement a custom subclass(es) of javax.ws.rs.core.Application.

  2. Secondly, we create a Singleton EJB class that will be used to persist the state of REST resource (created in next stem). This is the class:
    package name;

    import javax.annotation.PostConstruct;
    import javax.ejb.Singleton;

    @Singleton
    public class NameBean {   
        private String name;
    |
    @PostConstruct
    private void init() {
    name="Robin Hood";
    }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    Note: The singleton EJB is a new feature in Java EE 6. The container is guaranteed to maintain a single shared instance of an EJB 3.1 Singleton. This means that Singletons can cache state across the application tier. The @PostContruct annotation is used to annotate a method performing any initialization stuff, and it's called by container just after a single instance is created.

  3. The last step is to create a simple REST root resource, using the singleton NameBean to persist its state:
    package name;

    import javax.ejb.*;
    import javax.ws.rs.*;

    @Path("name")
    @Stateless
    public class NameService {
        @EJB
        private NameBean nameBean;

        @GET
        @Produces("text/html")
        public String getHtml() {
            return "<h2>Hello "+nameBean.getName()+"</h2>";
        }

        @PUT
        @Consumes("text/plain")
        public void put(String content) {
            nameBean.setName(content);
        }

    }

    Note: Dependency Injection is used to inject the NameBean into the resource. The EJB 3.0 @Stateless annotation is a convenient way to enable dependency injection. If this annotation is missing, the nameBean field won't be initialized by the container. The other annotations come from the JAX-RS (JSR311) specification.

NetBeans IDE provides a RESTful, JavaScript based, tester capability that can be used to test HTTP GET, POST, PUT or DELETE methods. This is an example of invoking HTTP PUT on REST resource located at "http://localhost:8080/RestApplication/resources/name":

Netbeans REST Tester

Finally, the HTTP GET method can also be tested easily by typing resource URI in the browser:

HTP GET test

Published at DZone with permission of its author, Milan Kuchtiak.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Reza Rahman replied on Tue, 2009/12/01 - 11:33am

Milan,

Great coverage of EJB 3.1 and JAX-RS!

Cheers,

Reza

Chetan Shinde replied on Wed, 2009/12/02 - 5:46am

Hello Milan,

 

That was a good introduction to REST Web Service and NetBeans.

Could you also  tell how you can implement the Client for this example?

Is there some specific API that we need to use?

 

Regards,

Chetan

Rafael Naufal replied on Wed, 2009/12/02 - 10:51am

Good introduction to combine REST services with EJB! BTW, I think is the @EJB annotation which enables bean dependency injection by the container instead of the @Stateless annotation.

Milan Kuchtiak replied on Wed, 2009/12/02 - 12:20pm in response to: Chetan Shinde

> Is there some specific API that we need to use?

In java code, you can use Jersey Client API.

See: Consuming REST

Milan Kuchtiak replied on Wed, 2009/12/02 - 12:28pm in response to: Rafael Naufal

> I think is the @EJB annotation which enables bean dependency injection by the container instead of the @Stateless annotation.

Sorry, I didn't express that properly. @EJB annotation, of course, provides an injection, but the class should be manageable by the container (e.g. EJB). If the class annotation @Stateless were missing it wouldn't work.

Stephan Kliche replied on Wed, 2010/02/10 - 11:48am

Hey Guys,

I really like the article because right now I am trying to get my rest service working and I prefer the @EJB annotation over the initial context blah. Anyways if I am annotating my class with @Sateless and if I use an @EJB annotation, my annotated variable is still null... I tried this out with jboss and with JOnAS... Any Ideas?

 

@Path("/user")
@Stateless
public class UserService {
    private static Logger log = Logger.getLogger(UserService.class.getName());

    @EJB(beanInterface=UserFacadeLocal.class, mappedName="myPlace/UserFacade/local") private UserFacadeLocal bean;

    @GET
    @Produces("text/xml")
    public ServiceResult getUser() {           
        ServiceResult result = new ServiceResult();

        bean.getUser(3); //fails
       
        return result;
    }
}

 

Ido Ran replied on Tue, 2010/02/23 - 2:50am

Thank you very much for the post about rest Application class. When I start a new web (or enterprise) application that has REST NetBeans pop a question how to handle the rest part and give 3 choices: generated Application class, manual Application class or plain old servlet. My question is how to change it once I've decide to go with the generated Application let's say to servlet? Thank you, Ido.

Milan Kuchtiak replied on Thu, 2010/06/10 - 7:42am in response to: Ido Ran

Sorry for replying so late.

It's available using:

RESTful Web Services node -> REST Resources Configuration

Daniil Kasyanov replied on Tue, 2011/06/14 - 2:06am

Hi, If I try to integrate JavaBean as local bean (no interfaces it works) but if I try Integrate it with interfaces I got deployment error that bean couldn't be resolved. I use eclipse to build application. @Remote public interface CalculatorEngineRemote {...} @Local public interface CalculatorEngineLocal {...} @Stateless @Remote (CalculatorEngineRemote.class) @Local (CalculatorEngineLocal.class) @LocalBean public class CalculatorEngine implements CalculatorEngineRemote, CalculatorEngineLocal {...} @Stateless @Path("calculator") // Dependency injection is used to inject the CalculatorEngine into the resource. // The EJB 3.0 @Stateless annotation is a convenient way to enable dependency injection. // If this annotation is missing, the nameBean field calculatorEngine field won't be initialized by the container. public class Calculator { @SuppressWarnings("unused") @Context private UriInfo context; @EJB private CalculatorEngine calculatorEngine; .... }

Daniil Kasyanov replied on Tue, 2011/06/14 - 2:08am in response to: Daniil Kasyanov

Sorry, the text is edited awful...

Andries Schutte replied on Fri, 2011/08/05 - 12:25pm

Hi,

 

thanks for the useful example. Just one note: If the @Stateless EJB implements an interface, the container throws an exception (in the case of Glassfish) or doesn't inject any dependencies (in the case of JBoss). If the @Stateless EJB doesn't implement an interface, it works fine on both containers. 

 Cheers,

Andries. 

 

Andries Schutte replied on Fri, 2011/08/05 - 12:46pm in response to: Andries Schutte

 

..or, if one wants to keep the interface implementation, one could annotate the @Stateless EJB with @LocalBean. That also works on both containers I tried.

Rajesh Viswanad... replied on Wed, 2012/03/07 - 1:37am in response to: Reza Rahman

Hi Milan,

 

Thanks for the article !!

I have few queries regarding EJb to ResT.

I have created an EJB 3.0 application and converted it to ReST service. I'm able to invoke methods on this ReST service using the url some thing like this: http://localhost:9080/EJB2TOReSTWeb/rest/customers

Now I'm trying to invoke the methods on my EJB by getting the EJB object through JNDI lookup.

but when I do initialConetext.lookup("jndiName");

I'm getting NameNotFoundException on client side. I have checked for this jndi name on my server, but i dont see any ejb registered with that name.

My Question here is : If we convert an EJB either 2.1 or 3.0 into ReST service, can we still do the lookup of that EJB the way we do it in normal way using initialContext.lookUp();

I'm using JBoss 4.2.3 server, i tried on WAS6.1 also.

 

Any help would be really appreciated.

 

Thanks,

Rajesh V

 

 

 

 

 

 

Matt Coleman replied on Wed, 2012/03/21 - 12:45pm

Milan,what a great program..this is awesome! web designer buffalo

 

 

Mateo Gomez replied on Thu, 2012/08/16 - 1:12am

what a great combination i must say

mexican dessert recipes

Morkel Abie replied on Thu, 2013/05/02 - 5:09am

I am hoping the same best work from you in the future as well. In fact your creative writing abilities has inspired me to start my own blog now. san antonio dj

Reeti Rajput replied on Fri, 2013/05/03 - 6:00am in response to: Morkel Abie

www.travelviews.co  Before you search the information in the internet, you need to think what your need for the holiday is. Do you want budget holiday? Or do you want holiday with high standard of accommodation? Per the information provided, you can then select and use the camping holiday smartly.

Danish12 Ali replied on Fri, 2013/07/26 - 3:35pm

  guess I am not the only one having all the leisure here! Keep up the good work. I have been meaning to write something like this on my website and you have given me an idea.  no flame e cig

Cata Nic replied on Mon, 2013/09/02 - 4:55pm

 The integration is not very easy to perform for a noob but the results are spectacular. I expect a new integration, with the next generation of EJB.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.