【问题标题】:@ManagedProperty null after @PostConstruct in JSF 2.2在 JSF 2.2 中 @PostConstruct 之后的 @ManagedProperty null
【发布时间】:2017-08-27 18:28:14
【问题描述】:

我的规格:

  • 动态 Web 模块 3.1
  • GlassFish Web 扩展 4.0
  • Java 1.8
  • JavaScript 1.0
  • JavaServer Faces 2.2
  • 服务器:glassfish-4.1.1
  • 操作系统:Win 10
  • IDE:版本:Neon.2 Release (4.6.2)

请注意,我已经研究过这个主题并找到了几篇相关的帖子。

例如

@ManagedProperty + @PostConstruct + init() = Nullpointer

@ManagedProperty injected AFTER @PostConstruct

但是,所提出的解决方案都不适合我,也不适用于我的情况。 我不混合 CDI 和/或 JSF 和/或 Spring。它只是 JSF 2.2 注释。

我注入@ManagedProperty("#{country}") Country country;到我的 ChangeCountrySystemEventListener 但 @ManagedProperty 国家的值为空。 我真的不明白问题出在哪里。 Country 构造函数确实被调用了。

有什么提示吗?

这是我的完整代码:

index.xhtml

    <!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:ui="http://xmlns.jcp.org/jsf/facelets"
        xmlns:h="http://xmlns.jcp.org/jsf/html"
        xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <title>Title</title>
    </h:head>
    <h:body>

        <h3><h:outputText value="#{country.name}" /> </h3>
        <h:form>

            <h:commandButton
                id="changeCountryNameBtn"
                value="Change"
                action="result"
                actionListener="#{appBean.changeCountryName}"
             />

        </h:form>
    </h:body>
    </html>

AppBean.java

    package com.test.beans;

    import javax.faces.application.Application;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.SessionScoped;
    import javax.faces.context.FacesContext;
    import javax.faces.event.ActionEvent;

    @ManagedBean
    @SessionScoped
    public class AppBean {

        public void changeCountryName(ActionEvent ev) {

            FacesContext context = FacesContext.getCurrentInstance();
            Application app = context.getApplication();
            app.publishEvent(context, ChangeCountrySystemEvent.class, ev.getSource());
            System.out.println(">>>> AppBean.publishEvent(ChangeCountrySystemEvent) fired... " + ev.getSource());

        }

    }

ChangeCountrySystemEvent.java

    package com.test.beans;
    import javax.faces.event.SystemEvent;

    public class ChangeCountrySystemEvent extends SystemEvent {

        private static final long serialVersionUID = -1587717461942271611L;

        public ChangeCountrySystemEvent(Object source) {
            super(source);
            System.out.println(">>>> ChangeCountrySystemEvent.class :: constructor invoked!");
        }

    }

ChangeCountrySystemEventListener.java

    package com.test.beans;

    import javax.faces.bean.ManagedProperty;
    import javax.faces.context.FacesContext;
    import javax.faces.event.SystemEvent;
    import javax.faces.event.SystemEventListener;

    public class ChangeCountrySystemEventListener implements SystemEventListener {

        @ManagedProperty("#{country}")
        Country country;

        // getters and setters
        public Country getCountry() {
            return country;
        }

        public void setCountry(Country country) {
            this.country = country;
        }

        public ChangeCountrySystemEventListener(FacesContext fc) {
            super();
            System.out.println(">>>> ChangeCountrySystemEventListener.class :: Listener constructor invoked!!!");
        }

        @Override
        public void processEvent(SystemEvent se) {

            if (country != null) {
                country.setName("Sweden");
                System.out.println(">>>> ChangeCountrySystemEventListener.class :: SYSTEM EVENT PROCESSED... <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ");
            } else if (country == null) {
                System.out.println(">>>> ChangeCountrySystemEventListener.class :: processEvent() > country managed property is EMPTY !!!!");
            }
        }

        @Override
        public boolean isListenerForSource(Object source) {
            return true; // needs to be set to true, otherwise "processEvent" won't be called...
        }

    }

Country.java

    package com.test.beans;

    import javax.annotation.PostConstruct;
    import javax.faces.application.Application;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.SessionScoped;
    import javax.faces.context.FacesContext;

    @ManagedBean(name = "country", eager = true)
    @SessionScoped
    public class Country {

        private String name = "Norway";

        public Country() {
            System.out.println(">>>> Country constructor called...");
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @PostConstruct
        public void init() {
            FacesContext fc = FacesContext.getCurrentInstance();
            Application app = fc.getApplication();
            app.subscribeToEvent(ChangeCountrySystemEvent.class, new ChangeCountrySystemEventListener(fc));
            System.out.println(">>>> Country.class :: app.subscribeToEvent() called... ");
        }
    }

控制台输出:

2017-04-02T21:49:51.392-0300|Info: JSF_TestProject was successfully deployed in 579 milliseconds.
2017-04-02T21:49:52.251-0300|Info: >>>> Country constructor called...
2017-04-02T21:49:52.277-0300|Info: >>>> ChangeCountrySystemEventListener.class :: Listener constructor invoked!!!
2017-04-02T21:49:52.277-0300|Info: >>>> Country.class :: app.subscribeToEvent() called...
2017-04-02T21:50:16.572-0300|Info: >>>> ChangeCountrySystemEvent.class :: constructor invoked!
2017-04-02T21:50:16.572-0300|Info: >>>> ChangeCountrySystemEventListener.class :: processEvent() > country managed property is EMPTY !!!!
2017-04-02T21:50:16.572-0300|Info: >>>> AppBean.publishEvent(ChangeCountrySystemEvent) fired... javax.faces.component.html.HtmlCommandButton@424c250c

【问题讨论】:

    标签: jsf jsf-2 glassfish


    【解决方案1】:

    ManagedProperty 可用于使用 ManagedBean 注解的类的字段上,以将值注入此属性。

    如果此注解出现在没有 ManagedBean 注解的类上,则实现不得对此注解采取任何行动。

    请看http://docs.oracle.com/javaee/6/api/javax/faces/bean/ManagedProperty.html

    由于类 ChangeCountrySystemEventListener 没有使用 ManagedBean 注释,因此不会对 ManagedProperty 字段 country 及其 null 采取任何操作。

    【讨论】:

    • 感谢您的回复。不幸的是,添加 ManagedBean 注释(甚至 SessionScoped)并不能解决问题。即使所有四个类(AppBean、ChangeCountrySystemEvent、ChangeCountrySystemEventListener、Country)都使用 ManagedBean 进行了注释,问题仍然存在。
    • 请在监听器中使用下面的代码来访问国家管理的bean。
    • country = (Country) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("country");
    • 非常感谢。您提出的解决方案对我有用。 :)
    猜你喜欢
    • 2011-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多