mojarra
mojarra copied to clipboard
Injection in FacesConverter not working
Using JSF 2.3.0 on EAP 7
This is my code:
<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_3.xsd" version="2.3"> ... </faces-config>
@FacesConfig(version = Version.JSF_2_3)
@ApplicationScoped
public class Config {}
@FacesConverter(forClass = Category.class, managed = true)
public class CategoryConverter implements Converter<Category> {
@Inject
Web web; // -> BREAKPOINT = always null
@Override
public Category getAsObject(FacesContext context, UIComponent component, String value) {
return web.getCategories().stream().filter(c -> c.getId() == Long.valueOf(value)).findFirst().get();
}
@Override
public String getAsString(FacesContext context, UIComponent component, Category value) {
return String.valueOf(value.getId());
}
}
@Named
@ApplicationScoped
public class Web { ... }
I am always getting NPE in getAsObject in the faces converter because the injected Web object is always null.
Which Mojarra version are you using? Do you mean Mojarra 2.3.0 with JSF 2.3.0?
Yes Mojarra 2.3.0 with JSF 2.3.0
Btw, my workaround is:
@Override
public Category getAsObject(FacesContext context, UIComponent component, String value) {
return CDI.current().select(Web.class).get().getCategories().stream()
.filter(c -> c.getId() == Long.valueOf(value)).findFirst().get();
}
This simulates the CDI injection as should be done by JSF.
You might want to try the current 2.3.3 version and see how that works. In general, this relatively straightforward injection should really work as there are tests for this. Your specific situation is likely different somewhere, so quite puzzling.
Ok, I will try the 2.3.3 setup next week. Will keep you posted.
Meanwhile, I found here another issue which looks very similar, except it is for faces validators:
https://github.com/javaserverfaces/mojarra/issues/4245
Could this be related? injection in validators should also work ;-)
I’ve given this some thought and there might be another possible reason.
The problem is that it’s not clearly defined which bean archive(s) CDI.current() applies to. In some servers, CDI.current() only sees the server classes when being called from a server jar (which Mojarra is, when included in the modules folder of WildFly).
The bean manager obtained via JNDI seems to always see classes in both server and app.
I’ve to check again which version Mojarra is using.
Ok, I just checked and CdiUtils#createConverter uses the JNDI bean manager, so this can’t really be the issue here.
The CDI.current() is the workaround which works. I'm using this but it is kinda ugly =) It is the @Inject which is not working. Could it maybe be the EAP version 7.0.X? I am not at work right now but I believe I use 7.0.0.
The CDI.current() is the workaround which works. I'm using this but it is kinda ugly =) It is the @Inject which is not working.
I know, but you are calling CDI.current() from the context of your application code. It can be different when called from a jar that resides within the container.
I installed 2.3.3, but unfortunately still NPE.
FYI, when putting FacesContext.class.getPackage().getImplementationVersion()
in the code it prints 2.3.3.
EAP version is 7.0.0
In installed following this guide: https://docs.jboss.org/author/display/WFLY10/JSF+Configuration Split the jar following this guide: https://stackoverflow.com/questions/35899887/how-to-install-one-jar-variant-of-jsf-javax-faces-jar-on-wildfly
Also tried to use the value attribute iso the forClass attribute in @FacesConverter, but still NPE.
Any other idea?
Also a little bit off topic, but the usage of @FacesConfig is really new to me. I based a presentation on your blog: http://arjan-tijms.omnifaces.org/p/jsf-23.html
Maybe you could add a word there about this new annotation that in fact is mandatory (correct?) to enable full 2.3 mode?
I should indeed still write something about that, it's on my TODO but didn't find the time yet. I've no idea yet why in EAP 7 you're seeing those issues. I'll have to debug it I guess...
Thanks.
If I may be so rude to make a wild suggestion, EAP 7 uses a specific JSF injection jar. Maybe there is something wrong there. I suppose it was designed for JSF 2.2... Anyway, if I can be of any help, let me know.
The injection SPI itself did not change between 2.2 and 2.3 really. In 2.4 there’s a change again, but as far as a remember not in 2.3.
But more importantly, for CDI injection with managed = true, Mojarra requests the full bean instance from CDI and doesn’t do anything with it itself, so the SPI does not come into play.
I am not sure about this situation but I could not inject for example ExternalContext on Payara 5 until I declared version 2.0 in beans.xml. Then it worked. My beans.xml:
<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_2_0.xsd"
version="2.0" bean-discovery-mode="all">
</beans>
The @FacesConfig(version = Version.JSF_2_3)
annotation is used too.
I'm not using beans.xml
I'm facing the same issue with JSF 2.3.3. Moreover JSF 2.3.3 breaks the injection in converters that was enabled by Apache DeltaSpike (https://deltaspike.apache.org/documentation/jsf.html#InjectioninJSFArtifacts).
Is there a JSF 2.3 compatible version of Deltaspike?
Wondering how it's different from OmniFaces where injection in converters/validators continued to work just fine.
I have attached a minimal project to reproduce the issue, which has only the following dependencies:
javaee-web-api 8.0 javax.faces 2.3.3 jstl 1.2 weld-servlet-shaded 3.0.0.Final
I tested on Tomcat 7.0.47 and 8.5.13.
I finally got the injection in my minimal project working. But I had actual to annotate the bean with @FacesConfig(version=Version.JSF_2_3)
. This doesn't seem to be an option, as we have to access CDI services from our business layers in which we have no refence to JSF and thus cannot use @FacesConfig
. Btw. I also had to annotate the injection point with the additional qualifier @Any
though the bean is the only one of it's type.
For the JSF application, @FacesConfig
has to be present once. You don't have to actually annotate the CDI bean that you want to inject with it, it can be present on any bean within the web layer.
I see the ticket is still open and I arrived here first with my search so wanted to point to the solution that is working for me on Wildfly 13 and Payara5.182 comes from the solution here: https://stackoverflow.com/questions/45682309/changing-faces-config-xml-from-2-2-to-2-3-causes-javax-el-propertynotfoundexcept,
Putting bean-discovery-mode="all" in beans.xml makes all Java classes of the project automatically processable by CDI (more memory!). I do not want this, this is just another work around. If I put it on "annotated" it is still not working... It must work also with "annotated", that is the whole point of JSF artifacts being injectable ;-)
After some time I come back to working with JSF 2.3 again. Injection made possible by Apache DeltaSpike seems to work again, at least it works in this converter:
@FacesConverter(value = TypedDateConverter.ID)
public class TypedDateConverter implements Converter<LocalDate> {
static final String ID = "com.pass.project.converter.TypedDateConverter";
@Inject
private LocaleBean localeBean;
private String pattern;
Unfortunately with 'managed=true' the attribute 'pattern' is no longer set.
Is there anything against using the converters without managed=true and relying on the injection made possible by deltaspike?
I'm using: javax.faces 2.3.8 omnifaces 3.2 deltaspike 1.8.2
Using Wildfly 16 jsf version 2.3.9.SP01 I have the same issue.
This only works if you have beans.xml configured with bean-discovery-mode="all"
and ConfigBean
annotated with
@FacesConfig(
// Activates CDI build-in beans
version = JSF_2_3
)
This is not how it should work, injection should happen by convention not by configuration.