RESTEasy Spring Integration

Version 3

    This coalesces all the configuration needed to get your RESTEasy-annotated classes to work with Spring.  The short list of what you need to do:

     

    1. Set up your project dependencies
    2. Configure Spring in web.xml
    3. Make sure RESTEasy configuration in web.xml doesn't interfere with what you are doing
    4. Configure your Spring beans

     

    (The last two steps took me a while to figure out)

     

    Set up your project dependencies

     

    For maven users add:

     

    <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-spring</artifactId>
      <version>${resteasy-version}</version>
    </dependency>
    

    Full example pom here

     

    Configure Spring in web.xml

    This is more or less what the official docs say:

     

     

    <listener>
      <listener-class>
      org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
      </listener-class>
    </listener>
    <listener>
      <listener-class>
      org.jboss.resteasy.plugins.spring.SpringContextLoaderListener
      </listener-class>
    </listener>
    

    The order is important.  Full example web.xml here

     

    Make RESTEasy configuration not interfere

     

    It's crucial that you do not configure resteasy.scan or resteasy.resources.  This will result in strange behavior; sometimes the beans created by Spring will be used by RESTEasy and sometimes RESTEasy will create its own.  So, don't configure your RESTEasy-annotated classes via RESTEasy's context params (I would assume implementing javax.ws.rs.core.Application to expose your classes would also cause these weird problems)

     

    The example web.xml contains scant configuration, and just be warned.

     

    Configure your Spring beans

     

    I was unable to get any auto-wiring to work, so you will need to configure your RESTEasy-annotated classes in your spring configuration (which, for web-apps, defaults to applicationContext.xml)

     

     

    <?xml version="1.0" encoding="utf-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:p="http://www.springframework.org/schema/p"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
      <import resource="other-spring-stuff.xml" />
    
      <bean id="servicePoint"
        class="com.example.ServicePoint">
        <property name="service"><ref bean="service" /></property>
      </bean>
    </beans>
     
    

     

    Note here, I'm injecting the bean service (which I've defined elsewhere); whatever beans you want, inject them here as normal (again, I wasn't able to get auto-wiring to work [but I'm not a fan of it anyway]).

     

    My class looks like so:

     

     

    package com.example;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    import com.example.Service;
    
    /**
     * Service Point endpoint.
     *
     * @author dave.copeland
     */
    @Path("/service_point")
    public class ServicePoint {
    
        private Service service;
        @GET
        @Path(value="/{meter_id}/daily_reads")
        @Produces("text/csv")
        public String getDailyReads(@PathParam("meter_id") String meterId){
            if (this.service == null) {
                throw new IllegalStateException("service didn't get injected");
            }
            List<Long> reads = this.service.getReads(meterId);
            StringBuilder b = new StringBuilder("date,val\n");
            for (Long read: reads) {
                b.append(String.valueOf(read));
                b.append("\n");
            }
            return b.toString();
        }
    
        
        public void setService(Service service) {
            this.service = service;
        }
    }
     
    

    Other Caveats

     

    If you cannot get RESTEasy to recognize your Spring beans as REST resources, you need to add the following lines to your Spring configuration files.  This is not mentioned in the documentation and it took this contributor (benw) over a day to figure this out.

     

       <context:annotation-config/>
       <context:component-scan base-package="com.example"/>