Jeff has posted 11 posts at DZone. View Full User Profile

Spring Framework Support in REST 0.7

05.20.2008
| 29045 views |
  • submit to reddit
REST 0.7 (i.e., Jersey, the reference implementation for RESTful web services) is out and now includes support for the Spring framework. Here is a step-by-step scenario based on a nice example written by my Sun colleague Peter Liu. Peter's sample uses NetBeans IDE 6.1 to create a web application that contains a Spring-aware servlet, a singleton resource, and a request resource. His example is derived from a blog post by Paul Sandoz showing how to manually integrate Spring and Jersey (and predating REST 0.7).

Note: In REST 0.8, Spring support will be enhanced so that the user does not have to create a Spring-aware servlet.

This is the example. It requires the NetBeans IDE Web and Java EE distribution 6.1 and REST plugin 0.7.

  1. Create a Web Application project and name it SpringRestWebApp. On the Frameworks page of the project creation wizard, select Spring Web MVC 2.5.

    Adding Spring framework in New Project wizard

  2. Right-click the SpringRestWebApp node and choose New > RESTful Web Services from Patterns. Select the Singleton pattern and name the resource Singleton (class name will then be SingletonResource). Create the test.servlet package to contain the resource.

    RESTful service from patterns wizard, showing resource and package names

  3. Replace the code in SingletonResource with the following.

    @Path("singleton")
    @Singleton
    public class SingletonResource {

    private String name;

    private int uses = 0;

    private synchronized int getCount() {
    return ++uses;
    }

    public SingletonResource() {
    name = "unset";
    }

    public String getName() {
    return name;
    }

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

    @GET
    @ProduceMime("text/plain")
    public String getDescription() {
    return "Name: " + getName() + ", Uses: " + Integer.toString(getCount());
    }
    }

  4. Right-click in the code and select Fix Imports. If the imports cannot be fixed, check that the Swing and Jersey libraries are in the project.

    Context menu inside code showing Fix Imports option

  5. Create another RESTful Web Service using the Singleton pattern. Name the resource PerRequest and create it in the same test.servlet package.

  6. Replace the code in PerRequestResource with the following. Right-click in the code and select Fix Imports when you are done.

    @Path("request")
    public class PerRequestResource {

    private String name;

    private int uses = 0;

    private synchronized int getCount() {
    return ++uses;
    }

    public PerRequestResource() {
    name = "unset";
    }

    public String getName() {
    return name;
    }

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

    @GET
    @ProduceMime("text/plain")
    public String getDescription() {
    return "Name: " + getName() + ", Uses: " + Integer.toString(getCount());
    }
    }

  7. Right-click the SpringRestWebApp node and choose New > Servlet. Name the servlet SpringServlet and create it in the test.servlet package. You have now added all resources to the project, which should have the following structure:

    Complete test.servlet package structure

  8. Replace the code in SpringServlet with the following. Right-click in the code and select Fix Imports when done.

    public class SpringServlet extends ServletContainer {

    private static class SpringComponentProvider implements ComponentProvider {
    private ApplicationContext springContext;

    SpringComponentProvider(ApplicationContext springContext) {
    this.springContext = springContext;
    }

    private String getBeanName(Class c) {
    String names[] = springContext.getBeanNamesForType(c);
    if (names.length == 0) {
    return null;
    } else if (names.length > 1) {
    throw new RuntimeException("Multiple configured beans for "
    + c.getName());
    }
    return names[0];
    }

    public Object getInstance(Scope scope, Class c)
    throws InstantiationException, IllegalAccessException {
    String beanName = getBeanName(c);
    if (beanName == null) return null;

    if (scope == Scope.WebApplication &&
    springContext.isSingleton(beanName)) {
    return springContext.getBean(beanName, c);
    } else if (scope == Scope.ApplicationDefined &&
    springContext.isPrototype(beanName) &&
    !springContext.isSingleton(beanName)) {
    return springContext.getBean(beanName, c);
    } else {
    return null;
    }
    }

    public Object getInstance(Scope scope, Constructor contructor,
    Object[] parameters)
    throws InstantiationException, IllegalArgumentException,
    IllegalAccessException, InvocationTargetException {
    return null;
    }

    public Object getInjectableInstance(Object instance) {
    return instance;
    }

    public void inject(Object instance) {
    }
    };

    @Override
    protected void initiate(ResourceConfig rc, WebApplication wa) {
    ApplicationContext springContext = WebApplicationContextUtils.
    getRequiredWebApplicationContext(getServletContext());

    wa.initiate(rc, new SpringComponentProvider(springContext));
    }
    }

    Paul Sandoz writes "Notice that SpringServlet extends ServletContainer and the initiate method is overridden. This method creates an ApplicationContext and then initiates the WebApplication by passing in an instance of the static inner class SpringComponentProvider. This class implements ComponentProvider and the getInstance method will attempt to obtain a Spring bean that is present and matches the requested scope, if so then the bean instance is returned otherwise null is returned. (Note that the getInstance method with a Constructor type parameter is not implemented, this is because we have not determined how to support constructors with Spring beans)."


  9. Expand the project's Web Pages > WEB-INF node. Open the project's web.xml file. Replace com.sun.ws.rest.impl.container.servlet.ServletAdaptor with test.servlet.SpringServlet.

  10. Add the following to the project's applicationContext.xml file, to initialize the resources:
    <bean id="bean1" scope="singleton" class="test.servlet.SingletonResource">
    <property name="name" value="Mr. Singleton Bean"/>
    </bean>
    <bean id="bean2" scope="prototype" class="test.servlet.PerRequestResource">
    <property name="name" value="Mr. PerRequest Bean"/>
    </bean>

  11. Right-click the project node and select Test RESTful Web Services. The IDE deploys the project and launches the RESTful service tester in a browser window.

    RESTful service tester in browser window, showing test of SingletonResource
