Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSF Facelet can not recognize CDI beans. #4264

Open
hantsy opened this issue Aug 5, 2017 · 33 comments

Comments

Projects
None yet
8 participants
@hantsy
Copy link

commented Aug 5, 2017

I am always trying to update myself to the latest Java EE specs. And two years ago, I created a ee8-sandbox project to practice the upcoming Java EE 8.

There is a Java EE 8 version JSF sample. which worked with the following when JSF 2.3 milestones was released.

  1. Java EE 7 API
  2. Glassfish 4.1.2 + JSF 2.3(copy and override the one existed in glassfish)

But in these days, it seems Glassfish v5 development becomes very active. It is really a good news for Java EE developers.

I tried to update all dependencies to the latest Java EE 8, and run this sample in Glassfish v 5.0 b17, I checked the GF shipped jars, it had been updated JSF to 2.3 and Weld to 3.0.Final.

But when I deployed my sample to GF v5, got the famous error Target Unreachable, identifier 'bean' resolved to null, JSF Facelet can not recognize CDI beans.

This error was described in details on stack overflow, https://stackoverflow.com/questions/30128395/identifying-and-solving-javax-el-propertynotfoundexception-target-unreachable, but none of them mentioned Java EE 8 and JSF 2.3.

The sample codes are almost same, only changed the Java EE APIs version and upgrade configuration file version.

Java EE 8 version: https://github.com/hantsy/ee8-sandbox/tree/master/jsf, upgraded to Java EE 8 APIs, did not work on GF v5, it was working when I changed the CDI bean-discovery-mode to all, and added @FacesConfig class to enable JSF 2.3.
Java EE 7 version: https://github.com/hantsy/ee7-sandbox/tree/master/taskboard, used Java EE 7 APIs, worked well on GF v4

@Andrew-Gr

This comment has been minimized.

Copy link

commented Aug 15, 2017

I have the absolutely the same issue! Vote up! Have tested on GlassFish 4.1.2, Payara 4.1.2.172, GlassFish 5 - everywhere the same error: javax.el.PropertyNotFoundException: ...... value="#{beanName.id}": Target Unreachable, identifier 'beanName' resolved to null
More details posted here: https://stackoverflow.com/questions/45682309
Also, in my case only by reverting faces-config back to JSF 2.2 syntax - solve this issue.

@hantsy

This comment has been minimized.

Copy link
Author

commented Aug 19, 2017

I have prepared a copy of codes for Java EE 7, and reverted the dependencies and configurations to Java EE 7 APIs. The codes are almost same, but it works in Java EE 7 and Glassfish v4. The difference is the Java EE version for APIs and configuration.

Java EE 7 sample: https://github.com/hantsy/ee7-sandbox/tree/master/taskboard

@Quix0r

This comment has been minimized.

Copy link

commented Aug 31, 2017

Just curious: Have you used @ManagedBean (JSF 2.0) or @Named (JSF 2.2) to give your backing bean a name? And have you used import javax.enterprise.context.*Scoped (JSF 2.2) and not deprecated javax.faces.bean.*Scoped (JSF 2.0). As a mixture of both versions don't work and is a common mistake to only change @ManagedBean to @Named.

@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 1, 2017

@Quix0r Did you check my sample codes?

I have used JSF in projects since 1.1. And when I used it within a DI container, such as Spring, Seam 2, CDI, I never used JSF built-in annotations to declare a bean. Never!

@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 1, 2017

BTW, It seems mojarra development is inactive in these months, from the Github commit logs, there are no resources on processing issues from reporters.

@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 1, 2017

@Andrew-Gr I found the some helpful info from GF issues. Maybe it clarified our confusion, but I think it is a very bad idea when I used JSF 2.3 in a Java EE 8 compatible application server, such as GF v5.

https://github.com/javaee/glassfish/issues/22094

We have to enable JSF 2.3 manually within a Java EE 8 container which has built-in JSF 2.3 support.

@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 1, 2017

I have added a ConfgirationBean as https://github.com/javaee/glassfish/issues/22094, but still does not work.

See #hantsy/ee8-sandbox@942e1b2

