2012-10-23 13 views
6

Ho letto molto sulla versione delle API REST, ad es. in questa discussione: Best practices for API versioning?API REST versioning e tipo di contenuto specifico del fornitore

Per questo vorrei utilizzare l'intestazione HTTP-Accept per indicare quale versione richiede il client. Ma come posso applicare questo nella mia applicazione? Quali modifiche sono state quindi apportate? Come sa il marshaller, quale versione dovrebbe essere usata? Devo registrare il mio tipo?

Quello che so è che devo cambiare il contenuto del @Produces -Annotation

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

Ma che altro deve essere cambiato?

risposta

2

È possibile utilizzare i Variant meccanismi di 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(); 
} 

Vedere anche lo Java EE 6 Tutorial.

Modifica

Non c'è modo automatico per schierare un'entità secondo la variante selezionata. Ciò richiede un po 'di lavoro manuale. Ad esempio:

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(); 

Se le versioni sono abbastanza diverse, utilizzerei una classe annotata JAXB per ogni versione. Ciascuna classe includerebbe quindi solo quelle proprietà valide per questa versione. JAX-RS si occupa di portarli in JSON.

+1

Grazie per la tua risposta. Ma come gestisco tali cose: '@POST @Path ("/locations ") @Consumi ({" application/vnd.mycompany-v2 + json "," application/vnd.mycompany-v1 + json "}) void createLocation (Location location); 'Come fa il marshaller ad usare la corretta Object-Version, ad esempio ho ottenuto un Location-Object per v1 e un altro per v2? – joshi737

+0

Vedere la mia modifica per alcune idee. –

+1

Grazie ancora. Le ultime due frasi della tua risposta sembrano interessanti e sono in realtà il punto che mi piacerebbe raggiungere. Se ho il seguente servizio REST e il client chiede v2: '@GET @Path ("/locations ") @Produces ({" application/vnd.mycompany-v1 + xml "," application/vnd. mycompany-v2 + xml "}) Location [] getLocations();' inoltre ho ottenuto due Objekts in pacchetti diversi come 'entities.v1.Location' e' entities.v2.Location'. Come posso dire al marshaller con le annotazioni JAXB di usare Objekt 'entities.v2.Location' perché il cliente lo ha richiesto ?? – joshi737

1

Per quanto ne so non è possibile utilizzare JAX-RS per l'instradamento automatico a diversi metodi basati su un'intestazione http.

È possibile leggere l'intestazione dentro di voi il metodo (con @HeaderParam o HttpHeaders sulla @context vedi here) e chiamare il appropriata versione

+1

Grazie per la risposta. In realtà non voglio usare la versione per indirizzare la richiesta a metodi diversi. Voglio solo utilizzare la versione per produrre oggetti di posizione nella versione specificata. Forse la posizione di v2 ha un attributo più di v1 ... questo è – joshi737

+0

Quindi puoi usare quello che ho detto sopra per capire quale versione devi restituire –