识别和解决javax.el.propertynotfoundexception:目标不可访问

ds97pgxw  于 2021-07-08  发布在  Java
关注(0)|答案(1)|浏览(482)

当试图引用el中的托管bean时 #{bean.entity.property} ,有时是 javax.el.PropertyNotFoundException: Target Unreachable 通常在设置bean属性或调用bean操作时抛出异常。
似乎有五种不同的信息:
目标不可访问,标识符“bean”解析为空
无法访问目标,“实体”返回null
无法访问目标,“null”返回null
无法访问目标,“0”返回null
无法访问目标,“bracketsuffix”返回null
它们都是什么意思?它们是如何产生的,应该如何解决?

f45qwnt8

f45qwnt81#

1. 目标不可访问,标识符“bean”解析为空

这可以归结为,在el中,托管bean示例本身不能被该标识符(托管bean名称)准确地找到 #{bean} .
确定原因可分为三个步骤:
答。谁在管理豆子?
b。托管bean的(默认)名称是什么?
c。支持bean类在哪里?

第1a条。谁在管理豆子?

第一步是检查哪个bean管理框架负责管理bean示例。是cdi via吗 @Named ? 还是jsf via @ManagedBean ? 还是Spring @Component ? 您能确保在同一个backingbean类上没有混合多个bean管理框架特定的注解吗?例如 @Named @ManagedBean , @Named @Component ,或 @ManagedBean @Component . 这是错误的。bean最多只能由一个bean管理框架管理,并且必须正确配置该框架。如果您已经不知道要选择哪一个,那么请转到backingbean(@managedbean)或cdibean(@named)?以及springjsf集成:如何在jsf管理的bean中注入spring组件/服务?
万一是cdi通过 @Named ,则需要确保以下各项:
CDI1.0(JavaEE6)需要 /WEB-INF/beans.xml 文件,以便在战争中启用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的行为相同。当CDI1.1兼容时 beans.xml 有明确的 version="1.1" ,则默认情况下它将只注册 @Named 带有显式cdi范围注解的bean,例如 @RequestScoped , @ViewScoped , @SessionScoped , @ApplicationScoped 如果您打算将所有bean注册为cdi管理的bean,即使是没有显式cdi作用域的bean,也可以使用下面的cdi1.1 /WEB-INF/beans.xmlbean-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" (默认),然后由于一个bug,您需要将mojarra升级到2.3.3或更新版本。如果无法升级,则需要设置 bean-discovery-mode="all"beans.xml ,或者将JSF2.3 @FacesConfig war中任意类上的注解(通常是某种应用程序范围的启动类)。
在Servlet4.0容器上使用JSF2.3时 web.xml 声明符合Servlet4.0,那么您需要显式地将JSF2.3 @FacesConfig war中任意类上的注解(通常是某种应用程序范围的启动类)。这在Servlet3.x中不是必需的。
像tomcat和jetty这样的非javaee容器并不附带cdi。你需要手动安装。这比仅仅添加库jar要多一些工作。对于tomcat,请确保遵循以下答案中的说明:如何在tomcat上安装和使用cdi?
运行时类路径是干净的,在cdiapi相关jar中没有重复项。确保您没有混合使用多个cdi实现(weld、openwebbeans等)。当目标容器已经打包了cdiapi时,确保不要在webapp中提供另一个cdi甚至javaeeapi jar文件。
如果要将用于jsf视图的cdi托管bean打包到jar中,那么请确保jar至少有一个有效的 /META-INF/beans.xml (可以保持为空)。
如果是jsf通过since 2.3管理bean的话 @ManagedBean ,并且您不能迁移到cdi,那么您需要确保:
这个 faces-config.xml 根声明与jsf2.0兼容。所以xsd文件和 version 必须至少指定JSF2.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">

对于jsf2.1,只需替换 2_0 以及 2.02_1 以及 2.1 分别。
如果您使用的是jsf2.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">

对于jsf2.3,只需替换 2_2 以及 2.22_3 以及 2.3 分别。
你不是偶然导入的 javax.annotation.ManagedBean 而不是 javax.faces.bean.ManagedBean . 注意ide的autocomplete,众所周知eclipse会自动将错误的提示作为列表中的第一项。
你没有覆盖 @ManagedBean 通过jsf1.x风格 <managed-bean> 进入 faces-config.xml 在同一个backingbean类上使用不同的托管bean名称。这个优先于 @ManagedBean . 在中注册托管bean faces-config.xml 从JSF2.0开始就没有必要了,只要删除它就行了。
运行时类路径是干净的,在jsfapi相关jar中没有重复项。确保您没有混合使用多个jsf实现(mojarra和myfaces)。当目标容器已经打包了jsfapi时,确保不要在webapp中提供另一个jsf甚至javaeeapi jar文件。另请参阅jsfwiki页面的“安装jsf”部分,以获取jsf安装说明。如果您打算从war-on而不是容器本身升级容器绑定的jsf,请确保已指示目标容器使用war绑定的jsfapi/impl。
如果要将jsf管理的bean打包到jar中,那么请确保jar至少有一个与jsf2.0兼容的bean /META-INF/faces-config.xml . 另请参阅如何引用jar文件中提供的jsf托管bean?
如果您实际使用的是jurassic jsf1.x,并且无法升级,那么您需要通过 <managed-bean>faces-config.xml 而不是 @ManagedBean . 不要忘记修复项目构建路径,这样您就不再有JSF2.x库了(这样 @ManagedBean 注解不会令人困惑地成功编译)。
以防是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相关的原因;e、 g.一些与xml配置相关的问题)
如果是中继器组件通过其 var 属性(例如。 <h:dataTable var="item"> , <ui:repeat var="item"> , <p:tabView var="item"> ,等等)并且您实际得到了“target unreachable,identifier'item'resolved to null”,那么您需要确保:
这个 #{item} 中未引用 binding 任何子组件的属性。这是不正确的,因为 binding 属性在视图生成时运行,而不是在视图渲染时运行。此外,在组件树中只有一个组件,在每一轮迭代中都可以简单地重用。换句话说,你实际上应该使用 binding="#{bean.component}" 而不是 binding="#{item.component}" . 但是更好的方法是完全摆脱组件bining到bean,并调查/询问您认为用这种方法解决的问题的正确方法。另请参见“binding”属性在jsf中是如何工作的?何时以及如何使用?

第1b条。托管bean的(默认)名称是什么?

第二步是检查已注册的托管bean名称。jsf和spring使用约定符合javabeans规范,而cdi根据cdi impl/version有例外。
FooBean 像下面这样支持bean类,

@Named
  public class FooBean {}

在所有bean管理框架中,默认的托管bean名称是 #{fooBean} ,符合javabeans规范。
FOOBean 像下面这样支持bean类,

@Named
  public class FOOBean {}

它的非限定类名至少以两个大写字母开头,在jsf和spring中会有一个与非限定类名完全相同的默认托管bean名称 #{FOOBean} ,也符合javabeans规范。在cdi中,在2015年6月之前发布的焊接版本中也是如此,但在2015年6月之后发布的焊接版本(2.2.14/2.3.0.b1/3.0.0.a9)中,由于cdi规范中的疏忽,openwebbeans中也没有这种情况。在这些焊接版本和所有owb版本中,只有第一个字符小写 #{fOOBean} .
如果已显式指定托管bean名称 foo 如下图所示,

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

或等同于 @ManagedBean(name="foo") 或者 @Component("foo") ,则只能在 #{foo} 因此不是通过 #{fooBean} .

1摄氏度。支持bean类在哪里?

第三步是双重检查backingbean类是否在构建和部署的war文件中的正确位置。确保您已经正确地执行了项目和服务器的完全清理、重建、重新部署和重新启动,以防您实际上正忙于编写代码并不耐烦地在浏览器中按f5。如果仍然是徒劳的,让构建系统生成一个war文件,然后用zip工具对其进行提取和检查。汇编的 .class 备份bean类的文件必须驻留在其包结构中 /WEB-INF/classes . 或者,当它被打包为jar模块的一部分时,包含已编译 .class 文件必须位于 /WEB-INF/lib 而不是耳朵 /lib 或者其他地方。
如果您使用的是eclipse,请确保backingbean类位于 src 因此不是 WebContent ,并确保已启用“项目>自动生成”。如果您使用的是maven,请确保backingbean类在 src/main/java 因此不在

*

相关问题