@Andrew-Gr

This comment has been minimized.

Copy link

commented Sep 3, 2017

@hantsy thank you for pointing out on the JSF 2.3 "activation" approach. I have seen that topic and also tried to activate JSF 2.3 according to that guide, but it didn't work for me as well.

@xinyuan-zhang

This comment has been minimized.

Copy link
Contributor

commented Sep 4, 2017

Here is my config,it works properly in latest GF5

Test.java

package com.corejsf;

import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import java.io.Serializable;

/**
 * Created by xinyuan.zhang on 9/4/17.
 */


@Named(value ="test")
@SessionScoped
public class Test implements Serializable{

    public Test() {
    }

    public Test(String output) {
        this.output = output;
    }

    private String output;

    public String getOutput() {
        output = "abc";
        return output;
    }

    public void setOutput(String output) {
        this.output = output;
    }
}

ConfigurationBean.java

package com.corejsf;

/**
 * Created by xinyuan.zhang on 9/4/17.
 */
import static javax.faces.annotation.FacesConfig.Version.JSF_2_3;

import javax.faces.annotation.FacesConfig;

@FacesConfig(
        // Activates CDI build-in beans
        version = JSF_2_3
)
public class ConfigurationBean {

}

beans.xml

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

faces-config.xml

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.3"
              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">
</faces-config>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app
        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-app_3_1.xsd"
        version="3.1"
>
   <servlet>
      <servlet-name>Faces Servlet</servlet-name>
      <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>Faces Servlet</servlet-name>
      <url-pattern>/faces/*</url-pattern>
   </servlet-mapping>
   <welcome-file-list>
      <welcome-file>faces/index.xhtml</welcome-file>
   </welcome-file-list>
   <context-param>
      <param-name>javax.faces.PROJECT_STAGE</param-name>
      <param-value>Development</param-value>
   </context-param>
</web-app>

index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
   <title>Facelet Title</title>
</h:head>
<h:body>
   <h:outputText value="#{test.output}"/> <br/>
</h:body>
</html>
@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 4, 2017

@xinyuan-zhang Compared to your codes, only some difference:

  1. I used CDI 2.0, and set bean-discovery-mode to annotated.
  2. I have not set FacesServlet, it can be configured automatically in Servlet 3.0 container for a long time.
  3. I have added ConfigurationBean and also added javax.faces.ENABLE_CDI_RESOLVER_CHAIN(true) in web.xml, I am not sure if the javax.faces.ENABLE_CDI_RESOLVER_CHAIN is no use now.
@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 4, 2017

@xinyuan-zhang @Andrew-Gr Just confirmed when I changed bean-discovery-mode to all, it works.

So the issue is JSF 2.3 does not work when bean-discovery-mode is set to annotated in beans.xml, obviously it is unreasonable. @Andrew-Gr Can you verify it?

@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 4, 2017

@xinyuan-zhang Just checked my Java EE 7 version, https://github.com/hantsy/ee7-sandbox/blob/master/taskboard/src/main/webapp/WEB-INF/beans.xml, bean-discovery-mode with value annotated works well in Java EE 7(JSF 2.2, CDI 1.1).

@xinyuan-zhang

This comment has been minimized.

Copy link
Contributor

commented Sep 4, 2017

@hantsy When you use bean-discovery-mode="annotated" in beans.xml, add

@FacesConfig(
        // Activates CDI build-in beans
        version = JSF_2_3
)

on your beans,for example

package com.corejsf;

import javax.enterprise.context.SessionScoped;
import javax.faces.annotation.FacesConfig;
import javax.inject.Named;
import java.io.Serializable;

import static javax.faces.annotation.FacesConfig.Version.JSF_2_3;

/**
 * Created by xinyuan.zhang on 9/4/17.
 */

@FacesConfig(
        // Activates CDI build-in beans
        version = JSF_2_3
)
@Named(value ="test")
@SessionScoped
public class Test implements Serializable{

    public Test() {
    }

    public Test(String output) {
        this.output = output;
    }

    private String output;

    public String getOutput() {
        output = "abc";
        return output;
    }

