I’ve been using Apache CXF which has some nice support for building JSR-311 compliant JAX-RS Services and recently had a requirement for sending back a custom version header as part of our API Responses.
It is generally accepted that versioning APIs is a good thing and adopting the general contract of Major.Minor.Patch covers our needs, now we need to have a standard method of reporting and documenting the APIs and versions. Before we get into the ins and outs of how one you should version an API, we have a company wide recommendation of adding a custom response header to each response X-API-Version: d.d.d which I have to say I’m in favour of over embedding the version in the url and is also the method adopted by Sun’s Cloud API – which certainly was commonly held to be a benchmark implementation of REST.
Using Apache CXF Filters led to this fairly elegant and simple solution which could be applied to add any type of additional headers but I found the documentation a little confusing so decided to write a post on it.
Some background about applying response filters
Perhaps you want to do custom logging or additional processing but more interestingly the response handler implementation can optionally overwrite or modify the application Response or modify the output message the first of which we are particularly interested in.
By implementing The ResponseHandler Interface:
And overriding handleResponse:
1 2 3 4
Starting with a test
Starting off with the simplest scenario which for me is that the X-API-Version header should be present in the response. Normally I’d start with the assert statement and work backwards using my Eclipse shortcuts. I’ve skipped ahead a few steps here but hopefully you get the idea.
1 2 3 4 5 6 7
Diving into our HttpResponseVersionProvider
So remember we are just doing the simplest thing possible to make the test pass which in this case is to add the new header to the final response.
1 2 3 4
Preserving the original response object
We obviously want to preserve the original response object and message body on the outgoing response so I add a test for that now introducing some Mocks to mock out the original response object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Our final HttpResponseVersionProvider
fromResponse performs a shallow copy of the existing Response.
1 2 3 4
You can see the tidied up finished test class and implementation here:
Wiring it up
Plug in to your cxf jax-rs providers spring configuration along with any other providers using your maven project version number.
1 2 3 4 5 6 7 8 9 10 11