EJB and CDI inject points in @FacesValidator and @FacesConverter fail to work by means of OmniFaces in newer versions of JSF
Asked Answered
V

1

5

I was using,

  • Mojarra 2.3.0-m01
  • OmniFaces 2.0.
  • PrimeFaces 5.1 final
  • PrimeFaces Extension 3.0.0
  • GlassFish Server 4.1

And other Java EE artifacts.


Injection points in @FacesValidator like as follows,

@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.
    }
}

Those injection points remain null (I did not explicitly try injecting an EJB but it should not happen as well like a managed bean).


Since the above-mentioned Mojarra version is still available as a snapshot, I tried downgrading it to 2.2.10 with the same version of OmniFaces which is 2.0 (alternatively also tried with OmniFaces 2.1-SNAPSHOT - on both Mojarra 2.2.10 and 2.3.0-m01 alternatively) but to no avail.

This worked, when I downgraded Majarra to 2.2.8-02 (tried with OmniFaces 1.8.1, 2.0 and 2.1-SNAPSHOT alternatively). I did not try other Mojarra versions.

Was the support to make @FacesValidator and @FacesConverter candidates for EJB and CDI injection points by means of OmniFaces (which in turn does not require any addition dependencies and/or configurations) removed for newer versions of Mojarra?

I have not yet explicitly tried in @FacesConverter just because changing this many libraries alternatively so many times using a buggy NetBeans IDE which also goes very slow on Windows by nature took the whole day from dawn to dusk.


EDIT :

The server produces the following Weld related warnings.

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.
Viscountcy answered 5/4, 2015 at 13:53 Comment(12)
Works for me on Tomcat 8.0.18 + Mojarra 2.3.0-m01 (and 2.2.10) + Weld 2.2.9. I don't have GF4.1 at hands right now, but which Weld version does it ship with?Townswoman
The Weld version in GlassFish 4.1 is 2.2.2 as mentioned here and here. Despite I do not know, if there is a way to fetch this version number programmatically. GlassFish 4.1 issues some Weld related warnings too. I have appended them to the question.Viscountcy
Weld version is logged as INFO: WELD-000900. I downgraded it to 2.2.2 for Tomcat, but still can't reproduce it. Should try GF 4.1 later. Those warnings are unlikely related.Townswoman
It is indeed logged as Info: WELD-000900: 2.2.2 (Final) on the terminal.Viscountcy
FYI, I got GF 4.1 up and running, upgraded its bundled Mojarra 2.2.7 to 2.2.10, and I made a test pass on OmniFaces 2.1 (snapshot) Showcase. Everything works just fine, including CDI/EJB injection in @FacesConverter. In other words, I'm still unable to reproduce your problem.Townswoman
This time I am on a blank playground project which I have created all over again from scratch having only a single XHTML file, a CDI managed bean (@SessionScoped and @ViewScoped alternatively), a single @FacesValidator where I have injected the CDI managed bean. The managed bean injection failed on Mojarra 2.2.10 but it succeeded on Mojarra 2.2.8-02 (alternatively). I have tried using OmniFaces 2.1 - SNAPSHOT. In a nutshell, I could see the exact same behaviour after creating a brand new blank JSF project having least possible dependencies and resources.Viscountcy
I have also tried injecting a CDI managed bean into a @FacesConverter. The same thing happened - the injection point succeeded on Mojarra 2.2.8-02 but it remained null on Mojarra 2.2.10. It is a standard NetBeans project using Ant build script to deploy the application hereby, not using the Maven build tool but that should not be the cause. The library is available on the class-path anyway. The server also logs that information on the terminal - Info: Using OmniFaces version 2.1-SNAPSHOT.Viscountcy
Gosh. I created a blank playground project and I reproduced your problem on GF 4.1. Then I recalled this related Q from today and I added a /WEB-INF/beans.xml (it was already present in OmniFaces showcase). Then it worked again. Does it for you too?Townswoman
I created beans.xml (/WEB-INF/beans.xml) with bean-discovery-mode="annotated" but to no avail. The injection point remained null on Mojarra 2.2.10 as said above (deployed the application all over again from scratch carefully).Viscountcy
My beans.xml was just empty. And yes, annotated makes the injected bean null again. When I changed to all (which is default btw), it works again. This is Weird.Townswoman
Yes setting bean-discovery-mode to all made the injection point work on Mojarra 2.2.10.Viscountcy
Reproduced same problem on WF 8.2 with both Mojarra 2.2.9 and 2.2.10, but not with Mojarra 2.2.8. So it's likely related to a change in 2.2.9. Now yet figuring which one ..Townswoman
T
7

This is caused by a change in Mojarra 2.2.9. It works fine in 2.2.8. I reproduced it in both GlassFish 4.1 and WildFly 8.2. After scanning all issues listed in the 2.2.9 release notes and the associated change bundles, it appears to be the consequence of backport of issue 3552 to JSF 2.2.x. They internally disabled checking injectability of components, behaviors, validators and converters which implicitly registered them as CDI managed bean candidates. In other words, during 2.2.x until 2.2.9, Mojarra unintentionally offered "native" @Inject support in the mentioned artifacts.

In order to get injection in @FacesConverter and @FacesValidator to work anyway via OmniFaces, you need to add an empty /WEB-INF/beans.xml or at least one with bean-discovery-mode set to all instead of 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>

It's the default value already, you could also just omit the bean-discovery-mode attribute.

The technical difference is that bean-discovery-mode="all" will register all eligible classes as CDI managed beans, while bean-discovery-mode="annotated" only registers classes with an explicit CDI scope annotation such as @RequestScoped as CDI managed beans, which would thus fail for @FacesConverter and @FacesValidator.

Townswoman answered 17/4, 2015 at 15:56 Comment(3)
JSF 2.3 approach requires additional managed=true attribute in class' annotation to trigger it. See also jdevelopment.nl/jsf-23Townswoman
Is it mandatory to use bean-discovery-mode="all". Would't it work if I mark Validator with some scope annotation? Will @ RequestScoped or @ Dependent work?Launcelot
@Launcelot Sadly, marking the bean with a bean defining annotation wouldn't work either. You might downgrade your JSF libs to an "injection supporting" Mojarra version using the steps described at #17086217. 'Cause bean-discovery-mode="all" sucks.Dodgson

© 2022 - 2024 — McMap. All rights reserved.