    public void setOutput(String output) {
        this.output = output;
    }
}
@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 4, 2017

@xinyuan-zhang I have added a standalone ConfigurationBean to enable CDI, if I set bean-discovery-mode="annotated" in beans.xml, it does not work.

Why I have to add @FacesConfig on each beans in my application, it is very unreasonable.

@xinyuan-zhang

This comment has been minimized.

Copy link
Contributor

commented Sep 4, 2017

@hantsy It confuses me also, but when I add @FacesConfig on cdi beans, it really works properly with bean-discovery-mode="annotated".
@edburns @AnghelLeonard @arjantijms @BalusC @manfredriem , does anyone can explain it?

@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 4, 2017

@xinyuan-zhang Personally I dislike use @FacesConfig to enable CDI as InejctionProvider.

The approaches in development stage was working well.

  1. faces-config.xml version to indicate the JSF version, but I think this version should only affect this config file itself, only indicates if the config xml schema is valid. A higher JSF implementations should be compatible with a lower-versioned faces-config.xml file, eg. mojarra 2.3.x should work well with faces-config.xml 2.2(version="2.2" in the namespace declaration.).
  2. Use javax.faces.ENABLE_CDI_RESOLVER_CHAIN(true) in web.xml to enable CDI as InjectionProvider, I think it should be set to true by default in a Java EE 8 application server. Set it to false explicitly only for those guys who do not want to use CDI to handle injection at the moment.

Remember nowdays all of us like the Convention over Configuration rule in project developments. Currently I migrated my sample from Java EE 7 to Java EE 8 and JSF 2.3, it should work without any modification. But I have to add more configuration to make it work, such as @FacesConfig and change bean-discovery-mode to all, it is unreasonable .

@Andrew-Gr

This comment has been minimized.

Copy link

commented Sep 4, 2017

@hantsy I was able to successfully run the empty "hello world" JSF 2.3.2 app on Payara 5 with the bean-discovery-mode="all" in beans.xml and standalone ConfigurationBean , but once I am configuring my target project with the same settings - I am getting issues with CDI.
Looks like adding @FacesConfig(version = FacesConfig.Version.JSF_2_3) to 'problem' beans partially solves the issue, but other exceptions comes during app deployment like:

WARN:   WELD-000146: BeforeBeanDiscovery.addAnnotatedType(AnnotatedType<?>) used for class org.glassfish.jersey.ext.cdi1x.servlet.internal.CdiExternalRequestScope is deprecated from CDI 1.1!
Warning:   The following warnings have been detected: WARNING: Parameter interceptedBean of type javax.enterprise.inject.spi.Bean<?> from private javax.enterprise.inject.spi.Bean<?> org.glassfish.soteria.cdi.LoginToContinueInterceptor.interceptedBean is not resolvable to a concrete type.

Warning:   The following warnings have been detected: WARNING: Parameter interceptedBean of type javax.enterprise.inject.spi.Bean<?> from private javax.enterprise.inject.spi.Bean<?> org.glassfish.soteria.cdi.RememberMeInterceptor.interceptedBean is not resolvable to a concrete type.

Severe:   Exception during lifecycle processing
org.glassfish.deployment.common.DeploymentException: CDI deployment failure:WELD-001408: Unsatisfied dependencies for type LocaleBean with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private local.test.beans.PageBean._localeBean
  at local.test.beans.PageBean._localeBean(PageBean.java:0)
WELD-001475: The following beans match by type, but none have matching qualifiers:
  - Managed Bean [class local.test.beans.LocaleBean] with qualifiers [@Any @FacesConfig @Named]

Where PageBean something like:

import javax.faces.annotation.FacesConfig;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;

@Named
@ViewScoped
@FacesConfig(version = FacesConfig.Version.JSF_2_3)
public class PageBean implements Serializable {
    @Inject
    private LocaleBean _localeBean;
}

And LocaleBean something like:

@Named
@SessionScoped
@FacesConfig(version = FacesConfig.Version.JSF_2_3)
public class LocaleBean implements Serializable {
    ...
}

