jax - restful java
La mejor forma de manejar el control de versiones de URI de API REST de JAX-RS (3)
El problema al colocarlo en la URL es que se supone que la URL representa un recurso por ubicación. Una versión API no es una ubicación y no forma parte del identificador del recurso.
Sticking /v2/
en la URL rompe todos los enlaces existentes que vinieron antes.
Hay una forma correcta de especificar el control de versiones de la API:
Ponlo en el tipo mime para el encabezado Accept:
que quieras. Algo así como Accept: application/myapp.2.0.1+json
El patrón Chain of Responsiblity va bien aquí especialmente si habrá una cantidad significativa de versiones de API que sean lo suficientemente diferentes como para tener su propio controlador, de esa manera los métodos no se salgan de control.
Primero hice mi búsqueda en stackoverflow y no pude encontrar ninguna respuesta relacionada con mi pregunta. Todo lo que puedo encontrar es preguntas relacionadas con el diseño REST uri.
Mi pregunta en el lado de back-end. Supongamos que tenemos dos versiones diferentes de REST uri
http://api.abc.com/rest/v1/products
http://api.abc.com/rest/v2/products
¿Cuál es el mejor enfoque a seguir en el lado de back-end (código del lado del servidor) para un enrutamiento, administración y reutilización adecuados de las clases existentes en estos dos juegos de API basados en la versión?
He pensado en el enfoque para definir clases de recursos con diferentes anotaciones @Path para, por ejemplo, tener un paquete para v1 y v2 por separado y en la clase ProductsResource de ese paquete, definir
package com.abc.api.rest.v1.products;
@Path("/rest/v1/products")
public class ProductsResource {...}
package com.abc.api.rest.v2.products;
@Path("/rest/v2/products")
public class ProductsResource {...}
y luego tiene la lógica de implementación basada en las versiones. Los problemas con este enfoque son cuando solo estamos cambiando una api de recursos particular del conjunto de api, también tenemos que copiar otras clases al paquete v2. ¿Podemos evitarlo?
¿Qué tal escribir una anotación personalizada, por ejemplo @Version y tener valores de las versiones que admite? Ahora bien, ya sea v1 o v2, ambas solicitudes irán a la misma clase de recursos.
Digamos por ejemplo
package com.abc.api.rest.products;
@Path("/rest/{version: [0-9]+}/products")
@Version(1,2)
public class ProductsResource {...}
ACTUALIZAR:
Hubo una sugerencia de control de versiones API por Jarrod para manejar la versión en los encabezados. Sin embargo, también es una forma de hacerlo, estoy a la espera de las mejores prácticas para usar cuando estamos siguiendo el control de versiones basado en URI
Esta entrada de blog tiene un ejemplo de lo que algunos consideran el enfoque correcto, es decir, no tener la versión en el URI: http://codebias.blogspot.ca/2014/03/versioning-rest-apis-with-custom-accept.html
En resumen, aprovecha la anotación JAX-RS @Consume
para asociar la solicitud de una versión particular a una implementación específica, como:
@Consumes({"application/vnd.blog.v1+xml", "application/vnd.blog.v1+json"})
Me preguntaba por qué no tener una subclase de ProductService llamada
@Path(/v2/ProductService)
ProductServiceV2 extends ProductService {
}
@Path(/v1/ProductService)
class ProductService{
}
y solo anula lo que se modificó en v2. Todo sin cambios funcionará igual que en v1 / ProductService.
Esto definitivamente lleva a más # de clases, pero es una forma más fácil de codificar solo lo que está cambiando en la nueva versión de la API y volver a la versión anterior sin duplicar el código.