1.无法到达目标,标识符“ bean”解析为空
可以归结为,像这样,无法通过EL中的那个标识符(托管Bean名称)准确地找到托管Bean实例本身#{bean}
。
查明原因可分为三个步骤:
一个。谁在管理bean?
b。(默认)托管Bean名称是什么?
C。支持bean类在哪里?
1a。谁在管理bean?
第一步是检查哪个bean管理框架负责管理bean实例。是通过JSF@ManagedBean
吗?还是CDI通过@Named
?还是通过Spring@Component
?您能确定不会在同一个支持bean类上混合使用多个特定于bean管理框架的注释吗?例如@Named @Component
或@Named @ManagedBean
或@ManagedBean @Component
。错了 该bean必须最多由一个bean管理框架管理,并且该框架必须正确配置。如果您不知道要选择哪个,请转到支持bean(@ManagedBean)或CDI Beans(@Named)?和Spring JSF集成:如何在JSF托管bean中注入Spring组件/服务?
如果是JSF通过来管理Bean @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
by 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会自动建议错误的列表中的第一项。
- 您没有在同一个支持Bean类上使用
@ManagedBean
JSF 1.x样式<managed-bean>
条目faces-config.xml
以及其他托管Bean名称来覆盖。这将优先于@ManagedBean
。faces-config.xml
从JSF 2.0开始,无需在其中注册托管bean ,只需将其删除即可。
- 您的运行时类路径是干净的,并且没有与JSF API相关的JAR中的重复项。确保您没有混合使用多个JSF实现(Mojarra和MyFaces)。当目标容器已经将JSF API捆绑在包装盒中时,请确保您没有在webapp上提供其他JSF甚至Java EE API JAR文件。另请参阅我们的JSF Wiki页面的“安装JSF”部分,以获取JSF安装说明。如果您打算从WAR而不是在容器本身中升级容器绑定的JSF,请确保已指示目标容器使用WAR捆绑的JSF API / impl。
- 如果要将JSF托管的Bean包装在JAR中,请确保JAR至少具有JSF 2.0兼容
/META-INF/faces-config.xml
。另请参见如何引用JAR文件中提供的JSF托管bean?
如果您实际上是在使用侏罗纪的JSF 1.x,并且无法升级,则需要通过<managed-bean>
in faces-config.xml
而不是通过注册Bean @ManagedBean
。不要忘了修正项目构建路径,以使您不再拥有JSF 2.x库(这样@ManagedBean
就不会混淆成功地注释注释)。
如果是CDI通过来管理Bean @Named
,那么您需要确保以下几点:
/WEB-INF/beans.xml
为了在WAR中启用CDI,CDI 1.0(Java EE 6)需要一个文件。它可以为空,也可以仅包含以下内容:
<?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
豆类有一个明确的CDI范围注释,如@RequestScoped
,@ViewScoped
,@SessionScoped
,@ApplicationScoped
,等等。如果你打算为CDI托管bean注册所有豆类,即使是那些没有明确的CDI范围,请使用以下/WEB-INF/beans.xml
与bean-discovery-mode="all"
set 兼容的CDI 1.1 (默认为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"
in beans.xml
或将JSF 2.3特定的@FacesConfig
注释放在WAR中的任意类上(通常是某种应用程序范围的启动类)。
- Tomcat和Jetty等非Java EE容器未附带捆绑的CDI。您需要手动安装。与添加库JAR相比,这需要做更多的工作。对于Tomcat,请确保遵循以下答案中的指示信息:如何在Tomcat上安装和使用CDI?
- 您的运行时类路径是干净的,并且没有与CDI API相关的JAR中的重复项。确保您没有混合使用多种CDI实现(Weld,OpenWebBeans等)。当目标容器已将CDI API打包为开箱即用时,请确保不要在webapp上提供其他CDI甚至Java EE API JAR文件。
如果要在JAR中将CDI托管的bean用于JSF视图打包,则请确保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">
,等),你实际上得到了一个“目标不可达,标识‘项目’解析为空”,那么你需要做以下的肯定:
1b。(默认)托管Bean名称是什么?
第二步是检查注册的受管Bean名称。JSF和Spring使用约定符合JavaBeans规范,而CDI则具有取决于CDI impl / version的异常。
甲FooBean
支撑类象下面,
@Named
public class FooBean {}
#{fooBean}
根据JavaBeans规范,所有bean管理框架中的默认托管bean名称将为。
甲FOOBean
支撑类象下面,
@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)或OpenWebBeans中都没有这种情况,原因是CDI规格。在那些Weld版本和所有OWB版本中,只有第一个字符小写#{fOOBean}
。
如果您明确指定了foo
如下所示的托管Bean名称,
@Named("foo")
public class FooBean {}
或等价于@ManagedBean(name="foo")
或@Component("foo")
,则只能由#{foo}
而不是由可用#{fooBean}
。
1c。支持bean类在哪里?
第三步将是仔细检查后备bean类是否在构建和部署的WAR文件中的正确位置。确保已正确执行了项目和服务器的完整清理,重建,重新部署和重新启动,以防您实际上正忙于编写代码并且不耐烦地在浏览器中按F5键。如果仍然徒劳,请让构建系统生成WAR文件,然后使用ZIP工具提取并检查该文件。.class
支持Bean类的编译文件必须位于的包结构中/WEB-INF/classes
。或者,当将其打包为JAR模块的一部分时,包含已编译.class
文件的JAR 必须驻留在/WEB-INF/lib
EAR中/lib
或其他地方,因此不能驻留。
如果使用的是Eclipse,请确保backing bean类在其中,src
而不是 WebContent
,并确保启用了Project> Build Automatically。如果您使用的是Maven,确保支撑类是在src/main/java
,因此没有在src/main/resources
或src/main/webapp
。
如果要使用EJB + WAR将Web应用程序打包为EAR的一部分,则需要确保支持Bean类在WAR模块中,因此不在EAR模块或EJB模块中。业务层(EJB)必须没有与任何Web层(WAR)相关的工件,以便该业务层可在多个不同的Web层(JSF,JAX-RS,JSP / Servlet等)之间重用。
2.无法到达目标,“实体”返回null
归结为嵌套属性entity
如#{bean.entity.property}
return null
。通常仅在JSF需要通过如下所示的输入组件设置值property
(而#{bean.entity}
实际返回)时才公开null
。
<h:inputText value="#{bean.entity.property}" />
如果要在同一视图上使用CRUD列表和/或对话框,则需要确保预先在@PostConstruct
,<f:viewAction>
方法或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
; 如果您正在使用使用代理(例如CDI)的bean管理框架,则在常规构造函数中执行此操作将失败。始终使用@PostConstruct
钩子托管bean实例初始化(并使用@PreDestroy
钩子托管bean实例销毁)。此外,在构造函数中,您将无法访问任何注入的依赖项,请参阅NullPointerException,同时尝试在构造函数中访问@Inject bean。
如果entityId
是通过提供的<f:viewParam>
,则需要使用<f:viewAction>
而不是@PostConstruct
。另请参见何时使用f:viewAction / preRenderView和PostConstruct?
如果null
仅在add()
操作方法中创建非模型,则还需要确保在回发期间保留非模型。最简单的方法是将bean放入视图范围。另请参见如何选择正确的bean作用域?
3. Target Unreachable,“ null”返回null
这实际上与#2具有相同的原因,只是使用的(较旧的)EL实现在保留要显示在异常消息中的属性名称时有些错误,最终错误地将其显示为“空”。仅当您具有类似这样的嵌套属性时,这才使调试和修复变得困难#{bean.entity.subentity.subsubentity.property}
。
解决方案仍然相同:确保null
所有级别的嵌套实体都不是。
4.无法到达目标,“ 0”返回null
这也与#2具有相同的原因,只有正在使用的(较旧的)EL实现在制定异常消息时存在问题。仅当您[]
在EL中使用大括号表示法(例如#{bean.collection[index]}
其#{bean.collection}
本身为非null,但指定索引处的项不存在)时,此方法才公开。然后,必须将此类消息解释为:
无法到达目标,“ collection [0]”返回null
解决方案也与#2相同:确保收集项可用。
5.无法到达目标,“ BracketSuffix”返回null
实际上,这与#4具有相同的原因,只是所使用的(较旧的)EL实现在保留要显示在异常消息中的迭代索引时存在一些错误,最终错误地将其公开为'BracketSuffix',这实际上是字符]
。当您在集合中有多个项目时,这只会使调试和修复更加困难。
其他可能的原因javax.el.PropertyNotFoundException
: