Discussion:
REST API Versioning
Robert DiFalco
2014-04-25 20:59:58 UTC
Permalink
Let's say that I choose to do URI versioning. I know many people are
against this approach but I don't want to spark a discussion on *which*
method I use for versioning. I want to ask HOW I would do it.

What I would like to do (ideally) is have a Container Request Filter that
will see if (for example) there is a V2 contained in the incoming the
request path. If there *is* the filter will look to see if there is a
resource with an exact match for this path. If there is *NOT* an exact
match it will modify the request URI to use the V1 version of the resource
method.

By doing this I do not need to create a "api/v2/whatever" version of every
resource path. I will only need to modify those that differ from version 1.
For example, if I have the @Path "api/user/info" but no @Path
"api/v2/user/info" then the filter will remap the "api/v2/user/info" to
"api/user/info".

Is there a way to do this? Is there a better approach to take for URI
versions with JAX-RS?

Thanks.
Van Klaveren, Brian N.
2014-04-25 21:11:41 UTC
Permalink
In the past, I have tackled this problem in several ways.

My preferred method is this:
Deploy your application to a unique path, and use an additional router or rewrite rules:

example.com/roberts-api-v1.0
example.com/roberts-api-v1.1
example.com/roberts-api-v2.0
example.com/roberts-api-v2.1-SNAPSHOT

use a router:
example.com/api/v1 -> example.com/roberts-api-v1.0
example.com/api/v1.1 -> example.com/roberts-api-v1.1
example.com/api/v2 -> example.com/roberts-api-v2
example.com/api/dev -> example.com/roberts-api-v2.0-SNAPSHOT

Then the rest of the application doesn’t ever have to know about it’s version number.

I did it with the router once, using:

<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.3</version>
</dependency>

You could also write your own filter to do something similar.

I think I had another version where I had added some HTTP headers which appended the original URL.

There’s probably better ways, but I was fine with this.

Brian
Let's say that I choose to do URI versioning. I know many people are against this approach but I don't want to spark a discussion on *which* method I use for versioning. I want to ask HOW I would do it.
What I would like to do (ideally) is have a Container Request Filter that will see if (for example) there is a V2 contained in the incoming the request path. If there *is* the filter will look to see if there is a resource with an exact match for this path. If there is *NOT* an exact match it will modify the request URI to use the V1 version of the resource method.
Is there a way to do this? Is there a better approach to take for URI versions with JAX-RS?
Thanks.
Robert DiFalco
2014-04-25 21:32:44 UTC
Permalink
That's a cool approach. If I understand you correctly you are saying to
keep my old version jars and just create new ones. Then have a router
handle the versioning. My only issues with that are (a) more expensive on
heroku (where I currently deploy) and (b) it would make hotfixes a little
more tedious. But a cool idea for sure.


On Fri, Apr 25, 2014 at 2:11 PM, Van Klaveren, Brian N. <
Post by Van Klaveren, Brian N.
In the past, I have tackled this problem in several ways.
example.com/roberts-api-v1.0
example.com/roberts-api-v1.1
example.com/roberts-api-v2.0
example.com/roberts-api-v2.1-SNAPSHOT
example.com/api/v1 -> example.com/roberts-api-v1.0
example.com/api/v1.1 -> example.com/roberts-api-v1.1
example.com/api/v2 -> example.com/roberts-api-v2
example.com/api/dev -> example.com/roberts-api-v2.0-SNAPSHOT
Then the rest of the application doesn’t ever have to know about it’s
version number.
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.3</version>
</dependency>
You could also write your own filter to do something similar.
I think I had another version where I had added some HTTP headers which
appended the original URL.
There’s probably better ways, but I was fine with this.
Brian
Post by Robert DiFalco
Let's say that I choose to do URI versioning. I know many people are
against this approach but I don't want to spark a discussion on *which*
method I use for versioning. I want to ask HOW I would do it.
Post by Robert DiFalco
What I would like to do (ideally) is have a Container Request Filter
that will see if (for example) there is a V2 contained in the incoming the
request path. If there *is* the filter will look to see if there is a
resource with an exact match for this path. If there is *NOT* an exact
match it will modify the request URI to use the V1 version of the resource
method.
Post by Robert DiFalco
By doing this I do not need to create a "api/v2/whatever" version of
every resource path. I will only need to modify those that differ from
"api/v2/user/info" then the filter will remap the "api/v2/user/info" to
"api/user/info".
Post by Robert DiFalco
Is there a way to do this? Is there a better approach to take for URI
versions with JAX-RS?
Post by Robert DiFalco
Thanks.
Van Klaveren, Brian N.
2014-04-25 21:42:56 UTC
Permalink
From a resource standpoint, it is more expensive (especially in memory starved environments).
From a development standpoint, I feel parallel deployments is the only thing that really makes sense with versioning, otherwise you end up with mixed classes, and at some point your code from v1 might was on jersey 2.4 where v2 might want to be on the new and shiny, and you end up with all sorts of classpath problems you’ll never be able to resolve.
Brian


On Apr 25, 2014, at 2:32 PM, Robert DiFalco <robert.difalco-***@public.gmane.org<mailto:robert.difalco-***@public.gmane.org>> wrote:

That's a cool approach. If I understand you correctly you are saying to keep my old version jars and just create new ones. Then have a router handle the versioning. My only issues with that are (a) more expensive on heroku (where I currently deploy) and (b) it would make hotfixes a little more tedious. But a cool idea for sure.


