1. Націлити недосяжно, ідентифікатор 'bean' вирішений до нуля
Це зводиться до того, що саме керований екземпляр біна не міг бути знайдений точно таким ідентифікатором (керованим ім'ям біна) в EL, як це #{bean}.
Визначення причини можна розділити на три етапи:
а. Хто керує квасолею?
б. Яке (за замовчуванням) керована назва квасолі?
c. Де клас підкладки з квасолі?
1а. Хто керує квасолею?
Першим кроком буде перевірка того, яка структура управління квасолею відповідає за керування екземпляром квасолі. Це JSF через @ManagedBean? Або це CDI через @Named? Або це весна через @Component? Чи можете ви переконатись, що ви не змішуєте конкретні примітки щодо управління декількома бобами для того самого класу резервних бобів? Наприклад @Named @Component, або @Named @ManagedBean, або @ManagedBean @Component. Це неправильно. Бін повинен керуватися, щонайменше, однією рамкою управління бобом, і ця структура повинна бути належним чином налаштована. Якщо ви вже не маєте ідеї, що обрати, перейдіть до фасолі фасолі (@ManagedBean) або CDI Beans (@Named)? та Spring JSF інтеграція: як ввести компонент Spring / службу в керований JSF боб?
Якщо JSF керує квасолею @ManagedBean, вам потрібно переконатися в наступному:
faces-config.xmlКоренева декларація сумісна з JSF 2.0. Таким чином, файл XSD і versionобов'язковим , по крайней мере вказати JSF 2.0 або вище і , отже , НЕ 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">
Для JSF 2.1 просто замініть 2_0і 2.0відповідно, 2_1і 2.1відповідно.
Якщо ви користуєтеся JSF 2.2 або новішою версією, переконайтеся, що ви використовуєте xmlns.jcp.orgпростори імен замість java.sun.comусіх місць.
<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">
Для JSF 2.3 просто замініть 2_2і 2.2відповідно, 2_3і 2.3відповідно.
Ви не випадково імпортували javax.annotation.ManagedBeanзамість цього javax.faces.bean.ManagedBean. Будьте уважні за допомогою автоматичного заповнення IDE, Eclipse, як відомо, автоматично запропонував неправильний варіант як перший елемент у списку.
- Ви не
@ManagedBeanзамінили <managed-bean>запис у стилі JSF 1.x у faces-config.xmlтому самому класі резервного боба разом з іншим керованим назвою квасолі. Цей має перевагу над @ManagedBean. Реєстрація керованого квасолі в faces-config.xmlне потрібна, оскільки JSF 2.0, просто видаліть її.
- Ваш клас маршруту виконання чистий і не містить дублікатів JAR-файлів, пов'язаних з JSF API. Переконайтеся, що ви не змішуєте кілька реалізацій JSF (Mojarra та MyFaces). Переконайтеся, що ви не надаєте інший файл JAR API JSF або навіть Java EE API разом з webapp, коли цільовий контейнер вже з’єднує API JSF у вікні. Дивіться також "Встановлення JSF" на нашій сторінці вікі JSF для інструкцій із встановлення JSF. Якщо ви маєте намір оновити контейнер JSF, що постачається з WAR, замість самого контейнера, переконайтесь, що ви доручили цільовому контейнерові використовувати JSF API / impl, що входить у пакет WAR.
- Якщо ви упаковуєте боби з керованою JSF у JAR, то переконайтеся, що JAR має принаймні сумісний JSF 2.0
/META-INF/faces-config.xml. Див. Також Як посилатися на керовані JSF боби, які містяться у файлі JAR?
Якщо ви на самому справі з допомогою юрського JSF 1.x, і ви не можете оновити, то вам необхідно зареєструвати компонент через <managed-bean>в faces-config.xmlзамість @ManagedBean. Не забудьте виправити шлях створення проекту таким чином, щоб у вас більше не було бібліотек JSF 2.x (щоб @ManagedBeanанотація не була заплутано успішно зібрана).
Якщо CDI керує квасолею @Named, вам потрібно переконатися в наступному:
CDI 1.0 (Java EE 6) потребує /WEB-INF/beans.xmlфайлу, щоб включити CDI у WAR. Він може бути порожнім або мати лише такий вміст:
<?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) без будь-якого beans.xml, або порожній beans.xmlфайл, або з вищевказаними сумісними CDI 1.0 beans.xmlповодитимуться так само, як CDI 1.0. Коли є CDI 1.1 сумісний beans.xmlз явним version="1.1", то він за замовчуванням буде реєструвати тільки @Namedбоби з явною КДІ області видимості анотації , такі як @RequestScoped, @ViewScoped, @SessionScoped, @ApplicationScopedі т.д. У разі , якщо ви збираєтеся реєструвати всі боби в якості КДІ керованих компонентів, навіть без явного Об'єм CDI, використовуйте наведений нижче CDI 1.1, сумісний /WEB-INF/beans.xmlіз bean-discovery-mode="all"набором (типовим є 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>
Під час використання CDI 1.1+ з bean-discovery-mode="annotated"(за замовчуванням) переконайтеся, що ви випадково не імпортували область JSF, наприклад javax.faces.bean.RequestScopedзамість області CDI javax.enterprise.context.RequestScoped. Слідкуйте за допомогою автозаповнення IDE.
- Якщо ви використовуєте Mojarra 2.3.0-2.3.2 та CDI 1.1+ з
bean-discovery-mode="annotated"(за замовчуванням), вам потрібно оновити Mojarra до 2.3.3 або новішої версії через помилку . У разі , якщо ви не можете оновити, то вам потрібно або набір bean-discovery-mode="all"в beans.xml, або поставити JSF 2.3 конкретну @FacesConfigанотацію довільного класу в WAR ( як правило , свого роду додатком запуску клас область дії).
- Контейнери, що не містять Java EE, такі як Tomcat та Jetty, не постачаються з пакетом CDI. Встановити його потрібно вручну. Це трохи більше роботи, ніж просто додавання бібліотечних JAR (s). Що стосується Tomcat, переконайтеся, що дотримуєтесь інструкцій у цій відповіді: Як встановити та використовувати CDI на Tomcat?
- Ваш клас маршруту виконання чистий і не містить копій JAR, пов'язаних з CDI API. Переконайтеся, що ви не змішуєте кілька реалізацій CDI (Weld, OpenWebBeans тощо). Переконайтеся, що ви не надаєте інший CDI-файл або навіть файл Java JE API JAR разом з webapp, коли цільовий контейнер вже з’єднує CDI API у вікні.
Якщо ви упаковуєте боби, керовані CDI, для переглядів JSF в JAR, то переконайтеся, що JAR має принаймні дійсний /META-INF/beans.xml(який може залишатися порожнім).
У випадку, якщо саме Весна управляє квасолею @Component, вам потрібно переконатися в наступному:
Весна встановлюється та інтегрується відповідно до її документації . Що важливо, вам потрібно принаймні мати це у web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
І це в faces-config.xml:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
(вище все, що я знаю щодо Spring - я не роблю Spring - не соромтесь редагувати / коментувати інші ймовірні причини, пов'язані з Spring; наприклад, деякі проблеми, пов’язані з конфігурацією XML)
У разі , якщо це компонент ретранслятора , який управляє (вкладеним) бобом через його varатрибут (наприклад <h:dataTable var="item">, <ui:repeat var="item">, <p:tabView var="item">і т.д.) , і ви на самому справі отримали «Target недосяжна, ідентифікатор" елемент "вирішив нуль», то вам необхідно переконатися в наступному :
На #{item}посилання не bindingвказано жодного дочірнього компонента. Це неправильно, оскільки bindingатрибут запускається під час збирання перегляду, а не під час візуалізації перегляду. Більше того, у дереві компонентів фізично є лише один компонент, який просто повторно використовується під час кожного раунду ітерації. Іншими словами, ви насправді повинні використовувати binding="#{bean.component}"замість цього binding="#{item.component}". Але набагато краще - позбутися бінінгу компонентів взагалі та дослідити / запропонувати належний підхід до проблеми, яку ви думали вирішити таким чином. Див. Також Як працює атрибут "прив'язки" у JSF? Коли і як його слід застосовувати?
1б. Яке (за замовчуванням) керована назва квасолі?
Другим кроком буде перевірка зареєстрованого керованого імені квасолі. Умови використання JSF та Spring відповідають стандартам JavaBeans, тоді як CDI має винятки залежно від імпульсу / версії CDI.
FooBeanКлас підтримки бобу , як показано нижче,
@Named
public class FooBean {}
буде у всіх структурах управління бобом мати керовану назву бобів за замовчуванням #{fooBean}відповідно до специфікації JavaBeans.
FOOBeanКлас підтримки бобу , як показано нижче,
@Named
public class FOOBean {}
чиє некваліфіковане ім'я класу починається щонайменше з двох великих літер, у JSF та Spring буде мати за замовчуванням кероване ім'я квасолі саме некваліфікованого імені класу #{FOOBean}, також відповідають специфікації JavaBeans. Що стосується CDI, це також у версіях Weld, випущених до червня 2015 року, але не у версіях Weld, випущених після червня 2015 року (2.2.14 / 2.3.0.B1 / 3.0.0.A9), а також у OpenWebBeans через контроль в КДІ специфікації . У цих версіях Weld і в усіх версіях OWB це лише з першим символом з нижнього регістру #{fOOBean}.
Якщо ви чітко вказали ім’я керованої квасолі, fooяк нижче,
@Named("foo")
public class FooBean {}
або еквівалентно с @ManagedBean(name="foo") або @Component("foo"), тоді він буде доступний лише #{foo}тим самим і, отже, не самим #{fooBean}.
1с. Де клас підкладки з квасолі?
Третім кроком буде подвійна перевірка, якщо клас резервного боба знаходиться у потрібному місці у вбудованому та розгорнутому файлі WAR. Переконайтесь, що ви належним чином виконали повний чистий, відновити, переустановити та перезапустити проект та сервер у випадку, якщо ви насправді були зайняті написанням коду та нетерплячим натисканням клавіші F5 у браузері. Якщо все-таки даремно, дозвольте системі збирання створити файл WAR, який ви потім витягнете та перевірите інструментом ZIP. Скомпільований .classфайл класу backing bean повинен містити структуру пакунків у /WEB-INF/classes. Або, коли він упакований як частина модуля JAR, JAR, що містить скомпільований .classфайл, повинен міститись /WEB-INF/libі, таким чином, не бути, наприклад, EAR /libабо в іншому місці.
Якщо ви використовуєте Eclipse, переконайтесь, що клас резервного боба є, srcа отже, ні WebContent , і переконайтесь, що Project> Build Automatically включено. Якщо ви використовуєте Maven, переконайтеся, що клас клавіатури підтримується src/main/javaі, отже, не знаходиться в src/main/resourcesабо src/main/webapp.
Якщо ви упаковуєте веб-додаток як частину EAR за допомогою EJB + WAR (s), то вам потрібно переконатися, що класи підкладки в модулі WAR і, отже, не в модулі EAR, ані в модулі EJB. Діловий рівень (EJB) повинен бути без будь-яких артефактів, пов’язаних із веб-рівнем (WAR), так що діловий рівень може бути повторно використаний у кількох різних ярусах (JSF, JAX-RS, JSP / Servlet тощо).
2. Націлити недосяжно, "сутність" повернула нуль
Це зводиться до цього вкладеного властивості, entityяк у #{bean.entity.property}поверненому null. Зазвичай це виявляється лише тоді, коли JSF потрібно встановити значення для propertyвхідного компонента, як показано нижче, а #{bean.entity}фактично поверненогоnull .
<h:inputText value="#{bean.entity.property}" />
Ви повинні переконатися , що ви підготували модель об'єкт заздалегідь в @PostConstruct, або <f:viewAction>метод, або , можливо, add()метод дії в разі , якщо ви працюєте зі списками CRUD і / або діалогові вікна на ту ж точку зору.
@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();
}
// ...
}
Щодо важливості @PostConstruct; зробити це в звичайному конструкторі не вдасться, якщо ви використовуєте структуру управління bean, яка використовує проксі , такі як CDI. Завжди використовуйте @PostConstructдля підключення керованої ініціалізації екземпляра біна (і використовуйте @PreDestroyдля підключення до керованого знищення екземпляра біна). Крім того, у конструкторі ви б ще не мали доступу до будь-яких введених залежностей, див. Також NullPointerException, намагаючись отримати доступ до @Inject bean в конструкторі .
У випадку, якщо entityIdпостачається через <f:viewParam>, вам потрібно буде використовувати <f:viewAction>замість @PostConstruct. Дивіться також Коли використовувати f: viewAction / preRenderView проти PostConstruct?
Вам також потрібно переконатися, що ви зберігаєте немодель nullпід час розсилки, якщо ви створюєте її лише add()методом дії. Найпростіше було б поставити квасоля в поле зору. Див. Також Як правильно вибрати область бобів?
3. Націлити недосяжно, "null" повернуто null
Це насправді та сама причина, що і №2, лише використовувана (старіша) реалізація EL є дещо помилковою у збереженні імені властивості для відображення у повідомленні про виключення, яке в кінцевому підсумку неправильно виставляється як "null". Це лише налагоджує налагодження та виправляє трохи важче, якщо у вас є такі вкладені властивості, як це #{bean.entity.subentity.subsubentity.property}.
Рішення все одно - переконайтесь, що відповідного вкладеного об'єкта немає nullна всіх рівнях.
4. Націлити недосяжно, "0" повернуто нулем
Це також є тією ж причиною, що і №2, лише (використовувана) старша реалізація EL є помилковою у формулюванні повідомлення про виключення. Це виявляється лише тоді, коли ви використовуєте позначення дужок []в EL, як #{bean.collection[index]}там, де #{bean.collection}сам по собі є недійсним, але елемент у вказаному індексі не існує. Тоді таке повідомлення слід інтерпретувати як:
Націлити недосяжно, "колекція [0]" повернула нуль
Рішення також таке ж, як №2: переконайтеся, що предмет колекції доступний.
5. Націлити недосяжно, "BracketSuffix" повернув нуль
Це насправді та сама причина, що і №4, лише використовувана (старіша) реалізація EL дещо помиляється при збереженні індексу ітерації для відображення у повідомленні про виключення, яке в кінцевому підсумку неправильно виявляється як "BracketSuffix", що є насправді символом ]. Це лише робить налагодження і виправляти трохи складніше, коли у колекції є кілька елементів.
Інші можливі причини javax.el.PropertyNotFoundException: