Backing beans (@ManagedBean) atau CDI Beans (@Named)?

109

Saya baru saja mulai membaca Core JavaServer Faces, 3rd Ed. dan mereka mengatakan ini (penekanan dari saya):

Merupakan kecelakaan historis bahwa ada dua mekanisme terpisah, biji CDI dan biji yang dikelola JSF, untuk biji yang dapat digunakan di halaman JSF. Kami menyarankan Anda menggunakan kacang CDI kecuali jika aplikasi Anda harus bekerja pada pelari servlet biasa seperti Tomcat.

Mengapa? Mereka tidak memberikan pembenaran apa pun . Saya telah menggunakan @ManagedBeanuntuk semua kacang dalam aplikasi prototipe yang berjalan di GlassFish 3, dan saya belum benar-benar memperhatikan masalah apa pun dengan ini. Saya tidak keberatan bermigrasi dari @ManagedBeanke @Named, tetapi saya ingin tahu mengapa saya harus repot .

Matt Ball
sumber
4
@ Bozho: pertanyaan itu sangat mirip, tetapi setelah membaca jawaban Pascal beberapa kali, saya masih tidak mengerti mengapa CDI jauh lebih unggul. Saya tidak tahu CDI dan saya senang mempelajarinya karena "lebih baik". Mengapa lebih baik?
Matt Ball
"kecuali aplikasi Anda harus bekerja pada pelari servlet biasa seperti Tomcat" Saya hanya menggunakan tomcat dan saya sangat merekomendasikan CDI. Tomcat dapat mendukungnya dengan baik
Karl Kildén
1
@ KarlKildén "pelari servlet biasa" mengacu pada wadah servlet yang tidak dapat digunakan CDI. Pada saat penulisan Tomcat tidak mendukung CDI kecuali dengan sedikit keajaiban.
Thorbjørn Ravn Andersen

Jawaban:

64

CDI lebih disukai daripada JSF biasa karena CDI memungkinkan injeksi ketergantungan seluruh JavaEE. Anda juga dapat menyuntikkan POJO dan membiarkannya dikelola. Dengan JSF Anda hanya dapat menyuntikkan sebagian dari apa yang Anda bisa dengan CDI.

Bozho
sumber
Jadi pada dasarnya, saya dapat memasukkan instance dari hampir semua kelas (asalkan memiliki "hal yang tepat" - apa itu, hanya konstruktor tanpa argumen? ) Dengan CDI, sementara saya harus menggunakan @ManagedBeanjika saya ingin menyuntikkannya dengan JSF?
Matt Ball
3
@MattBall Matt setelah Anda bertahun-tahun, dapatkah Anda mengomentari migrasi ini?
Koray Tugay
5
@KorayTugay Saya belum menyentuh kode ini sejak Juni 2011 tetapi saya telah beralih ke CDI dan semuanya bekerja dengan baik. Saya akan dengan senang hati menjawab pertanyaan spesifik apa pun sepanjang ingatan saya jika Anda memilikinya.
Matt Ball
170

Gunakan CDI.

Sesuai JSF 2.3, @ManagedBeansudah tidak digunakan lagi . Lihat juga masalah spesifikasi 1417 . Ini berarti bahwa tidak ada lagi alasan untuk memilih @ManagedBeanlebih @Named. Ini pertama kali diterapkan di Mojarra 2.3.0 versi beta m06.

masukkan deskripsi gambar di sini


Sejarah

Perbedaan utamanya adalah, @ManagedBeandikelola oleh kerangka kerja JSF dan hanya @ManagedPropertytersedia melalui biji yang dikelola JSF lainnya. @Nameddikelola oleh server aplikasi (wadah) melalui kerangka kerja CDI dan melalui @Injecttersedia untuk setiap jenis wadah artefak dikelola seperti @WebListener, @WebFilter, @WebServlet, @Path, @Stateless, dll dan bahkan JSF @ManagedBean. Dari sisi lain, @ManagedPropertytidak bukan bekerja di dalam @Namedatau wadah dikelola artefak lainnya. Ia bekerja hanya di dalam @ManagedBean.

