Di mana menggunakan EJB 3.1 dan CDI?

120

Saya membuat produk berbasis Java EE yang saya gunakan GlassFish 3 dan EJB 3.1.

Aplikasi saya memiliki kacang sesi , penjadwal dan menggunakan layanan web. Saya baru-baru ini mengetahui tentang Apache TomEE , yang mendukung Injeksi Konteks dan Ketergantungan (CDI) . Wadah GlassFish juga mendukung CDI.

Dapatkah saya mengganti kacang sesi di mana saya tidak memerlukan fitur apa pun yang juga belum disediakan CDI? Dan jika kemudian, apa keuntungan yang bisa saya dapatkan?

Dhrumil Shah
sumber

Jawaban:

408

Ya, Anda dapat dengan bebas mencampur CDI dan EJB dan mendapatkan hasil yang luar biasa. Sepertinya Anda sedang menggunakan @WebServicedan @Schedule, itulah alasan bagus untuk menambahkan EJB ke dalam campuran.

Ada banyak kebingungan di luar sana, jadi berikut adalah beberapa informasi umum tentang EJB dan CDI yang terkait satu sama lain.

EJB> = CDI

Perhatikan bahwa EJB adalah biji CDI dan karena itu memiliki semua manfaat CDI. Kebalikannya tidak benar (belum). Jadi pastinya jangan biasakan berpikir "EJB vs CDI" karena logika itu diterjemahkan menjadi "EJB + CDI vs CDI", yang merupakan persamaan ganjil.

Di versi Java EE yang akan datang, kami akan terus menyelaraskannya. Yang dimaksud dengan menyelaraskan adalah memungkinkan orang melakukan apa yang sudah bisa mereka lakukan, hanya tanpa @Stateful, @Statelessatau @Singletonanotasi di atas.

EJB dan CDI dalam Ketentuan Pelaksanaan

Pada akhirnya, EJB dan CDI berbagi desain fundamental yang sama sebagai komponen yang diproksikan. Ketika Anda mendapatkan referensi ke kacang EJB atau CDI, itu bukanlah kacang yang sebenarnya. Sebaliknya objek yang Anda berikan adalah palsu (proxy). Saat Anda memanggil metode pada objek palsu ini, panggilan masuk ke container yang akan mengirim panggilan melalui interseptor, dekorator, dll. Serta menangani transaksi atau pemeriksaan keamanan. Setelah semua selesai, panggilan akhirnya masuk ke objek nyata dan hasilnya akan diteruskan kembali melalui proxy ke pemanggil.

Perbedaannya hanya terletak pada bagaimana objek yang akan dipanggil diselesaikan. Yang kami maksud dengan "diselesaikan" adalah, di mana dan bagaimana penampung mencari instance nyata untuk dipanggil.

Dalam CDI, penampung melihat dalam "cakupan", yang pada dasarnya akan menjadi peta hash yang berlaku untuk jangka waktu tertentu (per permintaan @RequestScoped, per Sesi HTTP @SessionScoped, per aplikasi @ApplicationScoped, Percakapan JSF @ConversationScoped, atau per implementasi cakupan khusus Anda).

Di EJB, container juga melihat ke dalam hashmap jika kacang bertipe @Stateful. Sebuah @Statefulkacang juga dapat menggunakan salah satu penjelasan ruang lingkup di atas menyebabkan ia hidup dan mati dengan semua kacang-kacangan lainnya dalam ruang lingkup. Dalam EJB @Statefulpada dasarnya adalah kacang "bercakupan apapun". Ini @Statelesspada dasarnya adalah kumpulan instance - Anda mendapatkan instance dari kumpulan selama satu pemanggilan. Ini @Singletonpada dasarnya@ApplicationScoped

Jadi pada level fundamental, apapun yang dapat Anda lakukan dengan bean "EJB", Anda harus bisa melakukan bean "CDI". Di bawah selimut, sangat sulit untuk membedakan mereka. Semua pipa ledeng sama dengan pengecualian bagaimana kasus diselesaikan.

Mereka saat ini tidak sama dalam hal layanan yang akan ditawarkan kontainer saat melakukan proxy ini, tetapi seperti yang saya katakan kami sedang mengerjakannya di tingkat spesifikasi Java EE.

Catatan kinerja

Abaikan gambaran mental "ringan" atau "berat" yang mungkin Anda miliki. Itu semua tentang pemasaran. Mereka memiliki desain internal yang sama untuk sebagian besar. Resolusi contoh CDI mungkin sedikit lebih kompleks karena sedikit lebih dinamis dan kontekstual. Resolusi instans EJB cukup statis, bodoh dan sederhana sebagai perbandingan.

Saya dapat memberi tahu Anda dari perspektif implementasi di TomEE, ada tentang perbedaan kinerja nol antara memanggil EJB vs memanggil kacang CDI.

Default ke POJO, lalu CDI, lalu EJB

Tentunya jangan gunakan CDI atau EJB bila tidak ada manfaatnya. Masukkan CDI ketika Anda mulai menginginkan injeksi, peristiwa, interseptor, dekorator, pelacakan siklus hidup, dan hal-hal seperti itu. Itu paling sering.

Di luar mereka dasar-dasar, ada sejumlah layanan kontainer berguna Anda hanya memiliki pilihan untuk menggunakan jika Anda membuat CDI kacang Anda juga EJB dengan menambahkan @Stateful, @Statelessatau @Singletondi atasnya.

Berikut daftar singkat saat saya keluar dari EJB.

Menggunakan JAX-WS

Mengekspos JAX-WS @WebService. Aku malas. Jika @WebServicejuga merupakan EJB, Anda tidak perlu mencantumkannya dan memetakannya sebagai servlet di web.xmlfile. Itu berhasil bagi saya. Selain itu, saya mendapatkan opsi untuk menggunakan salah satu fungsi lain yang disebutkan di bawah ini. Jadi itu tidak perlu dipikirkan lagi bagi saya.