On Fri, Apr 25, 2014 at 2:11 PM, Van Klaveren, Brian N. <bvan-***@public.gmane.org.edu<mailto:bvan-***@public.gmane.org>> wrote:

In the past, I have tackled this problem in several ways.

My preferred method is this:
Deploy your application to a unique path, and use an additional router or rewrite rules:

example.com/roberts-api-v1.0<http://example.com/roberts-api-v1.0>
example.com/roberts-api-v1.1<http://example.com/roberts-api-v1.1>
example.com/roberts-api-v2.0<http://example.com/roberts-api-v2.0>
example.com/roberts-api-v2.1-SNAPSHOT<http://example.com/roberts-api-v2.1-SNAPSHOT>

use a router:
example.com/api/v1<http://example.com/api/v1> -> example.com/roberts-api-v1.0<http://example.com/roberts-api-v1.0>
example.com/api/v1.1<http://example.com/api/v1.1> -> example.com/roberts-api-v1.1<http://example.com/roberts-api-v1.1>
example.com/api/v2<http://example.com/api/v2> -> example.com/roberts-api-v2<http://example.com/roberts-api-v2>
example.com/api/dev<http://example.com/api/dev> -> example.com/roberts-api-v2.0-SNAPSHOT<http://example.com/roberts-api-v2.0-SNAPSHOT>

Then the rest of the application doesn’t ever have to know about it’s version number.

I did it with the router once, using:

<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.3</version>
</dependency>

You could also write your own filter to do something similar.

I think I had another version where I had added some HTTP headers which appended the original URL.

There’s probably better ways, but I was fine with this.

Brian
Let's say that I choose to do URI versioning. I know many people are against this approach but I don't want to spark a discussion on *which* method I use for versioning. I want to ask HOW I would do it.
What I would like to do (ideally) is have a Container Request Filter that will see if (for example) there is a V2 contained in the incoming the request path. If there *is* the filter will look to see if there is a resource with an exact match for this path. If there is *NOT* an exact match it will modify the request URI to use the V1 version of the resource method.
Is there a way to do this? Is there a better approach to take for URI versions with JAX-RS?
Thanks.
Paul O'Fallon
2014-04-25 22:26:29 UTC
Permalink
I've never tried it myself, but I was looking around and came across Model
Processors:

https://jersey.java.net/documentation/latest/resource-builder.html#d0e9698

I wonder if you couldn't loop through your resources at deployment time and
programmatically "fill in" the missing ones (i.e. identify and define the
missing /v2/ resources at deploy time, having them fulfilled by the same v1
methods). That way you wouldn't even need a filter...

Anyway, like I said, I've never used it, but it sounded intriguing...

- Paul


On Fri, Apr 25, 2014 at 5:42 PM, Van Klaveren, Brian N. <
From a resource standpoint, it is more expensive (especially in memory
starved environments).
From a development standpoint, I feel parallel deployments is the only
thing that really makes sense with versioning, otherwise you end up with
mixed classes, and at some point your code from v1 might was on jersey 2.4
where v2 might want to be on the new and shiny, and you end up with all
sorts of classpath problems you’ll never be able to resolve.
Brian
That's a cool approach. If I understand you correctly you are saying to
keep my old version jars and just create new ones. Then have a router
handle the versioning. My only issues with that are (a) more expensive on
heroku (where I currently deploy) and (b) it would make hotfixes a little
more tedious. But a cool idea for sure.
On Fri, Apr 25, 2014 at 2:11 PM, Van Klaveren, Brian N. <
Post by Van Klaveren, Brian N.
In the past, I have tackled this problem in several ways.
example.com/roberts-api-v1.0
example.com/roberts-api-v1.1
example.com/roberts-api-v2.0
example.com/roberts-api-v2.1-SNAPSHOT
example.com/api/v1 -> example.com/roberts-api-v1.0
example.com/api/v1.1 -> example.com/roberts-api-v1.1
example.com/api/v2 -> example.com/roberts-api-v2
example.com/api/dev -> example.com/roberts-api-v2.0-SNAPSHOT
Then the rest of the application doesn’t ever have to know about it’s
version number.
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.3</version>
</dependency>
You could also write your own filter to do something similar.
I think I had another version where I had added some HTTP headers which
appended the original URL.
There’s probably better ways, but I was fine with this.
Brian
Post by Robert DiFalco
Let's say that I choose to do URI versioning. I know many people are
against this approach but I don't want to spark a discussion on *which*
method I use for versioning. I want to ask HOW I would do it.
Post by Robert DiFalco
What I would like to do (ideally) is have a Container Request Filter
that will see if (for example) there is a V2 contained in the incoming the
request path. If there *is* the filter will look to see if there is a
resource with an exact match for this path. If there is *NOT* an exact
match it will modify the request URI to use the V1 version of the resource
method.
Post by Robert DiFalco
By doing this I do not need to create a "api/v2/whatever" version of
every resource path. I will only need to modify those that differ from
"api/v2/user/info" then the filter will remap the "api/v2/user/info" to
"api/user/info".
Post by Robert DiFalco
Is there a way to do this? Is there a better approach to take for URI
versions with JAX-RS?
Post by Robert DiFalco
Thanks.
Loading...