2013-05-13 23 views
5

Veritabanı işlemi başlatan, isteği işleyen ve ardından işlemi gerçekleştirmeye çalışan bir filtreniz olduğunu düşünün. Bazı sorunlar var Jersey kullanmaJAX-RS/Jersey ile geleneksel Servlet Filtreleme yapabilir misiniz?

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

:

  1. Filtre kullanarak, Jersey Servlet Container taahhüt/Filtrenize yürütme dönmeden önce yanıtı temizler. Bu nedenle, işlem başarısız olursa, dönüş kodunu bir hata olarak değiştiremezsiniz. Ayrıca, istisnalar bir JAX-RS ExceptionMapper tarafından yakalanmayacaktır.
  2. ContainerRequestFilter/ContainerResponseFilter öğesinin kullanılması.

    (ContainerRequest istek) { ... }
    kamu ContainerResponse filtresi (ContainerRequest istek, ContainerResponse response) { ... }

Bu kadar kabarcık istisnalar tanımaktadır

kamu ContainerRequest filtresi bir ExceptionMapper için, ancak 2 ayrı yöntem/arabirim üzerinden mantığı böler. Sorun, bir yanıtı eşlemeyen bir istisna varsa, ContainerResponseFilter hiçbir zaman çağrılmamaktadır, bu yüzden temizleyemezsiniz.

JAX-RS ortamında bunu işlemenin tercih edilen yolu nedir? Yanıtın yıkanmasını yapılandırmanın bir yolu var mı, yoksa baktığım bir sınıf veya arayüz var mı?

+0

Anlattığınız şey genellikle "açık oturum görünümü" (anti-) desen olarak bilinir. Bir tartışma için bkz. [Bu SO sorusu] (http://stackoverflow.com/q/1103363/131929). Ayrıca, daha fazla tartışma için JBoss'a (Hazırda Bekletme/Dikiş) dönün. https://community.jboss.org/docs/DOC-13954 –

+0

Tam olarak bir "görünüm" in ne olduğuna dair bir tartışma var, ama bu sadece bir REST uygulaması. Jax-rs kaynak yöntemleri hizmet katmanıdır ve kalıcılık kullanırlar. Yanıt nesnesi, servis çağrısının sonucudur. Her yöntemde işlem yönetiminden kaçınmaya çalışıyorum ve cevap ya bir filtreye benzeyen bir şeydir, ya da CDI kesişimine (ki bu durumda projede bu noktadan kaçınmak isterim) kablo bağlarım var. – Shaun

cevap

3

Bunu bir JAX-RS/RESTEasy uygulaması için de biraz araştırıyorum. Bu soruyu okumadan önce ben düşündüğünü iki seçenek:

  1. bir ExceptionMapper<Throwable> (özel bir DaoException veya ExceptionMapper<DaoException>) yazın ve orada işlemek veya çünkü tüm durumları işleme ExceptionMapper<?> arasında yürütülen alacak ContainerResponseFilter içinde.
  2. transaction.begin()'dan önce, işlemin geçerli durumunu kontrol edin ve gerekirse geri dönün.

Her iki seçenekte de sorunlar var. ExceptionMapper<DaoException>, diğer bazı istisna kaçırmak tekrar işlem temizlenmiş değil bırakarak olabilir iken

  1. Ben bir ExceptionMapper<Throwable> çok geniş bulabilirsiniz.
  2. Bir sonraki istekte işlemi geri almak uzun sürebilir, bu da diğer işlemler için kilitleme sorunlarına neden olabilir.

Yani soru okuduktan sonra, Şu anda düşünüyorum:

  • (@NameBinding açıklama inşaatı ile birlikte) işlemlerini başlatmak için bir ContainerRequestFilter kullanma.
  • Bir işlem gerçekleştirmek için ContainerResponseFilter'u kullanın (kaynak yöntemi henüz kapatmamışsa).
  • Bir işlemin kapatıldığından emin olmak için Filter'u kullanın ve değilse geri sarın.
+0

Nasıl "ExceptionMapper çok geniş" demek istiyorsun? ExceptionMapper 'da etkin bir işlem için oturumu denetlerseniz, bir şeyler ters gittiğinden ve geri alınabileceğinden emin olabilirsiniz. Etkin işlem yoksa, hiçbir şey yapmayın. Gördüğüm sorun, ContainerResponseFilter içinde transaction.commit() öğesi başarısız olursa, yanıt nesnesinin değiştirilmesi gerekir. ContainerResponseFilter'da bir istisna atılırsa ne olacağından emin değil misiniz, ExceptionMapper tarafından yakalanacak mı? – joscarsson

+0

Ayrıca, "ExceptionMapper " özelliğine sahip olabileceğiniz için çok geniş. İstisnai "ExceptionMapper " hangi görevi kaldıracaktır? Önce 'SpecificException' ve ardından 'Throwable' için olanı hangisi? Yoksa ikincisi bir 'SpecificException' yuturur mu? – drvdijk

İlgili konular