Haruskah saya menggunakan tipe Tanggal di JAX-RS @PathParam?

9

Ini adalah apa yang saya pikirkan tentang lakukan di server GlassEE JEE menggunakan Jersey.

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

Saya suka ide untuk bisa memberi tahu orang yang menggunakan layanan web RESTful ini bahwa "Tanggal di sini adalah apa pun yang bekerja dengan kelas Date di Java". Itu cukup sederhana dari sudut pandang bahwa mereka hanya dapat melihat spec Date, dan mereka sudah memiliki model kerja yang dapat mereka uji.

Masalah yang saya khawatirkan adalah ketika saya melakukan ini, JAX-RS tidak begitu baik ketika Date () tidak suka apa yang didapat di konstruktor. Sejak Date () melempar kesalahan jika tidak dapat menguraikan apa yang diberikan (seperti jika Anda memberikannya string "hari ini" alih-alih tanggal nyata), server JEE mengembalikan kesalahan 404.

Apakah ini praktik yang baik? Apakah ada cara yang lebih baik untuk melakukan ini yang tidak saya pikirkan?

Jazzepi
sumber

Jawaban:

8

Kedengarannya seperti ide yang buruk. Untuk satu hal, konstruktor Date yang akan Anda andalkan telah ditinggalkan sejak Java 1.1 yang mendukung DateFormat.parseDate (), tepatnya karena tidak jelas bagaimana string harus diuraikan menjadi tanggal, karena aturan berbeda untuk daerah yang berbeda.

Rekomendasi saya adalah tetap menggunakan format tertentu, lebih disukai yyyy-MM-dd yang dipahami secara internasional, dan menggunakan DateFormat untuk mengurai tanggal dari string di dalam layanan Anda, yang membuatnya jelas bagaimana cara mengkonsumsi layanan web, dan memungkinkan Anda untuk mengikuti apa pun konvensi standar untuk mengembalikan pesan kesalahan adalah untuk layanan web Anda ketika terjadi kesalahan.

Theodore Murdock
sumber
11

Saya menggunakan kelas khusus DateParam:

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

Kelas didefinisikan sebagai:

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;
  }
}

Jika parameter kosong maka Anda akan mendapatkan tanggal nol. Anda dapat memperluas DateParamdengan bidang akhir statis publik untuk nilai tanggal yang tidak ditentukan. Ini akan membuat pengujian untuk tanggal yang tidak ditentukan lebih jelas.

Satu kekurangan di sini adalah bahwa untuk setiap DateParam, instance baru SimpleDateFormat dibuat. Namun, karena SimpleDateFormat bukan thread-safe, kami tidak dapat menggunakannya kembali dengan mudah.

migu
sumber
3
1+. Java 8 memperkenalkan thread aman DateTimeFormatter. Untuk Java <= 7, saya akan menggunakanThreadLocal
Anthony Accioly
3

Siapa yang akan menggunakan layanan Anda? Apakah mereka akan repot-repot mencari spesifikasi Datekelas dan mencari tahu apa jenis string yang akan diuraikan? Saya tidak akan, bahkan jika menjadi programmer Java saya akan tahu di mana mencarinya ;-)

Saya pikir Anda harus terlebih dahulu memberi tahu pengguna Anda seperti apa URI Anda nantinya, misalnya

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

dan kemudian mencari cara agar Jersey membantu Anda dalam menguraikan format tanggal apa pun yang Anda pilih. Itu bisa berarti menggunakan Datetipe parameter dan mungkin menentukan ekspresi reguler di @Pathanotasi Anda , misalnya

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

atau menggunakan beberapa kelas lain yang mampu menguraikan tanggal dalam format Anda. Bagaimana menangani URI yang tidak cocok dengan spesifikasi yang Anda berikan kepada pengguna Anda adalah hal lain yang harus Anda putuskan bagaimana menangani secara independen dari salah satu di atas (mengembalikan sumber daya default? Mengembalikan kesalahan 404?).

agnul
sumber