So now I am trying to understand is it a part of the same issue discussed here, or this is something not related to this topic...
P.S. all changes are done in the absolutely stable code, which works fine in JSF 2.2 mode...

EDIT 1: Okay, looks like I need to add "@FacesConfig(version = FacesConfig.Version.JSF_2_3)" to separate standalone "fresh" java class, not to the existing CDI bean.

EDIT 2: removed exception content as looks like it is not really related to the issue discussed here.

@arjantijms

This comment has been minimized.

Copy link
Collaborator

commented Sep 4, 2017

@hantsy

BTW, It seems mojarra development is inactive in these months, from the Github commit logs, there are no resources on processing issues from reporters.

Indeed, it's a little inactive. Not because of disinterest or anything, but simply a matter of time. I'm personally very busy with preparing Payara 5, of which we're planning to release the first alpha this week.

Especially the Mojarra 2.4 branch was hanging mid-development (I had to flush out my changes when we moved from java.net to GitHub) and it's high on my TODO level to resume that, but there are always higher level items popping up :(

@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 4, 2017

@arjantijms Understood.

@Toberumono

This comment has been minimized.

Copy link

commented Sep 19, 2017

@xinyuan-zhang, I didn't see this answered, but I had the same issue, and I worked out why adding @FacesConfig to a bean fixes the CDI issue. Essentially, in CdiExtension's collect method, it looks up all beans with the @FacesConfig annotation on them and, provided that the last bean found with that annotation has its value set to at least Version.JSF_2_3, it sets a flag on itself (CdiExtension) which is checked in a couple of places. In this case, the two important ones are the afterBean method in CdiExtension (where it is referenced as a field) and ELUtils#tryAddCDIELResolver (where it is referenced via the getter).

In CdiExtension#afterBean, it loads the CdiProducer-based implementations of the implicit JSF objects (i.e. "request", "session", etc) if the flag is true. While this does not have a direct effect on loading other beans, it is important when considering the new injection features.

Similarly, in ELUtils#tryAddCDIELResolver, it will only add the CDI BeanManager-based ELResolver if the flag is true. Thus, if the @FacesConfig annotation is not present on at least one resolved bean, the CDI BeanManager-based EL resolver is not added to the chain, and, as a result, any beans that were discovered purely through CDI annotations (i.e. those that are in the BeanManager) will not be resolved.

@arjantijms

This comment has been minimized.

Copy link
Collaborator

commented Sep 19, 2017

@Toberumono Your observation is correct.

The major problem is that JSF 2.3 by default runs in a pseudo JSF 2.2 mode (a kind of JSF 2.2 compatibility mode). To make it truly JSF 2.3 you need to switch it to JSF 2.3 via the @FacesConfig annotation with, indeed, version 2.3.

@Andrew-Gr

This comment has been minimized.

Copy link

commented Sep 23, 2017

@arjantijms is it any plans for JSF 2.3.3 to be release in the nearest future with your latest changes on this? Thanks! Edit: ...ah, I see: JSF 2.3.3 -> Due by October 4, 2017. Okay, look forward to having it released soon! )

@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 23, 2017

I hope in Java EE 8 compatible environment(eg. Glassfish 5, it was just released) JSF 2.3 should be enabled by default, no need global @FacesConfig or adding it every beans, and also should free my CDI settings (both annotated or all discovery mode should work, in a Java EE 8 application, CDI is not just for JSF ).

And for those cases who want to use JSF 2.3 with Java EE 7 or Servlet 3.1 container, maybe @FacesConfig is an option. Currently I do not care about this case.

@Andrew-Gr

This comment has been minimized.

Copy link

commented Sep 23, 2017

@hantsy first of all thank you for mentioning that GF 5 was released - I haven't noticed that! Re "JSF 2.3 enabled by default in GF 5" - are you sure about that? ) ...didn't have time to check it, will start practicing with GF5 from tomorrow by moving my apps to it.

@arjantijms

This comment has been minimized.

Copy link
Collaborator

commented Sep 23, 2017

@hantsy

I hope in Java EE 8 compatible environment(eg. Glassfish 5, it was just released), JSF 2.3 is enabled by default,

Unfortunately, this is not the case. In a full or web profile Java EE 8 environment the specification says that JSF should by default run into this 2.2 pseudo compatibility mode. I'm personally not a fan of this either. For Payara, but only for Payara, I may be able to make 2.3 the default.

no need global @facesconfig

Don't forget that you always need something to enable JSF. Like a FacesServlet mapping in web.xml, an (empty) faces-config.xml, or the use of any one of the JSF specific annotations.

Next to the empty faces-config.xml, the @FacesConfig annotation is one of the simplest ways to activate JSF. You can have JSF activated with that without any web.xml present.

Note also that JAX-RS needs an activating annotation as well

@hantsy

This comment has been minimized.

Copy link
Author

commented Sep 23, 2017

Don't forget that you always need something to enable JSF. Like a FacesServlet mapping in web.xml, an (empty) faces-config.xml, or the use of any one of the JSF specific annotations.

If there is a @FacesConfig annotated class can configure JSF and replace the faces-config.xml, I think it is better.

Note also that JAX-RS needs an activating annotation as well

You mean the @ApplicationPath annotated Application class? but this class provides some custom room by overriding the methods.

@omolenkamp

This comment has been minimized.

Copy link

commented Oct 6, 2017

@arjantijms

The major problem is that JSF 2.3 by default runs in a pseudo JSF 2.2 mode (a kind of JSF 2.2 compatibility mode). To make it truly JSF 2.3 you need to switch it to JSF 2.3 via the @facesconfig annotation with, indeed, version 2.3.


> ~~~JSF 2.3 is fully backward compatible with previous releases of JSF unless a CDI managed bean is included in the application with the annotation @javax.faces.annotation.FacesConfig.~~~

Never mind, it looks like it -is- working as expected when a faces-config.xml with version="2.2" is used; resolving `@Named` beans only stops working when version="2.3" is used without also adding `@FacesConfig`. A bit weird (I'd expect version="2.3" to either activate the 2.3 features, or to do nothing without `@FacesConfig`), but workable.
@hantsy

This comment has been minimized.

Copy link
Author

commented Oct 6, 2017

@omolenkamp When you change the version to 2.2 in faces-config.xml, all of the new features added in JSF 2.3 are worked(such as websocket, datetime, inject in converter, cdi alignment, el in facelets etc) ?

@arjantijms

This comment has been minimized.

Copy link
Collaborator

commented Oct 6, 2017

@nAmed beans only stops working when version="2.3" is used without also adding @FacesConfig. A bit weird (I'd expect version="2.3" to either activate the 2.3 features, or to do nothing without @FacesConfig), but workable.

That's because of a very unfortunate bug that somehow went unnoticed despite all the testing that we did. I fixed it here: 9662b55

Hoping to release 2.3.3 soon with the help of @ren-zhijun-oracle and @edburns . This bug causes a lot of confusion really. If you have the time, please try building 2.3.3-SNAPSHOT and see if that works for you.

@arjantijms

This comment has been minimized.

Copy link
Collaborator

commented Oct 9, 2017

Hi, @xinyuan-zhang just did the 2.3.3 release. You can find the notes here: https://github.com/javaserverfaces/mojarra/releases/tag/2.3.3

Thanks @xinyuan-zhang

@arjantijms

This comment has been minimized.

Copy link
Collaborator

commented Oct 10, 2017

@hantsy

That should definitely not have any influence. @FacesConfig is an annotation that's only read by a CDI Extension to enable a certain amount of build-in beans. Repeating it for multiple classes should have no effect. You might want to take a look at the Mojarra tests for this feature and see where it differs with your code.

@hantsy

This comment has been minimized.

Copy link
Author

commented Oct 11, 2017

@arjantijms Thanks. Checked out the source codes of mojarra.

@edburns

This comment has been minimized.

Copy link
Collaborator

commented Oct 29, 2017

Please see this important message regarding community contributions to
Mojarra.

https://javaee.groups.io/g/jsf-spec/message/30

Also, please consider joining that group, as that group has taken the
place of the old dev@javaserverfaces.java.net mailing list.

Thanks,

Ed Burns

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.