Идентификация и решение javax.el.PropertyNotFoundException: Target Unreachable

При попытке ссылаться на управляемый bean в EL, как и на #{bean.entity.property}, иногда возникает исключение javax.el.PropertyNotFoundException: Target Unreachable, обычно когда свойство bean должно быть установлено или когда действие bean для вызова.

Кажется, есть пять различных видов сообщений:

Что они все означают? Как они вызваны и как их решить?

Ответ 1

1. Цель недостижима, идентификатор "bean" преобразован в ноль

Это сводится к тому, что сам экземпляр управляемого компонента не может быть найден именно этим идентификатором (именем управляемого компонента) в EL, как, например, #{bean}.

Выявление причины можно разбить на три этапа:

а. Кто управляет бобом?
б. Какое имя (по умолчанию) управляемого бина?
с. Где класс бобов?

1a. Кто управляет бобом?

Первым шагом будет проверка того, какая структура управления компонентом отвечает за управление экземпляром компонента. Это JSF через @ManagedBean? Или это CDI через @Named? Или это spring через @Component? Можете ли вы убедиться, что вы не смешиваете несколько аннотаций, специфичных для структуры управления компонентами, в одном и том же классе базовых компонентов? Например, @Named @Component или @Named @ManagedBean или @ManagedBean @Component. Это не верно. Бин должен управляться не более чем одной структурой управления бином, и эта структура должна быть правильно настроена. Если вы уже не знаете, какой из них выбрать, перейдите к разделу "Бэк-бины" (@ManagedBean) или CDI-бины (@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 в @ManagedBean faces-config.xml в том же классе @ManagedBean компонента вместе с другим именем управляемого компонента. Этот будет иметь приоритет над @ManagedBean. faces-config.xml с JSF 2.0, регистрация управляемого bean-компонента faces-config.xml не требуется, просто удалите его.
  • Ваш путь к классу во время выполнения является чистым и не содержит дубликатов в JAR файлах, связанных с JSF API. Убедитесь, что вы не смешиваете несколько реализаций JSF (Mojarra и MyFaces). Убедитесь, что вы не предоставляете другой JSF файл или даже JAR файл Java EE API вместе с веб-приложением, когда целевой контейнер уже включает JSF API из коробки. См. Также раздел "Установка JSF" нашей вики-страницы JSF для получения инструкций по установке JSF. В случае, если вы собираетесь обновить JSF, включенную в контейнер, с WAR, а не в самом контейнере, убедитесь, что вы указали целевому контейнеру использовать JSF API в комплекте с WAR/impl.
  • Если вы упаковываете управляемые компоненты JSF в JAR файл, убедитесь, что JAR- /META-INF/faces-config.xml имеет по крайней мере совместимый с JSF 2.0 /META-INF/faces-config.xml. См. Также Как ссылаться на управляемые bean-компоненты JSF, которые представлены в файле JAR?
  • Если вы на самом деле используете Jurassic JSF 1.x и не можете выполнить обновление, тогда вам нужно зарегистрировать bean-компонент с помощью <managed-bean> в @ManagedBean faces-config.xml вместо @ManagedBean. Не забудьте исправить путь сборки проекта таким образом, чтобы у вас больше не было библиотек JSF 2.x (чтобы аннотация @ManagedBean не @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. Если существует beans.xml совместимый с CDI 1.1, с явной version="1.1", то по умолчанию он будет регистрировать только @Named с явной аннотацией области действия CDI, такой как @RequestScoped, @ViewScoped, @SessionScoped, @ApplicationScoped и т.д. Если вы собираетесь зарегистрировать все bean-компоненты как управляемые CDI-компоненты, даже те, которые не имеют явной области действия 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, либо поместить специальную аннотацию @FacesConfig JSF 2.3 в произвольный класс в WAR (обычно это какой-то класс запуска приложения.
  • non- Контейнеры Java EE, такие как Tomcat и Jetty, не поставляются в комплекте с CDI. Вам необходимо установить его вручную. Это немного больше работы, чем просто добавление библиотеки JAR. Для Tomcat обязательно следуйте инструкциям в этом ответе: Как установить и использовать CDI на Tomcat?
  • Ваш путь к классу во время выполнения является чистым и не содержит дубликатов в JAR файлах, связанных с API CDI. Убедитесь, что вы не смешиваете несколько реализаций CDI (Weld, OpenWebBeans и т.д.). Убедитесь, что вы не предоставили другой веб-приложение CDI или даже JAR файл API Java EE, когда целевой контейнер уже связывает CDI API из коробки.
  • Если вы упаковываете управляемые компоненты CDI для представлений JSF в JAR, убедитесь, что в JAR есть как минимум действительный /META-INF/beans.xml (который можно оставить пустым).


В случае если Spring управляет компонентом через @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)


В случае, если это компонент ретранслятора, который управляет (вложенным) bean-компонентом через его атрибут var (например, <h:dataTable var="item">, <ui:repeat var="item">, <p:tabView var="item"> и т.д.) и вы фактически получили "Target Unreachable, идентификатор" item "разрешен до нуля", тогда вам необходимо убедиться в следующем:

  • #{item} Item #{item} не упоминается в binding атрибута любого дочернего компонента. Это неверно, поскольку атрибут binding выполняется во время построения представления, а не во время отображения представления. Более того, физически в дереве компонентов есть только один компонент, который просто повторно используется во время каждого цикла итерации. Другими словами, вы должны использовать binding="#{bean.component}" вместо binding="#{item.component}". Но гораздо лучше избавиться от объединения компонентов в бин и исследовать/задать правильный подход к проблеме, которую вы решили решить таким образом. Смотрите также Как работает атрибут 'binding' в JSF? Когда и как его следует использовать?


1б. Какое имя (по умолчанию) управляемого бина?

Вторым шагом будет проверка зарегистрированного имени управляемого бина. Соглашения об использовании JSF и Spring соответствуют спецификации JavaBeans, в то время как CDI имеет исключения в зависимости от impl/версии CDI.

  • FooBean бобов FooBean ниже,

    @Named
    public class FooBean {}
    

    будет во всех средах управления bean-компонентами иметь имя управляемого bean-компонента по умолчанию #{fooBean} согласно спецификации JavaBeans.

  • FooBean бобов 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 спец. В этих версиях Weld и во всех версиях OWB это только первый символ в нижнем регистре #{fOOBean}.

  • Если вы явно указали имя управляемого компонента foo как foo ниже,

    @Named("foo")
    public class FooBean {}
    

    или эквивалентно с @ManagedBean(name="foo") или @Component("foo"), тогда он будет доступен только #{foo} и, следовательно, не #{fooBean}.


1c. Где класс бобов?

Третий шаг - двойная проверка, если класс компонента поддержки находится в нужном месте во встроенном и развернутом файле WAR. Убедитесь, что вы правильно выполнили полную очистку, перестроение, повторное развертывание и перезапуск проекта и сервера, если вы действительно заняты написанием кода и нетерпеливым нажатием клавиши F5 в браузере. Если все еще напрасно, позвольте системе сборки создать файл WAR, который вы затем извлекаете и проверяете с помощью инструмента ZIP. Скомпилированный файл .class класса базового компонента должен находиться в его структуре пакета в /WEB-INF/classes. Или, когда он упакован как часть модуля JAR, JAR, содержащий скомпилированный файл .class должен находиться в /WEB-INF/lib и, следовательно, не может быть, например, EAR /lib или где-либо еще.

Если вы используете Eclipse, убедитесь, что класс bean-компонента находится в src а не в WebContent, и убедитесь, что Project> Build Automatics включен. Если вы используете Maven, убедитесь, что класс bean-компонента находится в src/main/java и, следовательно, не в src/main/resources или src/main/webapp.

Если вы упаковываете веб-приложение как часть EAR с EJB + WAR, вам необходимо убедиться, что классы компонентов поддержки находятся в модуле 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, @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 для @PreDestroy к уничтожению экземпляра управляемого компонента). Кроме того, в конструкторе у вас еще не будет доступа ни к каким внедренным зависимостям, смотрите также NullPointerException при попытке получить доступ к компоненту @Inject в конструкторе.

В случае, если entityId предоставляется через <f:viewParam>, вам нужно будет использовать <f:viewAction> вместо @PostConstruct. См. Также Когда использовать f: viewAction/preRenderView по сравнению с PostConstruct?

Вам также необходимо убедиться, что вы сохраняете null модель non- во время обратной передачи на случай, если вы создадите ее только с помощью метода действия add(). Проще всего было бы поместить боб в область видимости. Смотрите также Как правильно выбрать сферу применения бобов?


3. Цель недостижима, "ноль" вернул ноль

Фактически это имеет ту же причину, что и # 2, только используемая (более старая) реализация EL несколько ошибочна в сохранении имени свойства для отображения в сообщении об исключении, которое в конечном итоге неверно отображается как 'null'. Это только усложняет отладку и исправление, когда у вас есть несколько вложенных свойств, таких как #{bean.entity.subentity.subsubentity.property}.

Решение остается тем же: убедитесь, что рассматриваемая вложенная сущность не равна null на всех уровнях.


4. Цель недостижима, '' 0 '' вернул ноль

Это также имеет ту же причину, что и # 2, только используемая (более старая) реализация EL содержит ошибки при формулировании сообщения об исключении. Это доступно только в том случае, если вы используете скобочную нотацию [] в EL, как в #{bean.collection[index]} где сама #{bean.collection} равна non- null, но элемент по указанному индексу не существует, Такое сообщение должно быть интерпретировано как:

Цель недостижима, 'collection [0]' возвратила ноль

Решение также совпадает С# 2: убедитесь, что элемент коллекции доступен.


5. Цель недостижима, "BracketSuffix" вернул ноль

Фактически это имеет ту же причину, что и # 4, только используемая (более старая) реализация EL несколько ошибочна при сохранении индекса итерации для отображения в сообщении об исключении, которое в конечном итоге неверно отображается как "BracketSuffix", который на самом деле является символом ]. Это только усложняет отладку и исправление, когда в коллекции несколько элементов.


Другие возможные причины javax.el.PropertyNotFoundException:

Ответ 2

Для тех, кто все еще застрял...

Используя NetBeans 8.1 и GlassFish 4.1 с CDI, по какой-то причине я имел эту проблему только локально, а не на удаленном сервере. Что сделал трюк:

- > используя javaee-web-api 7.0 вместо стандартной версии pom, предоставляемой NetBeans, которая является javaee-web-api 6.0, поэтому:

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
    <type>jar</type>
</dependency>

- > загрузите этот javaee-web-api-7.0.jar как lib на сервер (папка lib в папке domain1) и перезапустите сервер.

Ответ 3

Я решил поделиться своим сообщением об этой ошибке после ее разрешения.

Прежде всего, решения BalusC следует воспринимать всерьез, но в NetBeans есть еще одна вероятная проблема, особенно для создания Enterprise Application Project (EAR) с использованием Maven.

Netbeans генерирует родительский POM файл, проект EAR, проект EJB и проект WAR, Все остальное в моем проекте было прекрасным, и я почти предположил, что проблема связана с ошибкой, вероятно, с GlassFish 4.0 (мне пришлось установить и подключить ее к Netbeans), потому что GlassFish 4.1 имеет ошибку Weld CDI, которая делает встроенный GlassFish 4.1 в Netbeans 8.0. 2 неприменимо, кроме как через патч.

Решение:

Чтобы разрешить "Недоступную цель, идентификатор bean" разрешен для null " ошибка -

I Щелкните правой кнопкой мыши родительский проект POM и выберите Свойства. Появится диалоговое окно "Свойства проекта", нажмите "Источники", вы будете удивлены, увидев, что " Источник/Бинарный формат" установлен на 1.5 и " Кодировка", установленном на Windows 1250. Измените " исходный/двоичный формат" на 1.6 0r 1.7, в зависимости от того, что вы хотите сделать совместимым с вашим CDI и " Encoding" в UTF-8.

Сделайте то же самое для всех других подпроектов (EAR, EJB, WAR), если они еще не совместимы. Запустите проект, и вы не получите эту ошибку еще раз.

Я надеюсь, что это поможет кому-то, имеющему подобную ошибку.

Ответ 4

Я решил поделиться своим решением, потому что, хотя многие ответы, представленные здесь, были полезны, у меня все еще была эта проблема. В моем случае я использую JSF 2.3, jdk10, jee8, cdi 2.0 для моего нового проекта, и я запустил свое приложение на wildfly 12, запустив сервер с параметром standalone.sh -Dee8.preview.mode = true, как рекомендовано для wildfly Веб-сайт. Проблема с "бином разрешен к нулю" исчезла после загрузки wildfly 13. Загрузка точно такой же войны в wildfly 13 заставила все это работать.

Ответ 5

В моем случае я совершил ошибку заклинания в @Named ( "beanName" ), он предположил быть "beanName", но я написал, например, "beanNam".

Ответ 6

Я использую wildfly 10 для контейнера javaee. Я столкнулся с проблемой "Целевая недоступность", сущность "null". Благодарим за предложения BalusC, но моя проблема из объясняемых решений. Случайно используя "import com.sun.istack.logging.Logger"; вместо "import org.jboss.logging.Logger;" вызванный CDI реализовал JSF EL. Надеюсь, что это поможет улучшить решение.

Ответ 7

У меня была та же проблема. Решение оказалось намного проще. Похоже, что datatable хочет метод в форме getter, то есть getSomeMethod(), а не только someMethod(). В моем случае в datatable я вызывал findResults. Я изменил метод в моей поддержке bean на getFindResults(), и он сработал.

CommandButton работал с поиском без get, который служил для того, чтобы сделать его более запутанным.

Ответ 8

Что касается № 2, в моем случае он волшебным образом ожил после замены

<body>

пометить с

<h:body>

После того, как я выполнил несколько (проще, если честно) проектов JSF, я не мог вспомнить, что делал что-то другое, настраивая его сейчас, и я впервые получил такую ошибку. Я делал очень простую страницу входа (имя пользователя, пароль, пользовательский Бин...) и настраивал все как обычно. Единственное различие, которое я заметил, - вышеупомянутые признаки. Может быть, кто-то найдет это полезным.

Ответ 9

Работа с JSF в старом стиле. Вы должны определить управляемый bean в beans -config.xml (находится в папке WEB-INF) и сделайте ссылку на него в файле web.xml, таким образом:

beans -config.xml

<managed-bean>
  <managed-bean-name>"the name by wich your backing bean will be referenced"</managed-bean-name>
  <managed-bean-class>"your backing bean fully qualified class name"</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>    
</managed-bean>

(Я пытался использовать другие области, но...)

web.xml

<context-param>
  <param-name>javax.faces.CONFIG_FILES</param-name>
  <param-value>"/WEB-INF/beans-config.xml</param-value>
</context-param>

Ответ 10

Еще одна подсказка: Я использовал JSF и добавил зависимости mvn:                  com.sun.faces           JSF-апи           2.2.11       

    <dependency>
        <groupId>com.sun.faces</groupId>
        <artifactId>jsf-impl</artifactId>
        <version>2.2.11</version>
    </dependency>

Затем я попытался изменить на Primefaces и добавить зависимость между ними:

<dependency>
    <groupId>org.primefaces</groupId>
    <artifactId>primefaces</artifactId>
    <version>6.0</version>
</dependency>

Я изменил свой xhtml с h: на p:, добавив xmlns: p = "http://primefaces.org/ui в шаблон. Только с JSF proyect работал нормально, и управляемая игра была достигнута нормально. Когда я добавляю Primefaces, я получаю недостижимый объект (javax.el.propertynotfoundexception). Проблема заключалась в том, что JSF генерировал ManagedBean, а не Primefaces, и я задавал простые объекты для объекта. Мне пришлось удалить jsf-impl из моего .pom, очистить и установить proyect. С этого момента все шло хорошо. Надеюсь, что это поможет.

Ответ 11

EL интерпретирует $ {bean.propretyName} как описано - propertyName становится getPropertyName() при условии, что вы используете явные или неявные методы генерации getter/setters

Вы можете переопределить это поведение, явно указав имя как функцию: $ {bean.methodName()} Это вызывает метод функции Name() напрямую без изменений.

Не всегда верно, что ваши средства доступа называются "получить...".