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
: