mojarra icon indicating copy to clipboard operation
mojarra copied to clipboard

Injection in FacesConverter not working

Open ghost opened this issue 7 years ago • 26 comments

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.

ghost avatar Nov 03 '17 12:11 ghost

Which Mojarra version are you using? Do you mean Mojarra 2.3.0 with JSF 2.3.0?

arjantijms avatar Nov 03 '17 13:11 arjantijms

Yes Mojarra 2.3.0 with JSF 2.3.0

ghost avatar Nov 03 '17 14:11 ghost

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.

ghost avatar Nov 03 '17 14:11 ghost

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.

arjantijms avatar Nov 03 '17 14:11 arjantijms

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 ;-)

ghost avatar Nov 03 '17 15:11 ghost

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.

arjantijms avatar Nov 03 '17 18:11 arjantijms

Ok, I just checked and CdiUtils#createConverter uses the JNDI bean manager, so this can’t really be the issue here.

arjantijms avatar Nov 03 '17 18:11 arjantijms

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.

ghost avatar Nov 04 '17 11:11 ghost

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.

arjantijms avatar Nov 04 '17 11:11 arjantijms

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?

ghost avatar Nov 10 '17 13:11 ghost

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?

ghost avatar Nov 10 '17 14:11 ghost

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

arjantijms avatar Nov 10 '17 14:11 arjantijms

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.

ghost avatar Nov 10 '17 14:11 ghost

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.

arjantijms avatar Nov 10 '17 15:11 arjantijms

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.

dmatej avatar Nov 10 '17 18:11 dmatej

I'm not using beans.xml

ghost avatar Nov 12 '17 16:11 ghost

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).

ghost avatar Feb 16 '18 15:02 ghost

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.

BalusC avatar Feb 16 '18 16:02 BalusC

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.

Jsf23Test.zip

ghost avatar Feb 19 '18 08:02 ghost

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.

ghost avatar Feb 19 '18 09:02 ghost

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.

arjantijms avatar Feb 19 '18 09:02 arjantijms

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,

mmeany avatar Jul 29 '18 11:07 mmeany

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 ;-)

ghost avatar Jul 29 '18 13:07 ghost

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

ghost avatar Dec 06 '18 13:12 ghost

Using Wildfly 16 jsf version 2.3.9.SP01 I have the same issue.

alibttb avatar Apr 21 '19 17:04 alibttb

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.

alibttb avatar Apr 21 '19 18:04 alibttb