1. Цель недостижима, идентификатор bean преобразован в нуль
Это сводится к тому, что сам экземпляр управляемого компонента не может быть найден точно по этому идентификатору (имени управляемого компонента) в EL, например #{bean}
.
Выявление причины можно разбить на три этапа:
а. Кто управляет бином?
б. Какое имя (по умолчанию) управляемого bean-компонента?
с. Где бин-класс поддержки?
1a. Кто управляет бином?
Первым шагом будет проверка того, какая структура управления компонентами отвечает за управление экземпляром компонента. Это JSF через @ManagedBean
? Или это через CDI@Named
? Или это Spring через @Component
? Можете ли вы убедиться, что вы не смешиваете несколько аннотаций, специфичных для инфраструктуры управления компонентами, в одном и том же классе вспомогательного компонента? Например @Named @Component
, или @Named @ManagedBean
, или @ManagedBean @Component
. Это не верно. Компонент должен управляться не более чем одной структурой управления компонентом, и эта структура должна быть правильно настроена. Если вы уже не знаете, что выбрать, перейдите к Backing beans (@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
стиле JSF 1.x <managed-bean>
в faces-config.xml
том же самом классе вспомогательного компонента вместе с другим именем управляемого компонента. Этот будет иметь приоритет перед @ManagedBean
. faces-config.xml
Начиная с JSF 2.0 регистрировать управляемый компонент не требуется, просто удалите его.
- Путь к классам среды выполнения чистый и не содержит дубликатов в JAR-файлах, связанных с JSF API. Убедитесь, что вы не смешиваете несколько реализаций JSF (Mojarra и MyFaces). Убедитесь, что вы не предоставляете другой JSF-файл или даже JAR-файл Java EE API вместе с веб-приложением, когда целевой контейнер уже включает в себя JSF API из коробки. См. Также раздел «Установка JSF» на нашей вики-странице JSF для получения инструкций по установке JSF. Если вы собираетесь обновить JSF, связанный с контейнером, с WAR, а не в самом контейнере, убедитесь, что вы проинструктировали целевой контейнер использовать связанный с WAR JSF API / impl.
- Если вы упаковываете управляемые компоненты JSF в JAR, убедитесь, что JAR имеет как минимум JSF 2.0 совместимый
/META-INF/faces-config.xml
. См. Также Как ссылаться на управляемые компоненты JSF, которые содержатся в файле JAR?
Если вы на самом деле используете jurassic JSF 1.x и не можете выполнить обновление, вам необходимо зарегистрировать компонент через <managed-bean>
in faces-config.xml
вместо @ManagedBean
. Не забудьте исправить путь сборки проекта как таковой, чтобы у вас больше не было библиотек JSF 2.x (чтобы @ManagedBean
аннотация не могла успешно компилироваться).
Если это CDI, который управляет bean-компонентом через @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"
set (по умолчанию 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 (ов). Для Tomcat убедитесь, что вы следуете инструкциям в этом ответе: Как установить и использовать CDI на Tomcat?
- Путь к классам среды выполнения чистый и не содержит дубликатов в JAR-файлах, связанных с API CDI. Убедитесь, что вы не смешиваете несколько реализаций CDI (Weld, OpenWebBeans и т. Д.). Убедитесь, что вы не предоставляете другой файл CDI или даже JAR-файл Java EE API вместе с webapp, если целевой контейнер уже включает в себя CDI API из коробки.
Если вы упаковываете bean-компоненты, управляемые CDI, для представлений JSF в JAR, убедитесь, что JAR имеет по крайней мере действительный /META-INF/beans.xml
(который можно оставить пустым).
Если это Spring, которая управляет bean-компонентом через @Component
, вам необходимо убедиться в следующем:
Spring устанавливается и интегрируется в соответствии с его документацией . Что немаловажно, вам нужно как минимум это иметь 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
attribtue любого дочернего компонента. Это неверно, поскольку binding
атрибут запускается во время построения представления, а не во время визуализации представления. Более того, физически в дереве компонентов есть только один компонент, который просто повторно используется во время каждой итерации. Другими словами, вы действительно должны использовать binding="#{bean.component}"
вместо binding="#{item.component}"
. Но гораздо лучше вообще избавиться от связывания компонентов с bean-компонентом и изучить / задать вопрос о подходящем подходе к проблеме, которую вы думали решить таким образом. См. Также Как работает атрибут «привязка» в JSF? Когда и как его использовать?
1б. Какое имя (по умолчанию) управляемого bean-компонента?
Вторым шагом будет проверка имени зарегистрированного управляемого компонента. Соглашения об использовании 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 из-за недосмотра в CDI spec . В этих версиях Weld и во всех версиях OWB только первый символ в нижнем регистре #{fOOBean}
.
Если вы явно указали имя управляемого bean-компонента, foo
как показано ниже,
@Named("foo")
public class FooBean {}
или, что эквивалентно с @ManagedBean(name="foo")
или @Component("foo")
, тогда он будет доступен только от, #{foo}
а не от #{fooBean}
.
1c. Где бин-класс поддержки?
Третий шаг - это двойная проверка, находится ли поддерживающий класс bean-компонента в нужном месте в созданном и развернутом WAR-файле. Убедитесь, что вы правильно выполнили полную очистку, перестройку, повторное развертывание и перезапуск проекта и сервера, на случай, если вы действительно были заняты написанием кода и нетерпеливым нажатием F5 в браузере. Если все еще напрасно, позвольте системе сборки создать файл WAR, который затем извлеките и изучите с помощью инструмента ZIP. Скомпилированный .class
файл класса вспомогательного компонента должен находиться в его структуре пакета в формате /WEB-INF/classes
. Или, когда он упакован как часть модуля JAR, JAR, содержащий скомпилированный .class
файл, должен находиться в нем, /WEB-INF/lib
а не, например, в EAR /lib
или в другом месте.
Если вы используете Eclipse, убедитесь, что класс вспомогательного bean-компонента включен, src
а значит, нет WebContent
, и убедитесь, что включен Project> Build Automatically . Если вы используете Maven, убедитесь, что поддерживающий класс bean-компонента находится внутри, src/main/java
а не в src/main/resources
или src/main/webapp
.
Если вы упаковываете веб-приложение как часть EAR с EJB + WAR (s), то вам необходимо убедиться, что классы вспомогательных компонентов находятся в модуле WAR, а, следовательно, не в модуле EAR или модуле EJB. Бизнес-уровень (EJB) должен быть свободен от каких-либо артефактов, связанных с веб-уровнем (WAR), чтобы бизнес-уровень можно было повторно использовать на нескольких разных веб-уровнях (JSF, JAX-RS, JSP / Servlet и т. Д.).
2. Target Unreachable, 'entity' вернул null
Это сводится к тому , что вложенной собственности 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
; выполнение этого в обычном конструкторе приведет к сбою, если вы используете структуру управления компонентами, которая использует прокси , такие как CDI. Всегда используйте @PostConstruct
для подключения к инициализации экземпляра управляемого компонента (и @PreDestroy
для подключения к уничтожению экземпляра управляемого компонента). Кроме того, в конструкторе у вас еще не будет доступа ни к каким внедренным зависимостям, см. Также исключение NullPointerException при попытке доступа к @Inject bean в конструкторе .
В случае, если entityId
поставляется через <f:viewParam>
, вам нужно будет использовать <f:viewAction>
вместо @PostConstruct
. См. Также Когда использовать f: viewAction / preRenderView по сравнению с PostConstruct?
Вам также необходимо убедиться, что вы сохраняете немодель null
во время обратной передачи, если вы создаете ее только в add()
методе действия. Проще всего было бы поместить компонент в область просмотра. См. Также Как выбрать правильную область применения фасоли?
3. Target Unreachable, "null" вернул null.
Фактически это имеет ту же причину, что и № 2, только используемая (более старая) реализация EL несколько ошибочна в сохранении имени свойства для отображения в сообщении об исключении, которое в конечном итоге неправильно отображается как «null». Это только немного усложняет отладку и исправление, когда у вас довольно много таких вложенных свойств #{bean.entity.subentity.subsubentity.property}
.
Решение остается тем же: убедитесь, что рассматриваемая вложенная сущность отсутствует null
на всех уровнях.
4. Target Unreachable, «0» вернул null.
Это также имеет ту же причину, что и №2, только используемая (более старая) реализация EL содержит ошибки при формулировании сообщения об исключении. Это проявляется только тогда, когда вы используете нотацию фигурных скобок []
в EL, например, #{bean.collection[index]}
когда #{bean.collection}
сам по себе не равен нулю, но элемент по указанному индексу не существует. Такое сообщение следует интерпретировать как:
Target Unreachable, 'collection [0]' вернул null
Решение также такое же, как и №2: убедитесь, что предмет коллекции доступен.
5. Target Unreachable, BracketSuffix вернул null.
Фактически это имеет ту же причину, что и # 4, только используемая (более старая) реализация EL несколько ошибочна в сохранении индекса итерации для отображения в сообщении об исключении, которое в конечном итоге неправильно отображается как 'BracketSuffix', что на самом деле является символом ]
. Это только немного усложняет отладку и исправление, когда в коллекции несколько элементов.
Другие возможные причины javax.el.PropertyNotFoundException
: