在较新版本的 JSF 中,@FacesValidator 和 @FacesConverter 中的 EJB 和 CDI 注入点无法通过 OmniFaces 工作

Posted

技术标签:

【中文标题】在较新版本的 JSF 中,@FacesValidator 和 @FacesConverter 中的 EJB 和 CDI 注入点无法通过 OmniFaces 工作【英文标题】:EJB and CDI inject points in @FacesValidator and @FacesConverter fail to work by means of OmniFaces in newer versions of JSF 【发布时间】:2015-06-10 01:38:45 【问题描述】:

我正在使用,

Mojarra 2.3.0-m01 OmniFaces 2.0。 PrimeFaces 5.1 最终版 PrimeFaces 扩展 3.0.0 GlassFish 服务器 4.1

以及其他 Java EE 工件。


@FacesValidator中的注入点如下,

@FacesValidator(value="testValidator")
public class TestValidator implements Validator 

    @Inject
    private DemoEJB ejb;

    @Inject
    private ManagedBean managedBean;

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException 
        // Use the injected EJB and/or managed bean here.
    

那些注入点仍然是null(我没有明确尝试注入 EJB,但它不应该像托管 bean 那样发生)。


由于上述 Mojarra 版本仍可作为快照使用,我尝试使用相同版本的 OmniFaces 2.0 将其降级到 2.2.10(或者也尝试使用 OmniFaces 2.1-SNAPSHOT - 在 Mojarra 2.2.10 上和 2.3.0-m01 替代)但无济于事。

当我将 Majarra 降级到 2.2.8-02 时,这很有效(交替使用 OmniFaces 1.8.1、2.0 和 2.1-SNAPSHOT 进行尝试)。我没有尝试其他 Mojarra 版本。

对于较新版本的 Mojarra,是否通过 OmniFaces(这反过来不需要任何附加依赖项和/或配置)将 @FacesValidator@FacesConverter 候选作为 EJB 和 CDI 注入点的支持删除了?

我还没有在@FacesConverter 中明确尝试过,只是因为使用有缺陷的 NetBeans IDE 更改了这么多库,在 Windows 上运行速度也很慢,从黎明到黄昏花了一整天的时间。


编辑:

服务器产生以下 Weld 相关警告。

WARN:   WELD-001700: Interceptor annotation class javax.ejb.PostActivate not found, interception based on it is not enabled
WARN:   WELD-001700: Interceptor annotation class javax.ejb.PrePassivate not found, interception based on it is not enabled
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] public org.omnifaces.VetoAnnotatedTypeExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] public org.omnifaces.VetoAnnotatedTypeExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.
WARN:   WELD-001473: javax.enterprise.inject.spi.Bean implementation com.sun.faces.cdi.ApplicationProducer@b15a70 declared a normal scope but does not implement javax.enterprise.inject.spi.PassivationCapable. It won't be possible to inject this bean into a bean with a passivating scope (@SessionScoped, @ConversationScoped). This can be fixed by assigning the Bean implementation a unique id by implementing the PassivationCapable interface.
WARN:   WELD-001473: javax.enterprise.inject.spi.Bean implementation com.sun.faces.cdi.ApplicationMapProducer@db0450 declared a normal scope but does not implement javax.enterprise.inject.spi.PassivationCapable. It won't be possible to inject this bean into a bean with a passivating scope (@SessionScoped, @ConversationScoped). This can be fixed by assigning the Bean implementation a unique id by implementing the PassivationCapable interface.
WARN:   WELD-001473: javax.enterprise.inject.spi.Bean implementation com.sun.faces.cdi.ViewMapProducer@1c55365 declared a normal scope but does not implement javax.enterprise.inject.spi.PassivationCapable. It won't be possible to inject this bean into a bean with a passivating scope (@SessionScoped, @ConversationScoped). This can be fixed by assigning the Bean implementation a unique id by implementing the PassivationCapable interface.
WARN:   WELD-001473: javax.enterprise.inject.spi.Bean implementation com.sun.faces.cdi.ExternalContextProducer@14b1a6 declared a normal scope but does not implement javax.enterprise.inject.spi.PassivationCapable. It won't be possible to inject this bean into a bean with a passivating scope (@SessionScoped, @ConversationScoped). This can be fixed by assigning the Bean implementation a unique id by implementing the PassivationCapable interface.
WARN:   WELD-001473: javax.enterprise.inject.spi.Bean implementation com.sun.faces.cdi.FacesContextProducer@1048acb declared a normal scope but does not implement javax.enterprise.inject.spi.PassivationCapable. It won't be possible to inject this bean into a bean with a passivating scope (@SessionScoped, @ConversationScoped). This can be fixed by assigning the Bean implementation a unique id by implementing the PassivationCapable interface.
WARN:   WELD-001473: javax.enterprise.inject.spi.Bean implementation com.sun.faces.cdi.ViewProducer@275cfa declared a normal scope but does not implement javax.enterprise.inject.spi.PassivationCapable. It won't be possible to inject this bean into a bean with a passivating scope (@SessionScoped, @ConversationScoped). This can be fixed by assigning the Bean implementation a unique id by implementing the PassivationCapable interface.

【问题讨论】:

在 Tomcat 8.0.18 + Mojarra 2.3.0-m01(和 2.2.10)+ Weld 2.2.9 上为我工作。我现在手头没有 GF4.1,但它附带哪个 Weld 版本? GlassFish 4.1 中的 Weld 版本是 2.2.2,如 here 和 here 所述。尽管我不知道,是否有办法以编程方式获取此版本号。 GlassFish 4.1 也会发出一些与焊接相关的警告。我已将它们附加到问题中。 焊接版本记录为INFO: WELD-000900。我将它降级到 Tomcat 的 2.2.2,但仍然无法重现它。应该稍后尝试 GF 4.1。这些警告不太可能相关。 确实在终端上记录为Info: WELD-000900: 2.2.2 (Final) 仅供参考,我启动并运行了 GF 4.1,将其捆绑的 Mojarra 2.2.7 升级到 2.2.10,并且我通过了 OmniFaces 2.1(快照)展示柜的测试。一切正常,包括@FacesConverter 中的 CDI/EJB 注入。换句话说,我仍然无法重现您的问题。 【参考方案1】:

这是由 Mojarra 2.2.9 中的更改引起的。它在 2.2.8 中运行良好。我在 GlassFish 4.1 和 WildFly 8.2 中都复制了它。在扫描了2.2.9 release notes 中列出的所有问题以及相关的变更包后,这似乎是issue 3552 向后移植到 JSF 2.2.x 的结果。他们在内部禁用了检查组件、行为、验证器和转换器的可注入性,这些组件、行为、验证器和转换器隐式地将它们注册为 CDI 托管 bean 候选者。换句话说,在 2.2.x 到 2.2.9 期间,Mojarra 无意中在上述工件中提供了“原生”@Inject 支持。

为了使@FacesConverter@FacesValidator 中的注入能够通过OmniFaces 正常工作,您需要添加一个空的/WEB-INF/beans.xml 或至少一个将bean-discovery-mode 设置为all 而不是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"
    xmlns:weld="http://jboss.org/schema/weld/beans"
    bean-discovery-mode="all"
>
    <!-- ... -->
</beans>

它已经是默认值了,你也可以省略bean-discovery-mode 属性。

技术区别在于bean-discovery-mode="all" 会将所有 符合条件的类注册为 CDI 托管 bean,而 bean-discovery-mode="annotated" 仅将具有显式 CDI 范围注释的类(例如 @RequestScoped)注册为 CDI 托管 bean ,因此对于 @FacesConverter@FacesValidator 将失败。

【讨论】:

JSF 2.3 方法需要在类的注释中附加 managed=true 属性来触发它。另见jdevelopment.nl/jsf-23 是否必须使用 bean-discovery-mode="all"。如果我用一些范围注释标记验证器,它不会工作吗? @RequestScoped 或 @Dependent 会起作用吗? @guest 可悲的是,用 bean 定义注释标记 bean 也不起作用。您可以使用***.com/questions/17085717/… 中描述的步骤将您的 JSF 库降级为“支持注入”的 Mojarra 版本。因为 bean-discovery-mode="all" 很烂。

以上是关于在较新版本的 JSF 中,@FacesValidator 和 @FacesConverter 中的 EJB 和 CDI 注入点无法通过 OmniFaces 工作的主要内容,如果未能解决你的问题,请参考以下文章

如何在较新版本的 libreoffice 中使用 unoconv

SVG sprite 图标背景位置在较新版本的 Chrome 中显示为关闭

如何在较新版本的 Delphi 中嵌入 YouTube 视频?

在较新版本的 Keras 中,LSTM 等效于 return_sequence = True

如何在较新版本的打字稿中处理打字稿错误 Object.ts (7053)?

React Native 图像未在较新版本的 iOS 上呈现