¿Debo usar el tipo Fecha en JAX-RS @PathParam?

9

Esto es lo que estoy pensando hacer en un servidor JEE Glassfish usando Jersey.

@GET
@Path("/{name}/{date}")
public String getMessages(@PathParam("name") String name, @PathParam("date") Date date)

Me gusta la idea de poder decirle a las personas que consumen este servicio web RESTful que "La fecha aquí es cualquier cosa que funcione con la clase Date en Java". Eso es bastante simple desde el punto de vista de que solo pueden mirar la especificación de Fecha, y ya tendrán un modelo de trabajo con el que pueden probar.

El problema que me preocupa es que cuando hago esto, JAX-RS no es muy agradable cuando a Date () no le gusta lo que obtiene en el constructor. Dado que Date () arroja un error si no puede analizar lo que se proporciona (como si le pasa la cadena "hoy" en lugar de una fecha real), el servidor JEE devuelve un error 404.

¿Es esta una buena practica? ¿Hay una mejor manera de hacer esto que no estoy pensando?

Jazzepi
fuente

Respuestas:

8

Suena como una mala idea. Por un lado, el constructor de fecha en el que confiaría ha quedado en desuso desde Java 1.1 a favor de DateFormat.parseDate (), precisamente porque no está claro cómo las cadenas deben analizarse en fechas, ya que las reglas son diferentes para diferentes localidades.

Mi recomendación sería seguir con un formato específico, preferiblemente aaaa-MM-dd, entendido internacionalmente, y usar un DateFormat para analizar la fecha desde una cadena dentro de su servicio, lo que deja en claro cómo consumir el servicio web y le permite seguir cualquiera que sea la convención estándar para devolver mensajes de error para sus servicios web cuando algo sale mal.

Theodore Murdock
fuente
11

Estoy usando una clase personalizada DateParam:

@GET
@Path("/{name}/{date}")
public String getMessages(@PathParam("name") String name, @PathParam("date") DateParam date)
  Date date = date.getDate();

La clase se define como:

public class DateParam {
  private final Date date;

  public DateParam(String dateStr) throws WebApplicationException {
    if (isEmpty(dateStr)) {
      this.date = null;
      return;
    }
    final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    try {
      this.date = dateFormat.parse(dateStr);
    } catch (ParseException e) {
      throw new WebApplicationException(Response.status(Status.BAD_REQUEST)
        .entity("Couldn't parse date string: " + e.getMessage())
        .build());
    }
  }

  public Date getDate() {
    return date;
  }
}

Si el parámetro está vacío, obtendría una fecha nula. Puede ampliar DateParammediante un campo final público estático para valores de fecha indefinidos. Esto haría que las pruebas de parámetros de fechas indefinidas sean más claras.

Un inconveniente aquí es que para cada DateParam, se crea una nueva instancia de SimpleDateFormat. Sin embargo, dado que SimpleDateFormat no es seguro para subprocesos, no podemos reutilizarlo fácilmente.

migu
fuente
3
1+. Java 8 introdujo un hilo seguro DateTimeFormatter. Para Java <= 7, usaría unThreadLocal
Anthony Accioly
3

¿Quién usará su servicio? ¿Se molestarán en buscar la especificación de la Dateclase y averiguar qué tipo de cadenas analizará? No lo haría, incluso si fuera un programador de Java sabría dónde buscar ;-)

Creo que primero debe decirles a sus usuarios cómo se verán sus URI, p. Ej.

.../your-resource-name/yyyy-MM-dd

y luego busque la manera de que Jersey lo ayude a analizar el formato de fecha que elija. Eso podría significar usar un Datetipo de parámetro y tal vez especificar una expresión regular en su @Pathanotación, como

@Path(/{name}/{date: [0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]/)

o usando alguna otra clase capaz de analizar una fecha en su formato. Cómo manejar los URI que no coinciden con las especificaciones que le da a sus usuarios es otra cosa que debe decidir cómo manejar independientemente de cualquiera de los anteriores (¿devolver un recurso predeterminado? ¿Devolver un error 404?).

agnul
fuente