users@jersey.java.net

Re: [Jersey] Resource and XML Schema versioning...

From: Kevin Duffey <andjarnic_at_yahoo.com>
Date: Tue, 24 Feb 2009 09:25:30 -0800 (PST)

Is there any option for you to do as Craig had suggested in one of his ways to handle this..that is, to support older APIs via separate deployments and have a front-end routing solution that can read the custom header (or pluck the URI version value out of the incoming request) and route to the appropriate server farm? This is the same thing I would have suggested.. that is, using either a custom http header or a URI with a version value as you originally suggested, but route the requests to version specific servers so that as you evolve, you'r newer code doesn't have to deal with backwards compatibility. One thing that comes to mind is perhaps to tag/branch your SCM before the next evolutionary change, then proceed as normal. If any bug fixes are required for older versions, work off of the branches and merge (if needed) to the trunk/head/latest. This may require separate build/deploy process for each set of servers designated for specific versions. The
 other method Craig mentioned may work if you can't deploy new versions to separate servers.. that is to use the custom http header (or again, as you suggested a version value in the URI that you then pluck on every request) and from that you can handle the request based on the version being requested. If no version value is provided, assume the latest is required. I personally like his approach with the custom http header over using a version string as part of the URI. It seems cleaner that you can provide the same URI to access your services as you evolve. Naturally you're going to provide an API and possibly SDK for your services, so anyone using your services should be able to read about the custom http header and make use of it. We do that now and it works great! ________________________________ From: "Rabick, Mark A (MS)" <Mark.Rabick_at_ngc.com> To: users_at_jersey.dev.java.net Sent: Tuesday, February 24, 2009 7:08:52 AM Subject: [Jersey] Resource and XML Schema versioning... Resource and XML Schema versioning... Paul/Craig, Thanks for the great suggestions: >Once you have the media types it is possible if you wish to support >URI-based content negotiation if the client cannot send an accept >header. >JAX-RS has support for resolving JAXBContext for media type and Java >type. See the ContextResolver [1]. >Thus you could do: > @Provider > @Produces("application/foo-v1") > public class Verson1ContextResolver implements ContextResolver<JAXBContext> { > public JAXBContext getContext(java.lang.Class<?> type) { > ... > } > } >I am not sure of the exact details of supporting two different >serializations from the same object. IMHO it seems, without >understanding too much about your use-case, easier to keep new and old >versions separate (different packages). That way you do not have to >work out backwards dependencies, plus think about the case when you >require 3 versions etc. As far as the URI-based content negotiation, are you suggesting I could couple the URI 'versioning' (../v1/…) in addition to custom/specific media types when the client can't send an "Accept: application/foo-vi? Second, the generated application.wadl just indicates on methods that return application/xml: <response> <representation mediaType="application/xml"/> </response> How can I get the JAXB context to genarate an XSD for each schema (v1,v2) and get the wadl to include corresponding XSD in the generated response element in the wadl? >I am not sure of the exact details of supporting two different >serializations from the same object. IMHO it seems, without >understanding too much about your use-case, easier to keep new and old >versions separate (different packages). Unfortunately, I don't have specific use-case scenarios yet, just a requirement to preserve backward compatibility for legacy service clients… even though we don't have any 'legacy' clients yet (no actual clients yet), so I'm trying to at least architect my service framework to better support that in the future. The short of if is that I have 1 set of persistence objects (entity beans) at any given time in the most recent version. If I embed JAXB (javax.xml.bind) annotations in those persistence objects, lets just focus on 1 right now (Foo.java). If it has an attribute: @XmlElement(required=true) protected String fooName; (v1) <ns2:foo> … <fooName>Name</fooName> ... </ns2:foo> A simple case might be a change to: @XmlElement(required=true) protected String fooFullName; (v2) <ns2:foo> … <fooFullName>Name</fooFullName> ... </ns2:foo> At deployment time, I only have the (v2) annotated Foo.java, but I need to support clients that could ask for v1 schema bound Foo objects. The XmlElement annotation processing would use the attribute's name as the xml element. That was my question about an external JAXB configuration? I need the Foo.java to talk to our hibernate JPA based DAOs and that is the object that I get returned from our JPA/DB calls. I would need to produce output in foo-v1.xsd AND foo-v2.xsd. Would you recommend a 'transfer object' pattern and based on URI and accept header negotiation, keep multiple versions of Foo for use by Jersey? That is, I would have to write a façade of sorts to map the incoming foo-v1.xsd requests to Foo.java and then back from Foo.java to foo-v2.xsd with annotated FooV1.java and FooV2.java classes that reflect the different 'versions' of Foo? Thanks again for all of your hard work and prompt responses! --mark _______________________________________________ Mark A. Rabick Software Engineer Em: mark.rabick_at_ngc.com