Nick's posterous http://nicktj.posterous.com Most recent posts at Nick's posterous posterous.com Wed, 18 May 2011 18:56:00 -0700 Versioning ActionWebService on Rails http://nicktj.posterous.com/versioning-actionwebservice-on-rails http://nicktj.posterous.com/versioning-actionwebservice-on-rails

I started a Rails project a few years ago that has grown up.  These days, there is a main consumer of a SOAP API provided through ActionWebService (with more on the way).  Most generally try and head down the RESTful path, but with server-to-server communication, it just made it easier to take a structured path.  (Custom XML/JSON output, yuck.)

Since the client system is actually the server for a desktop client, it became more necessary to independently update the two servers.  This did pose a bit of a problem with SOAP API bindings in .NET.  We wanted to establish a backwards compatible base API (to maintain the status quo) and also start working on a few API breaking updates.  This would normally be pretty easy in rails with namespaces but it unfortunately doesn't work out so well for ActionWebService.

ActionWebService actually supports a few different models of dispatching actions: direct, delegated, and layered.  Direct just maps a controller's actions to the entire described API.  Delegated enables exposing single methods as SOAP actions from another controller.  Lastly, layered is a lot like direct and delegated mixed; separate ports are created for each layered implementation, and everything is described in the same wsdl.

So...everything should be great, right? Well, it turned out that all of the session code broke.  Since the 'versioned' implementations were actually instantiated from the original controller, they're not provided the same environment as the top level. This little trick from the ruby-forum re-instated the functionality (with a minor edit):

class ServicesController < ApplicationController
    web_service_dispatching_mode :layered
    web_service(:v1) { ServicesV1Controller.new(self) }
  end

 

class ServicesV1Controller < ApplicationController
    def initialize(self)
      @controller = self
      @session = @controller.session
    end
  end

We're still working through some of the kinks in making the API fully backwards compatible, but this got us a long ways to supporting multiple API versions with SOAP.

 

Helpful post on API versioning: http://stackoverflow.com/questions/389169/best-practices-for-api-versioning

Permalink | Leave a comment  »

]]>
http://posterous.com/images/profile/missing-user-75.png http://posterous.com/users/heOPIhURBYqT0 Nick Jones nicktj Nick Jones