Perbedaan lainnya adalah CDI sebenarnya menyuntikkan proxy yang didelegasikan ke instance saat ini dalam cakupan target berdasarkan per-permintaan / utas (seperti bagaimana EJB diinjeksi). Mekanisme ini memungkinkan penyuntikan kacang dari lingkup yang lebih sempit ke dalam kacang dengan cakupan yang lebih luas, yang tidak mungkin dilakukan dengan JSF @ManagedProperty. JSF "menyuntikkan" di sini contoh fisik secara langsung dengan memanggil penyetel (itu juga alasan mengapa penyetel diperlukan, sementara itu tidak diperlukan dengan @Inject).

Meskipun tidak secara langsung merugikan - ada cara lain - cakupannya @ManagedBeansangat terbatas. Dari perspektif lain, jika Anda tidak ingin mengekspos "terlalu banyak" @Inject, Anda juga dapat menyimpan kacang yang Anda kelola @ManagedBean. Ini seperti protectedversus public. Tapi itu tidak dihitung.

Setidaknya, di JSF 2.0 / 2.1, kelemahan utama dari mengelola kacang pendukung JSF oleh CDI adalah tidak adanya CDI yang setara @ViewScoped. The @ConversationScopeddatang dekat, tapi masih membutuhkan manual mulai dan berhenti dan menambahkan jelek cidpermintaan parameter untuk URL hasil. MyFaces CODI membuatnya lebih mudah dengan menjembatani JSF javax.faces.bean.ViewScopedke CDI secara transparan sehingga Anda dapat melakukannya @Named @ViewScoped, namun itu menambahkan windowIdparameter permintaan yang jelek ke URL hasil, juga pada navigasi halaman-ke-halaman vanilla biasa. OmniFaces menyelesaikan ini semua dengan CDI sejati @ViewScopedyang benar-benar mengikat ruang lingkup kacang ke status tampilan JSF alih-alih ke parameter permintaan arbitrer.

JSF 2.2 (yang dirilis 3 tahun setelah pertanyaan / jawaban ini) menawarkan @ViewScopedanotasi baru yang kompatibel dengan CDI di luar kotak dalam bentuk javax.faces.view.ViewScoped. JSF 2.2 bahkan hadir dengan CDI-only @FlowScopedyang tidak memiliki @ManagedBeanpadanan, dengan ini mendorong pengguna JSF ke CDI. Harapannya adalah bahwa @ManagedBeandan teman-teman akan tidak digunakan lagi sesuai Java EE 8. Jika saat ini Anda masih menggunakan @ManagedBean, oleh karena itu sangat disarankan untuk beralih ke CDI untuk bersiap untuk jalur peningkatan di masa mendatang. CDI sudah tersedia dalam wadah yang kompatibel dengan Profil Web Java EE, seperti WildFly, TomEE dan GlassFish. Untuk Tomcat, Anda harus menginstalnya secara terpisah, persis seperti yang Anda lakukan untuk JSF. Lihat juga Bagaimana cara menginstal CDI di Tomcat?

BalusC
sumber
4
Saya telah membuat beans.xml, mengubah @ManagedBeanbacking beans menjadi @Named, dan mengubahnya @ManagedPropertymenjadi @Inject. Semua baik-baik saja di dunia. Namun, jika saya mengubah @EJBanotasi saya menjadi @Inject, penerapan gagal ( org.jboss.weld.exceptions.DeploymentException) dengan pesan WELD-001408 Injection point has unsatisfied dependencies. Haruskah saya benar-benar menggunakan @Injectuntuk menyuntikkan EJB tanpa antarmuka ke dalam @Namedkacang, atau haruskah saya tetap menggunakannya @EJB? EJB dikemas dalam EJB JAR, EAR yang sama dengan WAR yang berisi kacang CDI saya.
Matt Ball
Seharusnya itu berhasil. Apakah Anda masih menghadapi masalah ini dengan versi Weld saat ini?
BalusC
Sayangnya, saya tidak bisa mengatakannya. Pertanyaan ini dari 2 pemberi kerja dan> 2 tahun yang lalu. Berdasarkan komentar lama saya atas jawaban Bozho, saya pasti sudah beralih ke CDI / @Named.
Matt Ball
"CODI MyFaces membuatnya lebih mudah dengan secara transparan menjembatani javax.faces.bean.ViewScoped JSF ke CDI sehingga Anda dapat melakukannya @Named @ViewScoped, namun hal itu menambahkan parameter permintaan windowId yang jelek ke URL hasil, juga pada navigasi halaman-ke-halaman vanilla biasa." Perhatikan bahwa dengan DeltaSpike, hal ini tidak berlaku lagi. Anda dapat menonaktifkan parameter URL dsId dan windowId, jika Anda tidak membutuhkan Window Scope.
JanM
1
@Jan: Dan sementara itu, OmniFaces juga memiliki JSF 2.2-like @ViewScopeduntuk JSF 2.0 / 2.1: showcase.omnifaces.org/cdi/ViewScoped
BalusC
16

