You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wink.apache.org by Jason Dillon <ja...@planet57.com> on 2010/04/26 06:51:20 UTC

Re: Any recommended way to handle versions of an applications REST API?

Thanks for the comments, this helps, though the choice between how I choose to indicate the version is really more of a minor issue.  What I'm still trying to understand is how I would wire up resources/servlets/applications to handle clients which use different versions of the protocol (the URI's + data model for the resources).

I suppose that if the model was versioned into packages and was compatible to be loaded into the same classloader, then I could implement it as a webapp, with a set of resources for the current version of the protocol, and adapting resources for the legacy versions to convert old model into new model and then delegate to the current version's resources.

If the model was not compatible in this fashion I think the only option is a webapp for each version of the model, probably still doing that decode/delegate/encode to the current versions resources (in a peer-webapp), or directly to an application facade if that is possible.

I'm still trying to grok how all that would work... but basically I'm trying to avoid having to come up with the perfect REST api in the first version (which ain't gonna happen... I'm too anal and picky)... and to avoid having to grandfather api turds for years and years.

I think I understand how to use path information to handle routing requests to versions of a resource (where the client would have to include the requested api version in the resource uri), but I'm not sure how I would use a header param to do that.

So, client with v1, resource goes to /v1/resource (v1.ResourceImpl), client with v2 goes to /v2/resource (v2.ResourceImpl).  If there was just /resource how could I use a header param to switch between v1.* and v2.* resources?

Has anyone else tried (failed or not) to solve this problem of versioning... ie. something I can peep at?

Thanks,

--jason


On Apr 24, 2010, at 10:43 PM, Mike Rheinheimer wrote:

> Hi Jason,
> 
> This is one of this things that could be solved ten different ways.
> For example, you could add a path parameter so that the version is
> recorded in the URI (http://example.com/version1/myresource).  You
> could do it in a query param
> (http://example.com/myresource?version=1).  You could do it in a
> matrix param, or a header param.
> 
> For params:  http://incubator.apache.org/wink/1.0/html/JAX-RS%20Parameters.html
> 
> I think the major consideration is the decision of whether the end
> user needs to know what version they're targetting or not.  If your
> end user is a web browser, and the end user needs to know whether they
> are using version 1 vs. version 2, then probably the path param, query
> param, or matrix param is the best choice.  If the end user is a
> client program where the versioning is transparent to the end user,
> then perhaps the header param is the best choice for managing it.  In
> the latter case, the decision of which version to use is being done at
> the application level, rather than the user level.  You could more
> easily switch which version is the default in your resource if the
> decision is based on a header param that is not recorded in the URL,
> but rather in a header; client apps would need no adjustment, and you
> would not have to inform your humen end-users of the new version.
> 
> That's probably the criteria I would personally use; if the end-user
> needs to see the version, then use path, query, or matrix params.  If
> the end user does *not* need to see the version or the end user is a
> client application that can automatically target the version it
> requires, I'd probably use the header param.
> 
> It's a good question, and one that, as with many REST practices, ends
> up having an answer of "whatever is appropriate for your particular
> needs".  :)
> 
> For header params:
> http://incubator.apache.org/wink/1.0/html/JAX-RS%20HTTP%20Headers.html
> 
> mike
> 
> 
> On Sat, Apr 24, 2010 at 8:18 PM, Jason Dillon <ja...@planet57.com> wrote:
>> Just curious if there is any recommended way to handle versioning of an apps REST... either from jaxrs or from winkers.
>> 
>> --jason


Re: Any recommended way to handle versions of an applications REST API?

Posted by Mike Rheinheimer <ro...@ohmyhead.com>.
Ok, I see what you're getting at.  It's not so much a question of how
to represent the version to the client, it's how to manage the
versions and upgrades, etc, on the server.  You'd either have to carry
the various versions within the same server app, or try to separate
the versions into distinct apps, somehow resolving requests (whether
through header param or path param, as you've indicated) to the
appropriate version.

Regarding server-side version management, you may have described a
good case for subresource locators.  Take a look at the section toward
the bottom of the page titled "Using Subresource Locators (@Path on
Java method)" (http://incubator.apache.org/wink/1.0/html/JAX-RS%20Resources,%20HTTP%20Methods,%20and%20Paths.html).

That specific example uses PathParam to dictate the pattern, but it
could just as easily use HeaderParam.  In that example, the
subresource locator method has a "@Path("{userid}")" annotation on it,
and the {userid} is the search criteria for which subresource to
return.  To use a header param instead of the path param as the search
criteria, the method in your subresource locator might look like this:

   @Path("/somepath")
   public Object findUserInfo(@HeaderParam("userid") String userId) {
       if(userId.equals("superuser")) {
           return new SuperUser();
       }
       return User.findUserInDatabase(userId);
   }


If we switch our thinking to versioning, maybe you could have a
subresource locator method in your top level resource class.  I'm not
officially endorsing this methodology, but wanted to lay out the idea:

@Path("/home")
public class MyTopLevelResource {

   @Path("/sub")
   public Object getVersionedSubResource(@HeaderParam("version")
String version) {
       if (version.equals("2")) {
           return SubResourceVersion2.class.newInstance();
       }
       // default to version 1
       return SubResourceVersion1.class.newInstance();
   }

This is, of course, not the best code.  To improve this I might use a
SubResourceFactory that takes the version as a parameter.  In that
SubResourceFactory.createSubResource(String version) method, you could
do a search for the class that handles the version requested, but
return a default JAX-RS annotated class when the specified version
class cannot be found.  In this design, you could keep all your
version 1 resources in a resourcesV1.jar and your version 2 resources
in a resourcesV2.jar, and so on, in your .ear.

I'm not aware of anyone who has an official recommendation regarding
how best to manage versioning in REST.  My searching came up with as
many different opinions as there are people who have them.  :)

Anyone else have some ideas?

Thanks..
mike



On Sun, Apr 25, 2010 at 11:51 PM, Jason Dillon <ja...@planet57.com> wrote:
> Thanks for the comments, this helps, though the choice between how I choose to indicate the version is really more of a minor issue.  What I'm still trying to understand is how I would wire up resources/servlets/applications to handle clients which use different versions of the protocol (the URI's + data model for the resources).
>
> I suppose that if the model was versioned into packages and was compatible to be loaded into the same classloader, then I could implement it as a webapp, with a set of resources for the current version of the protocol, and adapting resources for the legacy versions to convert old model into new model and then delegate to the current version's resources.
>
> If the model was not compatible in this fashion I think the only option is a webapp for each version of the model, probably still doing that decode/delegate/encode to the current versions resources (in a peer-webapp), or directly to an application facade if that is possible.
>
> I'm still trying to grok how all that would work... but basically I'm trying to avoid having to come up with the perfect REST api in the first version (which ain't gonna happen... I'm too anal and picky)... and to avoid having to grandfather api turds for years and years.
>
> I think I understand how to use path information to handle routing requests to versions of a resource (where the client would have to include the requested api version in the resource uri), but I'm not sure how I would use a header param to do that.
>
> So, client with v1, resource goes to /v1/resource (v1.ResourceImpl), client with v2 goes to /v2/resource (v2.ResourceImpl).  If there was just /resource how could I use a header param to switch between v1.* and v2.* resources?
>
> Has anyone else tried (failed or not) to solve this problem of versioning... ie. something I can peep at?
>
> Thanks,
>
> --jason
>
>
> On Apr 24, 2010, at 10:43 PM, Mike Rheinheimer wrote:
>
>> Hi Jason,
>>
>> This is one of this things that could be solved ten different ways.
>> For example, you could add a path parameter so that the version is
>> recorded in the URI (http://example.com/version1/myresource).  You
>> could do it in a query param
>> (http://example.com/myresource?version=1).  You could do it in a
>> matrix param, or a header param.
>>
>> For params:  http://incubator.apache.org/wink/1.0/html/JAX-RS%20Parameters.html
>>
>> I think the major consideration is the decision of whether the end
>> user needs to know what version they're targetting or not.  If your
>> end user is a web browser, and the end user needs to know whether they
>> are using version 1 vs. version 2, then probably the path param, query
>> param, or matrix param is the best choice.  If the end user is a
>> client program where the versioning is transparent to the end user,
>> then perhaps the header param is the best choice for managing it.  In
>> the latter case, the decision of which version to use is being done at
>> the application level, rather than the user level.  You could more
>> easily switch which version is the default in your resource if the
>> decision is based on a header param that is not recorded in the URL,
>> but rather in a header; client apps would need no adjustment, and you
>> would not have to inform your humen end-users of the new version.
>>
>> That's probably the criteria I would personally use; if the end-user
>> needs to see the version, then use path, query, or matrix params.  If
>> the end user does *not* need to see the version or the end user is a
>> client application that can automatically target the version it
>> requires, I'd probably use the header param.
>>
>> It's a good question, and one that, as with many REST practices, ends
>> up having an answer of "whatever is appropriate for your particular
>> needs".  :)
>>
>> For header params:
>> http://incubator.apache.org/wink/1.0/html/JAX-RS%20HTTP%20Headers.html
>>
>> mike
>>
>>
>> On Sat, Apr 24, 2010 at 8:18 PM, Jason Dillon <ja...@planet57.com> wrote:
>>> Just curious if there is any recommended way to handle versioning of an apps REST... either from jaxrs or from winkers.
>>>
>>> --jason
>
>