1. Target Tidak Dapat Dicapai, pengidentifikasi 'kacang' diselesaikan ke nol
Ini bermuara pada bahwa contoh kacang yang dikelola itu sendiri tidak dapat ditemukan dengan persis pengenal (nama kacang yang dikelola) di EL seperti itu #{bean}.
Mengidentifikasi penyebabnya dapat dipecah menjadi tiga langkah:
Sebuah. Siapa yang mengelola kacang?
b. Apa nama kacang yang dikelola (default)?
c. Di mana kelas kacang dukungan?
1a. Siapa yang mengelola kacang?
Langkah pertama adalah memeriksa kerangka kerja manajemen kacang mana yang bertanggung jawab untuk mengelola instance kacang. Apakah ini JSF via @ManagedBean? Atau melalui CDI@Named ? Atau musim semi lewat @Component? Bisakah Anda memastikan bahwa Anda tidak mencampur anotasi kerangka kerja beberapa manajemen kacang pada kelas kacang dukungan yang sama? Misalnya @Named @Component, atau @Named @ManagedBean, atau @ManagedBean @Component. Ini salah. Kacang harus dikelola oleh paling banyak satu kerangka kerja pengelolaan kacang dan kerangka kerja itu harus dikonfigurasi dengan benar. Jika Anda tidak tahu harus memilih mana, pergilah ke Backing beans (@ManagedBean) atau CDI Beans (@Named)? dan integrasi Spring JSF: bagaimana cara menyuntikkan komponen / layanan Spring dalam kacang yang dikelola JSF?
Jika JSF yang mengelola kacang melalui @ManagedBean, maka Anda perlu memastikan hal-hal berikut:
The faces-config.xmlakar deklarasi kompatibel dengan JSF 2.0. Jadi file XSD dan versionharus setidaknya menentukan JSF 2.0 atau lebih tinggi dan dengan demikian tidak 1.x.
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
Untuk JSF 2.1, cukup ganti 2_0dan 2.0dengan 2_1dan 2.1masing - masing.
Jika Anda menggunakan JSF 2.2 atau lebih tinggi, pastikan Anda menggunakan xmlns.jcp.orgruang nama alih-alih dari java.sun.comsemua tempat.
<faces-config
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
Untuk JSF 2.3, cukup ganti 2_2dan 2.2dengan 2_3dan 2.3masing - masing.
Anda tidak sengaja mengimpor javax.annotation.ManagedBeanbukan javax.faces.bean.ManagedBean. Hati-hati dengan IDE autocomplete, Eclipse dikenal untuk menyarankan secara otomatis yang salah sebagai item pertama dalam daftar.
- Anda tidak mengganti
@ManagedBeandengan <managed-bean>entri gaya JSF 1.x di faces-config.xmlpada kelas kacang dukungan yang sama bersama dengan nama kacang terkelola yang berbeda. Yang ini akan lebih diutamakan @ManagedBean. Mendaftarkan kacang terkelola faces-config.xmltidak diperlukan sejak JSF 2.0, hapus saja.
- Classpath runtime Anda bersih dan bebas dari duplikat di JAR terkait JSF API. Pastikan Anda tidak mencampur beberapa implementasi JSF (Mojarra dan MyFaces). Pastikan Anda tidak menyediakan file JSF JSF atau Java EE API lainnya di webapp ketika wadah target sudah bundel API JSF di luar kotak. Lihat juga "Memasang JSF" dari halaman wiki JSF kami untuk instruksi pemasangan JSF. Jika Anda berniat untuk meningkatkan JSF yang dibundel dalam wadah dari WAR pada dan bukan di dalam wadah itu sendiri, pastikan Anda telah menginstruksikan wadah target untuk menggunakan JSF API / impl yang dibundel dengan WAR.
- Jika Anda mengemas kacang yang dikelola JSF dalam JAR, maka pastikan bahwa JAR memiliki setidaknya JSF 2.0 yang kompatibel
/META-INF/faces-config.xml. Lihat juga Bagaimana merujuk kacang yang dikelola JSF yang disediakan dalam file JAR?
Jika Anda benar-benar menggunakan JSF 1.x jurassic, dan Anda tidak dapat meng-upgrade, maka Anda harus mendaftar kacang melalui <managed-bean>di faces-config.xmlbukannya @ManagedBean. Jangan lupa untuk memperbaiki path build proyek Anda sehingga Anda tidak memiliki pustaka JSF 2.x lagi (sehingga @ManagedBeananotasi tidak akan berhasil dikompilasi secara membingungkan).
Jika CDI- lah yang mengelola biji melalui @Named, maka Anda perlu memastikan hal-hal berikut:
CDI 1.0 (Java EE 6) membutuhkan /WEB-INF/beans.xmlfile untuk mengaktifkan CDI di WAR. Itu bisa kosong atau hanya memiliki konten berikut:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
CDI 1.1 (Java EE 7) tanpa beans.xml, atau beans.xmlfile kosong , atau dengan CDI 1.0 yang kompatibel beans.xmlakan berperilaku sama dengan CDI 1.0. Ketika ada CDI 1.1 kompatibel beans.xmldengan eksplisit version="1.1", maka akan secara default hanya mendaftar @Namedkacang dengan sebuah CDI lingkup penjelasan eksplisit seperti @RequestScoped, @ViewScoped, @SessionScoped, @ApplicationScoped, dll Dalam kasus Anda berniat untuk mendaftarkan semua kacang sebagai CDI dikelola kacang, bahkan mereka tanpa eksplisit Cakupan CDI, gunakan CDI 1.1 yang kompatibel /WEB-INF/beans.xmldengan bean-discovery-mode="all"set di bawah ini (standarnya adalah bean-discovery-mode="annotated").
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>
Saat menggunakan CDI 1.1+ dengan bean-discovery-mode="annotated"(default), pastikan Anda tidak secara tidak sengaja mengimpor lingkup JSF seperti javax.faces.bean.RequestScopedbukan lingkup CDI javax.enterprise.context.RequestScoped. Hati-hati dengan IDE autocomplete.
- Saat menggunakan Mojarra 2.3.0-2.3.2 dan CDI 1.1+ dengan
bean-discovery-mode="annotated"(default), maka Anda perlu memutakhirkan Mojarra ke 2.3.3 atau lebih baru karena bug . Dalam kasus Anda tidak dapat meng-upgrade, maka Anda perlu baik untuk set bean-discovery-mode="all"di beans.xml, atau untuk menempatkan JSF 2.3 spesifik @FacesConfigpenjelasan pada kelas sewenang-wenang dalam WAR (umumnya semacam aplikasi scoped kelas startup).
- Kontainer EE non-Jawa seperti Tomcat dan Jetty tidak dikirimkan bersama CDI. Anda harus menginstalnya secara manual. Ini sedikit lebih banyak pekerjaan daripada hanya menambahkan JAR perpustakaan. Untuk Tomcat, pastikan Anda mengikuti instruksi dalam jawaban ini: Bagaimana cara menginstal dan menggunakan CDI di Tomcat?
- Classpath runtime Anda bersih dan bebas dari duplikat dalam JAR terkait CDI. Pastikan Anda tidak mencampur beberapa implementasi CDI (Weld, OpenWebBeans, dll). Pastikan Anda tidak menyediakan CDI lain atau bahkan file Java EE API JAR di sepanjang webapp ketika wadah target sudah bundel dengan CDI API di luar kotak.
Jika Anda mengemas kacang yang dikelola CDI untuk tampilan JSF dalam JAR, maka pastikan bahwa JAR setidaknya memiliki yang valid /META-INF/beans.xml(yang dapat disimpan kosong).
Jika Spring yang mengelola bean melalui @Component, maka Anda perlu memastikan hal-hal berikut:
Spring sedang diinstal dan terintegrasi sesuai dokumentasinya . Yang penting, Anda setidaknya harus memiliki ini di web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Dan ini di faces-config.xml:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
(di atas adalah semua yang saya tahu sehubungan dengan Spring - Saya tidak melakukan Spring - jangan ragu untuk mengedit / berkomentar dengan kemungkinan penyebab terkait Spring lainnya; misalnya beberapa masalah terkait konfigurasi XML)
Dalam kasus itu komponen repeater siapa yang mengelola (bersarang) kacang melalui nya varatribut (misalnya <h:dataTable var="item">, <ui:repeat var="item">, <p:tabView var="item">, dll) dan Anda benar-benar mendapat "Target Unreachable, identifier 'item' memutuskan untuk null", maka Anda perlu memastikan berikut ini :
Tidak #{item}dirujuk dalam bindingatribut komponen anak apa pun. Ini tidak benar karena bindingatribut berjalan selama waktu pembuatan tampilan, bukan selama waktu tampilan render. Selain itu, secara fisik hanya ada satu komponen dalam komponen pohon yang hanya digunakan kembali selama setiap putaran iterasi. Dengan kata lain, Anda harus benar-benar menggunakan binding="#{bean.component}"bukan binding="#{item.component}". Tetapi jauh lebih baik untuk menyingkirkan komponen bining sekaligus dan selidiki / tanyakan pendekatan yang tepat untuk masalah yang Anda pikir dapat memecahkan masalah ini. Lihat juga Bagaimana atribut 'mengikat' bekerja di JSF? Kapan dan bagaimana seharusnya digunakan?
1b. Apa nama kacang yang dikelola (default)?
Langkah kedua adalah memeriksa nama kacang yang dikelola terdaftar. Konvensi JSF dan Spring menggunakan spesifikasi JavaBeans sementara CDI memiliki pengecualian tergantung pada versi / implementasi CDI.
Kelas FooBeanbacking bean seperti di bawah ini,
@Named
public class FooBean {}
akan di semua kerangka kerja manajemen bean memiliki nama default kacang dikelola #{fooBean}, sesuai spesifikasi JavaBeans.
Kelas FOOBeanbacking bean seperti di bawah ini,
@Named
public class FOOBean {}
yang nama kelasnya tidak memenuhi syarat dimulai dengan setidaknya dua ibukota akan di JSF dan Spring memiliki nama kacang dikelola standar persis nama kelas yang tidak memenuhi syarat #{FOOBean}, juga sesuai dengan spesifikasi JavaBeans. Dalam CDI, ini juga merupakan kasus dalam versi Weld yang dirilis sebelum Juni 2015, tetapi tidak dalam versi Weld yang dirilis setelah Juni 2015 (2.2.14 / 2.3.0.B1 / 3.0.0.A9) atau di OpenWebBeans karena pengawasan di Spesifikasi CDI . Dalam versi Weld tersebut dan dalam semua versi OWB hanya dengan karakter pertama yang lebih rendah #{fOOBean}.
Jika Anda telah secara eksplisit menentukan nama kacang yang dikelola fooseperti di bawah ini,
@Named("foo")
public class FooBean {}
atau setara dengan @ManagedBean(name="foo")atau @Component("foo"), maka itu hanya akan tersedia oleh #{foo}dan dengan demikian bukan oleh #{fooBean}.
1c. Di mana kelas kacang dukungan?
Langkah ketiga adalah memeriksa ulang jika kelas backing bean berada di tempat yang tepat di file WAR yang dibangun dan digunakan. Pastikan Anda telah melakukan pembersihan, pembangunan kembali, penempatan ulang, dan restart proyek dan server seandainya Anda benar-benar sibuk menulis kode dan dengan tidak sabar menekan F5 di browser. Jika masih sia-sia, biarkan sistem build menghasilkan file WAR, yang kemudian Anda ekstrak dan periksa dengan alat ZIP. File yang dikompilasi .classdari kelas backing bean harus berada dalam struktur paketnya di /WEB-INF/classes. Atau, ketika itu dikemas sebagai bagian dari modul JAR, JAR yang berisi .classfile yang dikompilasi harus berada di /WEB-INF/libdan dengan demikian tidak misalnya EAR /libatau di tempat lain.
Jika Anda menggunakan Eclipse, pastikan kelas backing bean ada srcdan tidak WebContent , dan pastikan Project> Build Automatically diaktifkan. Jika Anda menggunakan Maven, pastikan kelas backing bean berada di src/main/javadan dengan demikian tidak di src/main/resourcesatau src/main/webapp.
Jika Anda mengemas aplikasi web sebagai bagian dari EAR dengan EJB + WAR (s), maka Anda perlu memastikan bahwa kelas kacang latar ada dalam modul WAR dan dengan demikian tidak dalam modul EAR atau modul EJB. Business tier (EJB) harus bebas dari artefak terkait web tier (WAR), sehingga tier bisnis dapat digunakan kembali di berbagai tingkatan web yang berbeda (JSF, JAX-RS, JSP / Servlet, dll).
2. Target Tidak Dapat Dicapai, 'entitas' dikembalikan nol
Ini bermuara pada bahwa properti bersarangentity seperti dalam #{bean.entity.property}dikembalikan null. Ini biasanya hanya mengekspos ketika JSF perlu menetapkan nilai untuk propertymelalui komponen input seperti di bawah ini, sedangkan yang #{bean.entity}sebenarnya dikembalikan null.
<h:inputText value="#{bean.entity.property}" />
Anda perlu memastikan bahwa Anda telah menyiapkan entitas model sebelumnya dalam suatu @PostConstruct, atau <f:viewAction>metode, atau mungkin add()metode tindakan jika Anda bekerja dengan daftar CRUD dan / atau dialog pada tampilan yang sama.
@Named
@ViewScoped
public class Bean {
private Entity entity; // +getter (setter is not necessary).
@Inject
private EntityService entityService;
@PostConstruct
public void init() {
// In case you're updating an existing entity.
entity = entityService.getById(entityId);
// Or in case you want to create a new entity.
entity = new Entity();
}
// ...
}
Mengenai pentingnya @PostConstruct; melakukan ini dalam konstruktor reguler akan gagal jika Anda menggunakan kerangka kerja manajemen kacang yang menggunakan proxy , seperti CDI. Selalu gunakan @PostConstructuntuk mengaitkan inisialisasi instance kacang terkelola (dan gunakan @PreDestroyuntuk mengait pada penghancuran instance kacang terkelola). Selain itu, di konstruktor Anda belum memiliki akses ke dependensi yang disuntikkan, lihat juga NullPointerException saat mencoba mengakses @Inject bean di konstruktor .
Jika entityIddisediakan melalui <f:viewParam>, Anda harus menggunakan <f:viewAction>sebagai gantinya @PostConstruct. Lihat juga Kapan menggunakan f: viewAction / preRenderView versus PostConstruct?
Anda juga perlu memastikan bahwa Anda mempertahankan non- nullmodel selama postback jika Anda membuatnya hanya dalam add()metode tindakan. Cara termudah adalah menempatkan kacang dalam lingkup tampilan. Lihat juga Bagaimana memilih lingkup kacang yang tepat?
3. Target Tidak Dapat Dicapai, 'null' dikembalikan nol
Ini sebenarnya memiliki penyebab yang sama dengan # 2, hanya implementasi EL (lebih tua) yang digunakan agak buggy dalam menjaga nama properti untuk ditampilkan dalam pesan pengecualian, yang akhirnya salah diekspos sebagai 'nol'. Ini hanya membuat debugging dan memperbaiki sedikit lebih sulit ketika Anda memiliki beberapa properti bersarang seperti itu #{bean.entity.subentity.subsubentity.property}.
Solusinya masih sama: pastikan entitas bersarang yang dimaksud tidak null, di semua tingkatan.
4. Target Tidak Dapat Dicapai, '' 0 '' dikembalikan nol
Ini juga memiliki penyebab yang sama dengan # 2, hanya implementasi EL (lama) yang digunakan adalah buggy dalam merumuskan pesan pengecualian. Ini memperlihatkan hanya ketika Anda menggunakan notasi penjepit []di EL seperti di #{bean.collection[index]}mana #{bean.collection}itu sendiri adalah non-nol, tetapi item pada indeks yang ditentukan tidak ada. Pesan seperti itu kemudian harus ditafsirkan sebagai:
Target Tidak Dapat Dicapai, 'koleksi [0]' dikembalikan nol
Solusinya juga sama dengan # 2: pastikan barang koleksi tersedia.
5. Target Tidak Dapat Dicapai, 'BracketSuffix' kembali nol
Ini sebenarnya memiliki penyebab yang sama dengan # 4, hanya implementasi EL (yang lebih tua) yang digunakan agak buggy dalam menjaga indeks iterasi untuk ditampilkan dalam pesan pengecualian, yang akhirnya salah diekspos sebagai 'BracketSuffix' yang benar-benar karakternya ]. Ini hanya membuat proses debug dan perbaikan sedikit lebih sulit ketika Anda memiliki banyak item dalam koleksi.
Kemungkinan penyebab lain dari javax.el.PropertyNotFoundException: