Dois-je utiliser le type Date dans JAX-RS @PathParam?

9

C'est ce que je pense faire sur un serveur JEE Glassfish en utilisant Jersey.

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

J'aime l'idée de pouvoir dire aux gens qui consomment ce service Web RESTful que "La date ici est tout ce qui fonctionne avec la classe Date en Java". C'est assez simple du point de vue qu'ils peuvent simplement regarder la spécification Date, et ils auront déjà un modèle de travail avec lequel ils pourront tester.

Le problème qui m'inquiète est que lorsque je fais cela, JAX-RS n'est pas très agréable lorsque Date () n'aime pas ce qu'il obtient dans le constructeur. Puisque Date () renvoie une erreur s'il ne peut pas analyser ce qui lui est donné (comme si vous lui passez la chaîne "aujourd'hui" au lieu d'une date réelle), le serveur JEE renvoie une erreur 404.

Est-ce une bonne pratique? Y a-t-il une meilleure façon de faire cela à laquelle je ne pense pas?

Jazzepi
la source

Réponses:

8

Cela ressemble à une mauvaise idée. D'une part, le constructeur Date sur lequel vous vous fondez est obsolète depuis Java 1.1 en faveur de DateFormat.parseDate (), précisément parce qu'il n'est pas clair comment les chaînes doivent être analysées en dates, car les règles sont différentes pour différentes localités.

Ma recommandation serait de s'en tenir à un format spécifique, de préférence le aaaa-MM-jj internationalement compris, et d'utiliser un format de date pour analyser la date à partir d'une chaîne à l'intérieur de votre service, ce qui indique clairement comment consommer le service Web et vous permet de suivre la convention standard pour le renvoi de messages d'erreur pour vos services Web en cas de problème.

Theodore Murdock
la source
11

J'utilise une classe personnalisée DateParam:

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

La classe est définie comme:

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 le paramètre est vide, vous obtiendrez une date nulle. Vous pouvez étendre DateParamun champ final statique public pour les valeurs de date non définies. Cela rendrait le test des paramètres de date non définis plus clair.

Un inconvénient ici est que pour chaque DateParam, une nouvelle instance de SimpleDateFormat est créée. Cependant, puisque SimpleDateFormat n'est pas thread-safe, nous ne pouvons pas le réutiliser facilement.

migu
la source
3
1+. Java 8 a introduit un thread sécurisé DateTimeFormatter. Pour Java <= 7, j'utiliserais unThreadLocal
Anthony Accioly
3

Qui utilisera votre service? Prendront-ils la peine de rechercher les spécifications de la Dateclasse et de déterminer le type de chaînes qu'elle analysera? Je ne le ferais pas, même si j'étais programmeur Java, je saurais où chercher ;-)

Je pense que vous devez d'abord dire à vos utilisateurs à quoi ressembleront vos URI, par exemple

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

puis cherchez un moyen pour que Jersey vous aide à analyser le format de date que vous avez choisi. Cela pourrait signifier utiliser un Datetype de paramètre et peut-être spécifier une expression régulière dans votre @Pathannotation, comme

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

ou en utilisant une autre classe capable d'analyser une date dans votre format. Comment gérer les URI qui ne correspondent pas aux spécifications que vous donnez à vos utilisateurs est une autre chose que vous devez décider comment gérer indépendamment de tout ce qui précède (renvoyer une ressource par défaut? Renvoyer une erreur 404?).

agnul
la source