mob
mob

Reputation: 587

REST versioning in URL using jersey

I have a Jersey / Spring REST servlet. I am trying to use URL versioning mechanism to have 2 versions of the same resource. What is the best way to solve this ?

This is my web.xml I am trying to load up 2 jersey servlets

<servlet>
    <servlet-name>REST_V1</servlet-name>
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet
    </servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.comp.resource.v1</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>REST_V1</servlet-name>
    <url-pattern>/v1/*</url-pattern>
</servlet-mapping>

This is the V2 mapping

<servlet>
    <servlet-name>REST_V2</servlet-name>
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet
    </servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.comp.resource.v2</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>REST_V2</servlet-name>
    <url-pattern>/v2/*</url-pattern>
</servlet-mapping>

I have defined 2 spring components, with the same resource path in their respective packages

package com.comp.resource.v1;

@Controller
@Path("/user")
public class User_V1 {

}

For V2

package com.comp.resource.v2;

@Controller
@Path("/user")
public class User_V2 {

}

I am seeing a conflicting URI Template error for the resource /user Is there a better way to solve this ? Any help wold be appreciated

Upvotes: 1

Views: 800

Answers (1)

mob
mob

Reputation: 587

Seems like the issue is with how spring beans are loaded. In the web.xml if you have contextConfigLocation outside of the Jersey to load up all the beans, then both REST_V1 and REST_V2 servlet conflicts with the same resource name.

Here is what I changed in the application context. Removed scanning of resource package from global applicationContext.xml

<context:annotation-config />
<context:component-scan base-package="com.comp.*">
    <context:exclude-filter type="regex" expression="com.comp.resource.*"/>
</context:component-scan>

Added 2 more applicationContext, for each servlet

applicationContext_V1.xml

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

applicationContext_V2.xml

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

Added reference to these applicationContext file in jersey configuration in web.xml

<servlet>
    <servlet-name>REST_V1</servlet-name>
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet
    </servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.comp.resource.v1</param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext_V1.xml</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>REST_V1</servlet-name>
    <url-pattern>/v1/*</url-pattern>
</servlet-mapping>

and for REST_V2

<servlet>
    <servlet-name>REST_V2</servlet-name>
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet
    </servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.comp.resource.v2</param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext_V2.xml</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>REST_V2</servlet-name>
    <url-pattern>/v2/*</url-pattern>
</servlet-mapping>

Upvotes: 1

Related Questions