Управление версиями REST API и тип контента конкретного поставщика

Я много читал о версиях API REST, например в этой теме:Лучшие практики для управления версиями API?

Из-за этого я хотел бы использовать HTTP-Accept-Header, чтобы указать, какую версию запрашивает клиент. Но как я могу применить это в моем приложении? Какие изменения были сделаны? Как маршаллер узнает, какую версию следует использовать? Должен ли я зарегистрировать свой тип?

Что я знаю, так это то, что я должен изменить содержание@Produces-Annotation

@GET
@Path("/locations")
@Produces("application/vnd.mycompany-v1+xml")
Location[] getLocations();

Но что еще нужно изменить?

Ответы на вопрос(2)

вы не можете использовать JAX-RS для автоматической маршрутизации к различным методам на основе заголовка http.

Вы можете прочитать заголовок внутри вашего метода (с помощью @HeaderParam или HttpHeaders на @context смотритеВот) и назовите соответствующую версию

 joshi73724 окт. 2012 г., 08:42
Спасибо за ваш ответ. На самом деле я не хочу использовать версию для направления запроса к различным методам. Я просто хочу использовать версию для создания объектов местоположения в указанной версии. Может быть, расположение v2 имеет один атрибут больше, чем v1 ... вот и все
 Arnon Rotem-Gal-Oz24 окт. 2012 г., 11:36
Тогда вы можете использовать то, что я упомянул выше, чтобы выяснить, какую версию вам нужно вернуть
Решение Вопроса

Вы можете использоватьVariant механизмы JAX-RS.

@GET
@Path("/locations/{id}")
@Produces(value = {"application/vnd.mycompany-v2+json", // current version
                   "application/vnd.mycompany-v1+json", // old version
                   MediaType.APPLICATION_JSON})         // fallback
public Response getLocation(@PathParam("id") Integer id,
                            @Context Request request) {
    MediaType vndTypeV1 = new MediaType("application", "vnd.mycompany-v1+json");
    MediaType vndTypeV2 = new MediaType("application", "vnd.mycompany-v2+json");
    Variant variant1 = new Variant(vndTypeV1, null, null);
    Variant variant2 = new Variant(vndTypeV2, null, null);
    Variant variantJson = new Variant(MediaType.APPLICATION_JSON_TYPE, null, null);
    List<Variant> variants = new ArrayList<Variant>();
    variants.add(variant1);
    variants.add(variant2);
    variants.add(variantJson);

    Variant selectedVariant = request.selectVariant(variants);

    Location location = someBackendService.getLocation(id);

    // Manipulate location according to which variant is the selectedVariant.
    // ...

    return Response.ok("{}")
        .header(HttpHeaders.CONTENT_TYPE, selectedVariant.getMediaType())
        .build();
}

УвидетьУчебник по Java EE 6, слишком.

редактировать

Не существует автоматического способа упорядочить сущность в соответствии с выбранным вариантом. Это требует ручной работы. Например:

String version = extractVersionFromVariant(selectedVariant);
if ("v1".equals(version)) {
    location.setSomeV1Propery("only in v1);
} else if ("v2".equals(version)) {
    location.setSomeV2Propery("only in v2);
}
return Response.ok(location)
               .header(HttpHeaders.CONTENT_TYPE, selectVariant.getMediaType())
               .build();

Если версии достаточно разные, я бы использовал аннотированный класс JAXB для каждой версии. Каждый такой класс будет содержать только те свойства, которые действительны для этой версии. JAX-RS заботится о том, чтобы направить их в JSON.

 user64777225 окт. 2012 г., 13:23
Смотрите мое редактирование для некоторых идей.
 user64777225 окт. 2012 г., 17:58
Просто создайте экземпляр правильногоLocation класс вif и вернуть его вok(), ЕслиLocation класс имеет соответствующие аннотации JAXB, JAX-RS должен маршалировать его в JSON.
 joshi73725 окт. 2012 г., 16:38
Еще раз спасибо Последние два предложения вашего ответа звучат интересно и на самом деле это то, чего я хотел бы достичь. Если у меня есть следующая служба REST и клиент запрашивает версию v2:@GET @Path("/locations") @Produces({"application/vnd.mycompany-v1+xml", "application/vnd.mycompany-v2+xml"}) Location[] getLocations(); кроме того, я получил два объекта в разных пакетах, таких какentities.v1.Location а такжеentities.v2.Location, Как я могу сказать маршаллеру с Аннотациями JAXB использовать Objektentities.v2.Location потому что клиент просил об этом ??
 joshi73725 окт. 2012 г., 11:47
Спасибо за ваш ответ. Но как мне справиться с такими вещами:@POST @Path("/locations") @Consumes({"application/vnd.mycompany-v2+json","application/vnd.mycompany-v1+json"}) void createLocation(Location location); Как маршаллер использует правильную Object-Version, например, я получил Location-Object для v1 и еще один для v2?

Ваш ответ на вопрос