首页 文章

识别并解决javax.el.PropertyNotFoundException:Target Unreachable

提问于
浏览
103

当试图在EL中引用托管bean时,有时会抛出 javax.el.PropertyNotFoundException: Target Unreachable 异常,通常是在设置bean属性时,或者要调用bean动作时 .

似乎有五种不同的消息:

这些都意味着什么?它们是如何引起的,它们应该如何解决?

10 回答

  • -1

    对于那些仍然被卡住的人......

    将NetBeans 8.1和GlassFish 4.1与CDI一起使用,出于某种原因我只在本地使用此问题,而不是在远程服务器上 . 诀窍是什么:

    • 使用javaee-web-api 7.0而不是NetBeans提供的默认pom版本,即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上传到服务器(domain1文件夹中的lib文件夹)并重新启动服务器 .

  • 0

    我决定分享我的解决方案,因为虽然这里提供的许多答案都有帮助,但我仍然遇到了这个问题 . 在我的情况下,我使用JSF 2.3,jdk10,jee8,cdi 2.0作为我的新项目,我在wildfly 12上运行我的应用程序,启动服务器参数standalone.sh -Dee8.preview.mode = true,如wildfly网站上的建议 . 下载wildfly 13后,“bean解析为null”的问题消失了 . 将完全相同的战争上传至wildfly 13使其全部工作 .

  • -1

    另一条线索:我使用的是JSF,并添加了mvn依赖项:com.sun.faces jsf-api 2.2.11

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

    然后,我尝试更改为Primefaces,并添加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运行正常,并且托管bean已达到正常 . 当我添加Primefaces时我得到了无法访问的对象(javax.el.propertynotfoundexception) . 问题是JSF正在生成ManagedBean,而不是Primefaces,我正在询问对象的primefaces . 我不得不从我的.pom中删除jsf-impl,清理和安装proyect . 从这一点开始一切顺利 . 希望有所帮助 .

  • 195

    在我的情况下,我在@Named(“beanName”)中犯了一个拼写错误,它被认为是“beanName”,但我写了“beanNam”,例如 .

  • 0

    使用旧样式的JSF您必须在 beans-config.xml 文件(位于WEB-INF文件夹中)中定义托管bean,并在 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>
    
  • -2

    EL如前所述解释$ - 假设您使用生成getter / setter的显式或隐式方法,propertyName变为getPropertyName()

    您可以通过将名称显式标识为函数来覆盖此行为:$ {bean.methodName()}这直接调用函数方法Name()而不进行修改 .

    您的访问者被命名为“get ...”并不总是如此 .

  • 2

    我有同样的问题 . 结果证明解决方案要简单得多 . 似乎数据表需要getter形式的方法,即getSomeMethod(),而不仅仅是someMethod() . 在我的数据表中,我调用了findResults . 我将我的支持bean中的方法更改为getFindResults()并且它工作正常 .

    一个commandButton工作找不到get,这使得它只会让人感到困惑 .

  • 0

    在我自己解决之后,我决定分享我对这个错误的发现 .

    首先,应该认真对待BalusC解决方案,但是Netbeans还有另一个可能的问题,特别是在使用Maven构建_479569时 .

    Netbeans生成 parent POM fileEAR projectEJB projectWAR project . 我项目中的其他所有内容都很好,我几乎认为这个问题可能是GlassFish 4.0中的一个错误(我必须安装并将其插入Netbeans),因为GlassFish 4.1有一个Weld CDI错误,它在Netbeans 8.0中嵌入了GlassFish 4.1 . 2除了通过补丁之外无法使用 .

    Solution:

    要解决 "Target Unreachable, identifier 'bean' resolved to null" 错误 -

    我右键单击父POM项目,然后选择 Properties . 出现项目属性对话框,单击"Sources",您会惊讶地看到“ Source/Binary Format " set to 1.5 and " Encoding " set to Windows 1250. Change the " Source/Binary Format " to 1.6 0r 1.7, whichever you prefer to make your project CDI compliant, and " Encoding ”到UTF-8 .

    对所有其他子项目(EAR,EJB,WAR)执行相同操作(如果它们尚不可分隔) . 运行您的项目,您将不会再次收到该错误 .

    我希望这可以帮助那些有类似错误的人 .

  • 6

    1.目标无法访问,标识符'bean'已解析为null

    这归结为托管bean实例本身无法通过EL中的标识符(托管bean名称)找到,如此 #{bean} .

    确定原因可分为三个步骤:

    一个 . 谁在管理 beans 子?
    湾什么是(默认)托管bean名称?
    C . 支持bean类在哪里?

    1 a . 谁在管理 beans 子?

    第一步是检查哪个bean管理framework负责管理bean实例 . 是 JSF 来自@ManagedBean?或者 CDI 来自@Named?或者 Spring 来自@Component?你能否确保你没有在同一个支持bean类上混合多个bean管理框架特定的注释?例如 . @Named @Component ,或 @Named @ManagedBean ,或 @ManagedBean @Component . 这是错的 . bean必须由最多一个bean管理框架管理,并且必须正确配置该框架 . 如果您已经不知道选择哪个,请前往Backing beans (@ManagedBean) or CDI Beans (@Named)?Spring JSF integration: how to inject a Spring component/service in JSF managed bean?

    如果 JSF 谁通过 @ManagedBean 管理bean,那么你需要确保以下内容:

    • faces-config.xml root声明与JSF 2.0兼容 . 所以XSD文件和 version 必须 at least 指定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_02.0 分别替换为 2_12.1 .

    如果你__79424_在所有地方使用 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_22.2 分别替换为 2_32.3 .

    • 您没有意外导入javax.annotation.ManagedBean而不是javax.faces.bean.ManagedBean . 注意IDE自动完成,Eclipse已知自动提供错误的一个作为列表中的第一项 .

    • 您没有通过 faces-config.xml 中的JSF 1.x样式 <managed-bean> 条目在同一个支持bean类上覆盖 @ManagedBean 以及不同的托管bean名称 . 这个优先于 @ManagedBean . 在 faces-config.xml 中注册托管bean不是必需的,因为JSF 2.0只是将其删除 .

    • 您的运行时类路径是干净的,并且与JSF API相关的JAR中没有重复项 . 当目标容器已经开箱即用JSF API时,请确保您沿着webapp提供另一个JSF甚至Java EE API JAR文件 . 有关JSF安装说明,另请参阅"Installing JSF" section of our JSF wiki page . 如果您打算从WAR而不是容器本身升级容器捆绑的JSF,请确保您已指示目标容器使用WAR捆绑的JSF API / impl .

    • 如果要在JAR中打包JSF托管bean,请确保JAR至少具有JSF 2.0兼容 /META-INF/faces-config.xml . 另见How to reference JSF managed beans which are provided in a JAR file?

    • 如果您实际使用的是侏罗纪JSF 1.x,并且无法升级,则需要通过 faces-config.xml 中的 <managed-bean> 而不是 @ManagedBean 注册bean . Don 't forget to fix your project build path as such that you don'不再有JSF 2.x库(因此 @ManagedBean 注释不会混淆地成功编译) .


    如果 CDI 谁通过 @Named 管理bean,那么你需要确保以下内容:

    • CDI 1.0(Java EE 6)需要 /WEB-INF/beans.xml 文件才能在WAR中启用CDI . 它可以是空的,也可以只有以下内容:
    <?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" ,则默认情况下它只会注册带有显式CDI范围注释的 @Named beans,例如@RequestScoped@ViewScoped@SessionScoped@ApplicationScoped等 . 如果您打算将所有bean注册为CDI托管bean,即使没有明确的CDI范围的bean,也使用下面的CDI 1.1兼容 /WEB-INF/beans.xmlbean-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" (默认)时,由于bug,您需要将Mojarra升级到2.3.3或更高版本 . 如果您无法升级,则需要在 beans.xml 中设置 bean-discovery-mode="all" ,或者将JSF 2.3特定的 @FacesConfig 注释放在WAR中的任意类(通常是某种应用程序范围的启动类)上 .

    • 像Tomcat和Jetty这样的非Java EE容器并没有比仅添加库JAR更多的工作 . 对于Tomcat,请确保按照以下答案中的说明操作:How to install and use CDI on Tomcat?

    • 您的运行时类路径是干净的,并且与CDI API相关的JAR中没有重复项 . 当目标容器已经将CDI API捆绑在一起时,请确保您沿着webapp提供另一个CDI甚至Java EE API JAR文件 .

    • 如果要在JAR中为JSF视图打包CDI托管bean,请确保JAR至少有一个有效的 /META-INF/beans.xml (可以保留为空) .


    如果 Spring 谁通过 @Component 管理bean,那么你需要确保以下内容:

    • 正在根据its documentation安装和集成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配置相关的麻烦)

    如果是 repeater component 谁通过其 var 属性(例如 <h:dataTable var="item"><ui:repeat var="item"><p:tabView var="item"> 等)管理(嵌套)bean,并且您实际上得到了"Target Unreachable, identifier 'item' resolved to null",那么您需要确保以下内容:

    • #{item} 未在任何子组件的 binding 属性中引用 . 这是不正确的,因为 binding 属性在视图构建时运行,而不是在视图渲染时 . 而且,在组件树中物理上只有一个组件,它在每次迭代循环中都被简单地重用 . 换句话说,您实际应该使用 binding="#{bean.component}" 而不是 binding="#{item.component}" . 但更好的方法是完全摆脱对bean的组件,并调查/询问你认为以这种方式解决的问题的正确方法 . 另见How does the 'binding' attribute work in JSF? When and how should it be used?

    1 b . 什么是(默认)托管bean名称?

    第二步是检查已注册的托管bean名称 . JSF和Spring使用约定符合JavaBeans specification,而CDI具有异常,具体取决于CDI impl / version .

    • FooBean 支持bean类如下,
    @Named
    public class FooBean {}
    

    根据JavaBeans规范,所有bean管理框架中的默认托管bean名称都是 #{fooBean} .

    • FOOBean 支持bean类,如下所示,
    @Named
    public class FOOBean {}
    

    其不合格的类名以至少两个大写字母开头,在JSF和Spring中有一个默认的托管bean名称,完全是非限定类名 #{FOOBean} ,也符合JavaBeans规范 . 在CDI中,2015年6月之前发布的Weld版本也是如此,但2015年6月之后发布的Weld版本(2.2.14 / 2.3.0.B1 / 3.0.0.A9)以及an oversight in CDI spec中的OpenWebBeans都没有 . 在那些焊接版本和所有OWB版本中,只有第一个字符小写 #{fOOBean} .

    • 如果您已明确指定了托管bean名称 foo ,如下所示
    @Named("foo")
    public class FooBean {}
    

    或等效地使用 @ManagedBean(name="foo")@Component("foo") ,它只能由 #{foo} 提供,因此不能由 #{fooBean} 提供 .


    1 c . 支持bean类在哪里?

    如果支持bean类位于构建和部署的WAR文件中的正确位置,则第三步将是双重检查 . 确保您已正确执行项目和服务器的完全清理,重建,重新部署和重新启动,以防您实际上忙于编写代码并在浏览器中不耐烦地按F5 . 如果仍然徒劳,那么让构建系统生成一个WAR文件,然后使用ZIP工具提取并检查 . 支持bean类的已编译 .class 文件必须位于 /WEB-INF/classes 中的包结构中 . 或者,当它作为JAR模块的一部分打包时,包含已编译的 .class 文件的JAR必须位于 /WEB-INF/lib 中,因此不能EAR的 /lib 或其他地方 .

    如果您正在使用Eclipse,请确保支持bean类位于 src 中,因此不是 WebContent ,并确保启用了Project> Build Automatically . 如果您正在使用Maven,请确保支持bean类位于 src/main/java 中,因此不在 src/main/resourcessrc/main/webapp 中 .

    如果您将Web应用程序打包为带有EJB WAR的EAR的一部分,那么您需要确保支持bean类在WAR模块中,因此不在EAR模块或EJB模块中 . 业务层(EJB)必须没有任何与Web层(WAR)相关的工件,因此业务层可以跨多个不同的Web层(JSF,JAX-RS,JSP / Servlet等)重用 .


    2.目标无法访问,'entity'返回null

    这归结为 #{bean.entity.property} 中的嵌套属性 entity 返回 null . 这通常只在JSF需要通过下面的输入组件 propertyproperty 时公开,而 #{bean.entity} 实际上返回了 null .

    <h:inputText value="#{bean.entity.property}" />
    

    您需要确保事先在 @PostConstruct<f:viewAction> 方法中准备好模型实体,或者在使用同一视图上的CRUD列表和/或对话框时使用 add() 操作方法 .

    @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 的重要性;如果您使用的是使用proxies的bean管理框架(例如CDI),那么在常规构造函数中执行此操作将会失败 . 始终使用 @PostConstruct 挂钩托管bean实例初始化(并使用 @PreDestroy 挂钩托管bean实例销毁) . 此外,在构造函数中,您还无法访问任何注入的依赖项,另请参阅NullPointerException while trying to access @Inject bean in constructor .

    如果 entityId 是通过 <f:viewParam> 提供的,则需要使用 <f:viewAction> 而不是 @PostConstruct . 另见When to use f:viewAction / preRenderView versus PostConstruct?

    您还需要确保在回发期间保留非 null 模型,以防您仅在 add() 操作方法中创建它 . 最简单的方法是将bean放在视图范围内 . 另见How to choose the right bean scope?


    3.目标无法访问,'null'返回null

    这与#2实际上是相同的原因,只有正在使用的(较旧的)EL实现在保留方面有些错误要在异常消息中显示的属性名称,该消息最终错误地显示为'null' . 当你有很多嵌套属性(如 #{bean.entity.subentity.subsubentity.property} )时,这只会使调试和修复变得更难 .

    解决方案仍然是相同的:确保所讨论的嵌套实体在所有级别中都不是 null .


    4.目标无法访问,''0'返回null

    这也与#2的原因相同,只有正在使用的(较旧的)EL实现在制定异常消息时存在错误 . 只有在 #{bean.collection[index]} 中使用EL中的括号符号 [] 时才会显示此情况,其中 #{bean.collection} 本身为非空,但指定索引处的项目不存在 . 这样的消息必须解释为:

    目标无法访问,'collection [0]'返回null

    解决方案也与#2相同:确保收集项目可用 .


    5.目标无法访问,'BracketSuffix'返回null

    这与#4实际上是相同的原因,只有正在使用的(较旧的)EL实现在保留迭代索引以显示在异常消息中有些错误,异常消息最终错误地暴露为'BracketSuffix',这实际上是字符 ] . 当您在集合中有多个项目时,这只会使调试和修复变得更加困难 .


    javax.el.PropertyNotFoundException的其他可能原因:

  • 0

    我使用wildfly 10作为javaee容器 . 我曾经历过“Target Unreachable,'entity'返回null”问题 . 感谢BalusC的建议,但我解决了解决方案的问题 . 无意中使用“import com.sun.istack.logging.Logger;”而不是“import org.jboss.logging.Logger;”导致CDI实现了JSF EL . 希望它有助于改善解决方案 .

相关问题