Solución Taller 2: Básico Rest
|
El código de esta solución está en la rama solucionTaller |
Para obtenerla desde Neatbeans vaya a: |
Team > Checkout > Checkout Revision y seleccione la rama solucionTaller |
Punto 1.
Agregue un atributo al recurso City, por ejemplo pais
de tipo String
. Modifique el código para las ciudades tengan ese atributo. Verifique con Postman su modificación:
a. Cuando utilice POST en el json que envía adicione el atributo nuevo. Revise que el Json que devuelve lo contenga.
b. Cuando invoque el servicio GET /cities
verifique que las ciudades tienen el atributo.
Solución Punto 1.
|
Modificación |
CityDTO |
1. Declare el nuevo atributo: |
|
private String pais; |
|
2. Defina los métodos setPais y getPais |
CityEntity |
3. Declare el nuevo atributo: |
|
private String pais; |
|
4. Defina los métodos setPais y getPais |
CityDTO |
5. Conversión Entity a DTO : Modifique el constructor public CityDTO(CityEntity city) para incluir el nuevo atributo |
|
6. ConversiÛn DTO a Entity : Modifique el método public CityEntity toEntity() para incluir el nuevo atributo |
Solución Punto 2. GET /cities/id
Para invocar el servicio construya la petición:
GET urlservidor/api/cities/1
donde urlservidor
en nuestros ejemplos corresponde: localhost:8080/cities-web
el número 1 debe corresponder al id
de una ciudad que existe. Si no existe debe enviar el mensaje de que la ciudad con el id
dado no existe.
Desarrolle los siguientes servicios:
Servicio |
Resumen |
Parámetros |
Retorno |
Código HTTP |
GET /cities/id |
Obtiene los atributos de una instancia de City (READ) que tiene identificado id |
@PathParam id: Identificador del recurso Json con la representación del recurso City correspondiente con el id dado |
404 Si no existe una ciudad con ese id |
Clase |
Modificación |
CityPersistence |
1. Agregue el método public CityEntity find(Long id) |
|
Invoque con el EntityManager (em) declarado en la clase el método: |
|
find(Class<T> entityClass, Object primaryKey) Ver documentación aquí |
CityLogic |
2. Defina el método public CityEntity getCity(Long id) . |
|
Este método debe invocar el método de la persistencia que creó en el paso anterior. |
CityResource |
3. Defina el método: |
@GET
@Path("{id: \\d+}")
public CityDetailDTO getCity(@PathParam("id") Long id)
|
|
CityResource |
La anotación @GET que es la que corresponde con el servicio que estamos definiendo |
|
@Path("{id: \d+}") indica que la url contiene una cadena de varios dígitos. La expresión \\d+ lo indica. |
|
En la signatura del método hay que declarar que lo que viene en la url (en el path: @PathParam("id") ) es lo que recibiremos en el parámetro Long id |
|
4. Importe la clase: import javax.ws.rs.Path; |
|
5. En la implementación primero debemos verificar que exista una ciudad con el id que se utilizó en el path. Para esto se debe llamar al método de la lógica que creamos en el punto 2 getCity . Si el método devuelve null quiere decir que el recurso no existe. Disparamos WebApplicationException así: |
CityEntity entity = cityLogic.getCity(id);
if (entity == null) {
throw new WebApplicationException("El recurso city: " + id + " no existe.", 404);
}
|
|
CityResource |
|
6. Note que el método getCity devuelve un CityEntity y lo que necesitamos devolver aquí es un CityDetailDTO . Para realizar la conversión, utilice el constructor de la clase CityDetailDTO que recibe un CityEntity |
Solución Punto 2. PUT /cities/:id
Servicio |
Resumen |
Parámetros |
Retorno |
Código HTTP |
PUT /cities/:id |
Actualiza una instancia de la entidad City (UPDATE) |
@PathParam id: Identificador del recurso |
Objeto JSON de City Instancia de City actualizada |
404 Si no existe una ciudad con ese id |
Reglas de Negocio
Cuando se actualiza la información de la ciudad se debe verificar que el nombre no exista ya en la base de datos. Si ya existe, se debe disparar una BusinessLogicException
Si el recurso no existe se debe disparar una excepción WebApplicationException
indicando que la ciudad no existe.
Clase |
Modificación |
CityPersistence |
1. Defina el método de la persistencia para actualizar una entidad. Utilizando el EntityManager de JPA (en nuestro código la variable em invocamos el método merge quien se encarga de actualizar, en la base de datos, los valores de la entidad que recibe de argumento. |
public CityEntity update(CityEntity entity) {
return em.merge(entity);
}
Clase |
Modificación |
CityLogic |
2. Defina en la lógica el método public CityEntity update(CityEntity entity) quien debe invocar el método de la persistencia definido en el paso anterior. |
CityResource |
3. Defina el método para actualizar una ciudad dado su id con la siguiente signatura: |
@PUT
@Path("{id: \\d+}")
public CityDetailDTO updateCity(@PathParam("id") Long id, CityDetailDTO city)
throws BusinessLogicException { }
|
|
CityResource |
La anotación @PUT corresponde con el servicio que estamos definiendo. Debe importar el paquete: import javax.ws.rs.PUT; |
|
@Path("{id: \\d+}") indica que la url contiene una cadena de varios dígitos. La expresión \\d+ lo indica. Este id corresponde al identificador de la ciudad que queremos actualizar. |
|
En la signatura del método declaramos dos parámetros: 1. lo que viene en la url (en el path: @PathParam("id") ) es lo que recibiremos en el parámetro Long id . 2. El DTO,que llamamos city , que trae los valores nuevos de la ciudad que queremos actualizar. |
|
4. Para la implementación del método lo primero que hacemos es forzar a que el id de la url sea el mismo del dto: city.setId(id); |
|
5. Verificamos que exista una ciudad con el id dado. Si no existe disparamos la excepción WebApplicationException . Hay que importar el paquete import javax.ws.rs.WebApplicationException |
CityEntity entity = cityLogic.getCity(id);
if (entity == null) {
throw new WebApplicationException("El recurso /city/" + id + " no existe.", 404);
}
|
|
CityResource |
6. Ahora debemos invocar el método de actualización que definimos en la lógica. Este método recibe un entity como argumento (public CityEntity update(CityEntity entity) ) pero lo que tenemos en un CityDetailDTO . El método para convertir un CityEntity a un CityDetailDTO está definido en el DTO y se llama toEntity . El llamado es entonces: cityLogic.updateCity(id, city.toEntity()) . |
|
7. El método de la lógica retorna un entity pero el método del recurso debe retornar un DTO. Entonces el llamado completo es: return new CityDetailDTO(cityLogic.updateCity(id, city.toEntity())); |
Nota: En este ejercicio falta verificar la primera regla de negocio.
Solución Punto 2. DELETE /cities/:id
Servicio |
Resumen |
Parámetros |
Retorno |
Código HTTP |
DELETE /cities/:id |
Borra instancia de City en el servidor (DELETE) |
@PathParam id: Identificador del recurso |
|
404 Si no existe una ciudad con ese id |
Clase |
Modificación |
CityPersistence |
1. Defina el método de la persistencia para borrar una entidad. |
|
JPA ofrece el método void remove(Object entity) Remove the entity instance. . El objeto debe estar en el contexto de persistencia de la aplicación. Podemor definir en la clase de persistencia de nuestra aplicación el método que recibe la entidad que se va a borrar: |
public void delete(CityEntity entity) {
LOGGER.log(Level.INFO, "Borrando ciudad con id={0}", entity.getId());
em.remove(entity);
}
Clase |
Modificación |
CityLogic |
2. En la lógica invocamos el método de la persistencia que definimos en el paso 1. Si tuvieramos que verificar que la entidad no se puede borrar porque se necesita por estar asociada con otras entidades, es aquí en esta capa donde haríamos la verificación. EN este ejemplo simple solo hacemos el llamado a la persitencia. |
CityResource |
3. Defina el método para borrar una ciudad dado su id con la siguiente signatura: |
@DELETE
@Path("{id: \\d+}")
public void deleteCity(@PathParam("id") Long id) { ...}
|
|
CityResource |
5. Verificamos que exista una ciudad con el id dado. Si no existe disparamos la excepción WebApplicationException . Hay que importar el paquete import javax.ws.rs.WebApplicationException |
CityEntity entity = cityLogic.getCity(id);
if (entity == null) {
throw new WebApplicationException("El recurso /city/" + id + " no existe.", 404);
}
|
|
CityResource |
6. Ahora debemos invocar el método para borrar la entidad que acabamos de recuperar de la base de datos:cityLogic.deleteCity(entity); |