Tersedia untuk @Statelessdan @Singletonhanya.

Menggunakan JAX-RS

Mengekspos sumber daya JAX-RS melalui @Path. Saya masih malas. Ketika layanan RESTful juga merupakan EJB, sekali lagi Anda mendapatkan penemuan otomatis dan tidak perlu menambahkannya ke Applicationsubkelas JAX-RS atau semacamnya. Ditambah saya dapat mengekspos kacang yang sama persis seperti @WebServicejika saya ingin atau menggunakan salah satu fungsi hebat yang disebutkan di bawah ini.

Tersedia untuk @Statelessdan @Singletonhanya.

Logika startup

Muat saat memulai melalui @Startup. Saat ini tidak ada yang setara dengan ini di CDI. Entah bagaimana kami melewatkan menambahkan sesuatu seperti AfterStartupacara dalam siklus hidup kontainer. Seandainya kami melakukan ini, Anda bisa saja memiliki @ApplicationScopedkacang yang mendengarkannya dan itu akan secara efektif sama dengan @Singletondengan @Startup. Itu ada di daftar untuk CDI 1.1.

Tersedia @Singletonhanya untuk .

Bekerja secara Paralel

@Asynchronouspemanggilan metode. Memulai utas adalah larangan di lingkungan sisi server mana pun. Memiliki terlalu banyak utas adalah pembunuh kinerja yang serius. Anotasi ini memungkinkan Anda untuk memparalelkan hal-hal yang Anda lakukan menggunakan kumpulan utas penampung. Ini luar biasa.

Tersedia untuk @Stateful, @Statelessdan @Singleton.

Menjadwalkan pekerjaan

@Scheduleatau ScheduleExpressionpada dasarnya adalah sebuah cron atau Quartzfungsionalitas. Juga sangat mengagumkan. Sebagian besar wadah hanya menggunakan Quartz di bawah penutup untuk ini. Namun, kebanyakan orang tidak tahu bahwa penjadwalan di Java EE bersifat transaksional! Jika Anda memperbarui database lalu menjadwalkan beberapa pekerjaan dan salah satunya gagal, keduanya akan secara otomatis dibersihkan. Jika EntityManagerpanggilan tetap gagal atau ada masalah flushing, tidak perlu membatalkan pekerjaan. Hore, transaksi.

Tersedia untuk @Statelessdan @Singletonhanya.

Menggunakan EntityManagers dalam transaksi JTA

Catatan tentang transaksi di atas tentu saja mengharuskan Anda menggunakan JTAmanaged EntityManager. Anda dapat menggunakannya dengan "CDI" biasa, tetapi tanpa transaksi yang dikelola container, duplikasi UserTransactionlogika commit / rollback bisa sangat monoton .

Tersedia untuk semua komponen Java EE termasuk CDI, JSF @ManagedBean, @WebServlet, @WebListener, @WebFilter, dll @TransactionAttributepenjelasan, bagaimanapun, tersedia untuk @Stateful, @Statelessdan @Singletonhanya.

Menjaga JTA tetap dikelola EntityManager

The EXTENDEDberhasil EntityManagermemungkinkan Anda untuk tetap EntityManagerterbuka antara JTAtransaksi dan tidak kehilangan data cache. Fitur bagus untuk waktu dan tempat yang tepat. Gunakan secara bertanggung jawab :)

Tersedia @Statefulhanya untuk .

Sinkronisasi mudah

Saat Anda membutuhkan sinkronisasi, anotasi @Lock(READ)dan @Lock(WRITE)cukup bagus. Ini memungkinkan Anda untuk mendapatkan manajemen akses bersamaan secara gratis. Lewati semua pipa ledeng ReentrantReadWriteLock. Di bucket yang sama is @AccessTimeout, yang memungkinkan Anda untuk mengatakan berapa lama thread harus menunggu untuk mendapatkan akses ke instance bean sebelum menyerah.

Tersedia @Singletonhanya untuk kacang.

David Blevins
sumber
32
Astaga David :) Saya pikir Anda menutupinya.
LightGuard
7
Terima kasih atas jawaban ini. Anda telah membersihkan penyumbatan di kepala saya dan menghubungkan banyak titik.
Thupten
7
Sejauh ini, inilah penjelasan terbaik tentang topik itu yang pernah saya baca. Ini juga mencakup hampir semua aspek penting EJB dalam penggunaan Kehidupan Nyata juga. Kerja bagus!!
nanoquack
3
Sangat bisa dimengerti dan Adam tidak salah dalam istilah hukum yang ketat, tapi perbedaannya diperdebatkan. Spesifikasi mengatakan instance EJB tidak kontekstual, tetapi kemudian mengatakan kemudian referensi (proxy) ke EJB adalah kontekstual. Siklus hidup kacang Stateful dikontrol sepenuhnya melalui referensi (proxy), jadi ketika wadah CDI mengontrol referensi (proxy) matematika keluar sama - EJB Stateful dapat secara efektif kontekstual.
David Blevins
3
Apakah Anda menulis ini saat istirahat makan siang di TESLA?
Edison
2

jika Anda benar-benar tidak menggunakan salah satu fitur ejb 3.1 jawabannya sederhana. tetapi tebak pencarian Anda menunjukkan bahwa Anda mencurigai ada konsep ejb 3.1 yang Anda manfaatkan tanpa menyadarinya. satu contoh mungkin bahwa wadah dapat menyimpan kumpulan slsb siap digunakan, sehingga koneksi jms dan database tidak perlu dimasukkan sebagai bagian dari permintaan

Aksel Willgert
sumber