Conceptos Generales

Ciclo de vida de una petición

El proceso para crear estos registros está conformado por los siguientes pasos:

  1. El controlador llama al servicio.
  2. Realizar la petición desde el frontend con el componente $http de AngularJS.
  3. JAX-RS recibe la petición en un String con formato JSON, JAX-B deserializa el JSON y lo convierte en un DTO.
  4. En el servicio, el DTO se transforma en un Entity usando la clase. Converter.
  5. Se invoca el método de la lógica pasando la entidad como parámetro.
  6. Llama a la persistencia pasando la entidad como parámetro.
  7. La lógica devuelve la entidad que recibió de la persistencia.
  8. El servicio recibe de la lógica la entidad creada, la convierte en DTO y la retorna.
  9. JAX-B serializa el DTO para convertirlo en un String con formato JSON.
  10. $http recibe la respuesta y resuelve el promise.

Anotación @StatusCreated

De acuerdo a la especificación de los códigos de estado de HTTP, se debe retornar 201 cuando se cree un nuevo recurso en el servidor. Esta situación se presenta especialmente cuando se crean instancias de entidades. Por ejemplo, cuando creamos un nuevo book y JPA le asigna el ID 1, un nuevo recurso es creado en la URI /books/1. Por esta razón, las funciones que crean instancias de entidades deben retornar el código 201.

Para evitar la repetición de este código en todos los métodos que crean instancias, se decidió crear un provider de JAX-RS que permita cambiarlo a través de una anotación. Este provider se llama CreatedFilter y tiene una característica especial: Aplica únicamente a los métodos anotados con @StatusCreated.

La anotación @StatusCreated permite que los provider anotados con ella solo sean ejecutados cuando el servicio que atiende la solicitud también esté anotado con la misma. De esta manera se restringue los servicios cuya respuesta es alterada.

@POST
@StatusCreated
public BookDTO createBook(BookDTO dto) {
    // Implementación
}

DateAdapter para JAX-B

JAX-B no tiene implementado un método para serializar y deserializar fechas (específicamente java.util.Date). Por esta razón, es necesario implementar un adapter que le indique cómo hacer esta tarea.

Para esto debemos crear una clase que herede de XmlAdapter<String, Date> y sobreescribir los métodos marshall y unmarshall, los cuales se encargar de serializar y deserializar respectivamente. Dentro de cada uno de estos métodos debemos incluir la lógica para realizar la conversión entre los dos tipos.

En el siguiente ejemplo se usa ThreadLocal ya que SimpleDateFormat no es thread-safe. La clase DateAdapter se crea en el paquete co.edu.uniandes.csw.bookstore.adapters:

package co.edu.uniandes.csw.bookstore.adapters;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class DateAdapter extends XmlAdapter<String, Date> {

    /**
     * Thread safe {@link DateFormat}.
     */
    private static final ThreadLocal<DateFormat> DATE_FORMAT_TL = new ThreadLocal<DateFormat>() {

        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };

    @Override
    public Date unmarshal(String v) throws Exception {
        return DATE_FORMAT_TL.get().parse(v);
    }

    @Override
    public String marshal(Date v) throws Exception {
        if (v == null) {
            return null;
        }
        return DATE_FORMAT_TL.get().format(v);
    }
}

Después de esto, debemos indicar a JAX-B que debe usar dicho adaptador para poder manejar fechas con la anotación @XmlJavaTypeAdapter. Existe dos maneras de usar esta anotación:

  • En cada atributo en el que se desee aplicar el adapter
  • En el paquete que contiene los DTO, con lo cual se aplica a todos los atributos de POJO que estén anotados con @XmlJavaTypeAdapter y java.util.Date.

En nuestro caso, aplicaremos la anotación en el paquete. Para esto, se debe crear un Archivo de información de paquete:

  1. Hacer clic derecho en el paquete co.edu.uniandes.csw.bookstore.dtos
  2. Seleccionar New > Other...
  3. En la categoría Java seleccionar el tipo Java Package Info
  4. Seleccionar Next y luego Finish
  5. Finalmente, añadir la anotación @XmlJavaTypeAdapter con value = DateAdapter.class y type = Date.class
@XmlJavaTypeAdapter(value = DateAdapter.class, type = Date.class)
package co.edu.uniandes.csw.bookstore.dtos;

import co.edu.uniandes.csw.bookstore.adapters.DateAdapter;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

results matching ""

    No results matching ""