2013-05-13 26 views
5

Hãy tưởng tượng bạn có một bộ lọc bắt đầu một giao dịch cơ sở dữ liệu, xử lý yêu cầu, và sau đó cố gắng thực hiện giao dịch.Bạn có thể thực hiện lọc Servlet truyền thống bằng JAX-RS/Jersey không?

doFilter(...) { 
    ... 
    transaction.begin(); 
    filterChain.doFilter(request, response); 
    transaction.commit(); 
} 

Sử dụng Jersey, có một số vấn đề:

  1. Sử dụng một bộ lọc, các Jersey Servlet container cam/xả phản ứng trước lợi nhuận thực hiện để bộ lọc của bạn. Vì vậy, nếu cam kết không thành công, bạn không thể sửa đổi mã trả về thành lỗi. Ngoài ra, các ngoại lệ sẽ không bị JAX-RS ExceptionMapper phát hiện.
  2. Sử dụng vùng chứaRequestFilter/ContainerResponseFilter.

    lọc ContainerRequest công cộng (ContainerRequest yêu cầu) { ... }
    công cộng lọc ContainerResponse (ContainerRequest yêu cầu, ContainerResponse response) { ... }

này cho phép ngoại lệ đối với bong bóng lên cho một ExceptionMapper, nhưng tách logic trên 2 phương thức/giao diện riêng biệt. Vấn đề là nếu có một ngoại lệ không ánh xạ tới một phản hồi, thì ContainerResponseFilter sẽ không bao giờ được gọi, vì vậy bạn không thể dọn sạch.

Cách ưu tiên để xử lý điều này trong môi trường JAX-RS là gì? Có cách nào để cấu hình các flushing của phản ứng, hoặc là có một lớp học hoặc giao diện mà tôi nhìn?

+0

Những gì bạn mô tả thường được gọi là mẫu "phiên mở trong chế độ xem" (chống). Xem [câu hỏi SO này] (http://stackoverflow.com/q/1103363/131929) để thảo luận. Cũng chuyển sang JBoss (Hibernate/Seam) để thảo luận thêm, ví dụ: https://community.jboss.org/docs/DOC-13954 –

+0

Chắc chắn có một số cuộc tranh luận về chính xác "khung nhìn" cấu thành, nhưng đây chỉ là một ứng dụng REST. Phương thức tài nguyên jax-rs là lớp dịch vụ và chúng sử dụng sự kiên trì trực tiếp. Đối tượng phản hồi là kết quả của cuộc gọi dịch vụ. Tôi đang cố gắng tránh việc quản lý giao dịch trong mọi phương thức, và câu trả lời là một cái gì đó giống như một bộ lọc, hoặc tôi bắt đầu can thiệp CDI (mà tôi muốn tránh tại thời điểm này trong dự án, nếu tôi có thể). – Shaun

Trả lời

3

Tôi đã nghiên cứu vấn đề này một chút cho ứng dụng JAX-RS/RESTEasy. Hai tùy chọn tôi đang cân nhắc trước khi đọc câu hỏi này:

  1. Viết một ExceptionMapper<Throwable> (hoặc ExceptionMapper<DaoException> với một tuỳ chỉnh DaoException) và xử lý nó có hoặc trong ContainerResponseFilter đó sẽ được thực hiện vì sự ExceptionMapper<?> xử lý tất cả trường hợp ngoại lệ.
  2. Trước transaction.begin(), hãy kiểm tra trạng thái hiện tại của giao dịch và quay lại tại đó nếu cần.

Có vấn đề với cả hai tùy chọn.

  1. Tôi tìm thấy ExceptionMapper<Throwable> quá rộng, trong khi ExceptionMapper<DaoException> có thể bỏ lỡ một số ngoại lệ khác, một lần nữa để giao dịch không được dọn sạch.
  2. Quay lại giao dịch theo yêu cầu tiếp theo có thể mất nhiều thời gian, có thể gây ra sự cố khóa cho các giao dịch khác.

Vì vậy, sau khi đọc câu hỏi của bạn, tôi đang suy nghĩ:

  • Sử dụng một ContainerRequestFilter để bắt đầu giao dịch (kết hợp với việc xây dựng @NameBinding chú thích).
  • Sử dụng ContainerResponseFilter để thực hiện giao dịch (nếu phương thức tài nguyên chưa đóng giao dịch).
  • Sử dụng Filter để đảm bảo giao dịch đã bị đóng và nếu không, hãy cuộn lại.
+0

Ý của bạn là "ExceptionMapper quá rộng"? Nếu bạn chỉ kiểm tra phiên cho một giao dịch đang hoạt động trong ExceptionMapper , bạn có thể chắc chắn đã xảy ra sự cố và khôi phục. Nếu không có giao dịch hoạt động, không làm gì cả. Vấn đề tôi thấy là nếu transaction.commit() không thành công trong ContainerResponseFilter, đối tượng phản hồi sẽ phải được thay đổi. Bạn không chắc chắn điều gì sẽ xảy ra nếu một ngoại lệ được ném trong ContainerResponseFilter, nó có bị bắt bởi ExceptionMapper không? – joscarsson

+0

Quá rộng theo nghĩa là bạn cũng có thể có 'ExceptionMapper '. 'ExceptionMapper ' nào sẽ xử lý ngoại lệ? Đầu tiên là một 'SpecificException' và sau đó là cái cho' Throwable'? Hay người kia nuốt một 'SpecificException'? – drvdijk