When you test the Singleton path, the service returns the Mr. Singleton Bean property and the Uses value increments for every request. When you test the PerRequest path, the service returns the Mr. PerRequest Bean property and the Uses value does not increment.
AttachmentSize
add-spring-framework.png22.46 KB
project-full-package.png11.71 KB
project-new-package.png10.92 KB
singleton-resource-class.png23.84 KB
singleton-resource-fix-imports.png8.8 KB
test-singleton.png49.15 KB
Published at DZone with permission of its author, Jeff Rubinoff.

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

Comments

Danilo Gurovich replied on Sat, 2008/07/19 - 8:26pm

Rest .8 is released.  having trouble with the SpringServlet class' inner, as the scope variables are throwing errors in the netbeans ide.

You mentioned "Note: In REST 0.8, Spring support will be enhanced so that the user does not have to create a Spring-aware servlet"

 Not to be obtuse, but I just igore the servlet entirely? 

 Thoughts?

John Brown replied on Wed, 2013/07/24 - 1:26am

 Just download the latest version today, very great framework.

Oud oil

Desmond Tan replied on Wed, 2013/09/11 - 10:34pm

Entertainment for your loved ones and friends is therefore at your fingertips with the full condo facilities as well as the amenities near Flora Drive Condo. Flora Drive Condo

Sudirman Felippe replied on Thu, 2013/09/26 - 9:48pm

New Investment Ideas

With so many uncertainties in Europe. How can a person decide on what property to buy to invest??Will it be another case of Property meltdown just like in USA??For Investors , please consider Asia, developing economies. it is the rising star now.We are marketing this new property in Kuala Lumpur, capital of MalaysiaIts economy is booming and growth is very high last yearTRIBECA, Kuala Lumpur is a new serviced suites, which functions like a hotel. Where tenants are given the option of laundry, concierge, maintenance, housekeeping all in one.for more details visit my website.http://www.malaysian-properties.com/tribeca-kuala-lumpur

Comment viewing options

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