Dengan Java EE 6 dan CDI, Anda memiliki opsi berbeda untuk Managed Beans

  • @javax.faces.bean.ManagedBeanmengacu pada JSR 314 dan diperkenalkan dengan JSF 2.0. Tujuan utamanya adalah untuk menghindari konfigurasi di fileface-config.xml untuk menggunakan kacang di dalam Halaman JSF.
  • @javax.annotation.ManagedBean(“myBean”) didefinisikan oleh JSR 316. Ini menggeneralisasi kacang yang dikelola JSF untuk digunakan di tempat lain di Java EE
  • @javax.inject.Named(“myBean”) hampir sama, dengan yang di atas, kecuali Anda membutuhkan file beans.xml di folder web / WEB-INF untuk mengaktifkan CDI.
h2mch
sumber
1
Apa perbedaan antara dua yang pertama?
Matt Ball
Tujuan dari penjelasan pertama adalah / adalah untuk mengganti konfigurasi kacang di face-config.xml untuk digunakan di JSF. Yang kedua menyalin konsep ke dalam "java ee 6 container". Ia memiliki lebih banyak fungsi (seperti @PostConstruct dan @PreDestroy anotasi), tetapi juga dapat dijangkau oleh Halaman JSF (dengan Expression Language).
h2mch
1
mengapa Anda membutuhkan beans.xmlfile? Apakah ini masih berlaku sampai sekarang?
Thufir
2
Tidak, dengan JavaEE7 Anda tidak membutuhkan beans.xml lagi. lihat docs.oracle.com/javaee/7/tutorial/doc/cdi-adv001.htm
h2mch
1
Dengan JavaEE7 Anda tidak memerlukan beans.xml: docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm (link yang benar) blogs.oracle.com/theaquarium/entry/… ( Pengaktifan CDI Default di Java EE 7)
M. Atif Riaz
2

Saya menggunakan CDI di GlassFish 3.0.1, tetapi untuk membuatnya bekerja saya harus mengimpor kerangka Seam 3 (Weld). Itu bekerja dengan cukup baik.

Di GlassFish 3.1 CDI berhenti bekerja, dan Seam Weld berhenti bekerja dengannya. Saya membuka bug tentang ini tetapi belum melihatnya diperbaiki. Saya harus mengonversi semua kode saya untuk menggunakan anotasi javax.faces. * Tetapi saya berencana untuk kembali ke CDI setelah mereka berhasil.

Saya setuju Anda harus menggunakan CDI, tetapi satu masalah yang belum saya selesaikan adalah apa yang harus dilakukan dengan anotasi @ViewScoped. Saya memiliki banyak kode yang bergantung padanya. Tidak jelas apakah @ViewScoped berfungsi jika Anda tidak menggunakan @ManagedBean dengannya. Jika ada yang bisa menjelaskan ini, saya akan sangat menghargainya.

AlanObject
sumber
-1

Satu alasan bagus untuk pindah ke CDI: Anda dapat memiliki sumber daya cakupan sesi yang umum (misalnya profil pengguna) @Injectke dalam kacang yang dikelola JSF dan layanan REST (yaitu, Jersey / JAX-RS).

Di sisi lain, @ViewScopedadalah alasan kuat untuk tetap menggunakan JSF @ManagedBean- terutama untuk apa pun dengan AJAX yang signifikan. Tidak ada pengganti standar untuk ini di CDI.

Tampaknya itu mungkin memiliki beberapa dukungan untuk @ViewScopedanotasi -seperti untuk kacang CDI, tapi saya belum bermain dengannya secara pribadi.

http://seamframework.org/Seam3/FacesModule

wrschneider
sumber