Devo usar o tipo Data no JAX-RS @PathParam?


9

É isso que estou pensando em fazer em um servidor JEE Glassfish usando Jersey.

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

Eu gosto da idéia de poder dizer às pessoas que consomem esse serviço web RESTful que "A data aqui é qualquer coisa que funcione com a classe Date em Java". Isso é bastante simples do ponto de vista de que eles podem apenas olhar para a especificação Date e já terão um modelo de trabalho com o qual podem testar.

O problema que me preocupa é que, quando faço isso, o JAX-RS não é muito bom quando Date () não gosta do que recebe no construtor. Como Date () gera um erro se não puder analisar o que foi fornecido (como se você passar a string "today" em vez de uma data real), o servidor JEE retornará um erro 404.

Esta é uma boa prática? Existe uma maneira melhor de fazer isso em que não estou pensando?

Respostas:


8

Parece uma má ideia. Por um lado, o construtor Date em que você confiava foi preterido desde o Java 1.1 em favor de DateFormat.parseDate (), precisamente porque não está claro como as strings devem ser analisadas em datas, pois as regras são diferentes para diferentes localidades.

Minha recomendação seria ficar com um formato específico, de preferência o internacionalmente conhecido aaaa-MM-dd, e usar um DateFormat para analisar a data de uma string dentro do seu serviço, o que deixa claro como consumir o serviço da Web e permite que você seguir qualquer convenção padrão para retornar mensagens de erro para seus serviços da Web quando algo der errado.


11

Estou usando uma classe personalizada DateParam:

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

A classe é definida 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;
  }
}

Se o parâmetro estiver vazio, você receberá uma data nula. Você pode estender DateParampor um campo final estático público para valores de data indefinidos. Isso tornaria os testes para parâmetros de datas indefinidos mais claros.

Uma desvantagem aqui é que, para cada DateParam, uma nova instância do SimpleDateFormat é criada. No entanto, como SimpleDateFormat não é seguro para threads, não podemos reutilizá-lo facilmente.


3
1+. O Java 8 introduziu um thread safe DateTimeFormatter. Para Java <= 7, eu usaria umThreadLocal
Anthony Accioly

3

Quem usará seu serviço? Será que eles se preocupam em procurar as especificações da Dateclasse e descobrir que tipo de strings serão analisadas? Eu não, mesmo sendo um programador Java, eu saberia onde procurar ;-)

Acho que você deve primeiro informar aos usuários como serão os seus URIs, por exemplo

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

e, em seguida, procure uma maneira de fazer com que Jersey o ajude a analisar o formato de data escolhido. Isso pode significar usar um Datetipo de parâmetro e talvez especificar uma expressão regular em sua @Pathanotação, como

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

ou usando alguma outra classe capaz de analisar uma data em seu formato. Como lidar com URIs que não correspondem às especificações fornecidas aos seus usuários é outra coisa que você deve decidir como lidar independentemente de qualquer uma das opções acima (retornar um recurso padrão? Retornar um erro 404?).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.