为什么更改托管 bean 的定义会导致未调用构造函数?

Why does altering my managed bean's definition result in the constructor not being called?

请查看以下 JSF 页面及其引用的托管 bean class 的定义。

当我 运行 我的应用程序并加载页面时,我得到 "Good Results" 屏幕截图中显示的结果。请注意,该页面正在显示数据,并且由 bean 的构造函数打印的 "Hello World" 字符串出现在控制台中。

如果我通过注释掉 "junk" 整数(靠近顶部)的定义来更改 bean 的定义,那么我会得到 "Bad Results" 屏幕截图中显示的结果。现在没有数据,最明显的是 "Hello World" 字符串没有出现在控制台中。没有错误报告到控制台。该页面正在呈现,但似乎 JSF 引擎已决定它不喜欢 bean 的定义,因此不会使用它(未调用构造函数)。

我已经竭尽全力制作 Minimal, Complete, and Verifiable example。我从 JSF 页面中删除了几个表单(您可以观察到该 bean 的大部分代码不再被 JSF 页面引用)。我通过创建 DummyDataAccessService class 从图片中删除了 JPA。我试图消除对一个或多个我自己的自定义 classes(Order、Patient、Product、DataAccessService 和 DummyDataAccessService)的使用,但我不能:几乎对 bean 定义的任何更改都会产生相同的奇怪行为删除 "junk" 成员变量的定义的结果。

我创建了一个自定义 logging.properties 文件,将级别提高到全部。好与坏案例产生的日志记录接近相同。下面的两个 "Logging Differences" 屏幕截图揭示了主要区别。

我不知道如何进一步探讨这个问题。我什至不知道会发生什么。任何有关行动方案的线索或建议都将不胜感激。

JSF 页面

<!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>
    <h:outputStylesheet library="default" name="css/style.css"  />
    <title>Managed Bean Problem</title>
</h:head>
<h:body> 
    <h3 class="title">Managed Bean Problem</h3>
    <h:outputText value="&#160;" />

    <table align="center" width="600">
        <tr><td><h:form>
            <h:dataTable value="#{orderController.table}" var="order" styleClass="demo" columnClasses="columns, columns">
                <h:column>
                    <f:facet name="header">
                        <h:column>
                            <h:outputText value="Patient"></h:outputText>
                        </h:column>
                    </f:facet>
                    <h:outputText value="#{order.patient.fullName}"></h:outputText>
                </h:column>

                <h:column>
                    <f:facet name="header">
                        <h:column>
                            <h:outputText value="Product"></h:outputText>
                        </h:column>
                    </f:facet>
                    <h:outputText value="#{order.product.name}"></h:outputText>
                </h:column>

                <h:column>
                    <f:facet name="header">
                        <h:column>
                            <h:outputText value="Actions"></h:outputText>
                        </h:column>
                    </f:facet>
                    <h:panelGrid columns="1">
                        <h:commandLink value="delete" action="#{orderController.delete}">
                            <f:setPropertyActionListener target="#{orderController.target}" value="#{order}" />
                        </h:commandLink>
                    </h:panelGrid>
                </h:column>
            </h:dataTable>
        </h:form></td></tr>
    </table>
</h:body>

订单控制器托管 Bean

package com.rvaessen.dmescripts.controllers;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.model.SelectItem;

import com.rvaessen.dmescripts.model.*;

@ManagedBean
public class OrderController {

private int junk; // Leave it in; Good. Comment it out; Bad.

private DataAccessService dataService = new DummyDataAccessService();

public OrderController() {
    System.out.println("Hello, World");
}

@PostConstruct
public void init() {
    initPatients();
    initProducts();
    initOrders();
}

// ********************************* The Orders Table ***************************************

private Order target;
private List<Order> table;

private void initOrders() { table = dataService.getOrders(); }

public List<Order> getTable() { return table; }

public void setTarget(Order order) { target = order; }

public String delete() {
    dataService.removeOrder(target);
    table.remove(target);
    return null;
}

// ********************************* Add New Order ***************************************
// NOTE: The Add New Order methods are no longer referenced by the JSF page

private Order newOrder;

public String addNew() {
    newOrder = new Order();
    return null;
}

public String save() {
    dataService.addOrder(newOrder, patient, product);
    table.add(newOrder);   
    cancel();

    return null;
}

public String cancel() {
    newOrder = null;
    return null;
}

public boolean getAddingNew() { return newOrder != null; }

/************************ The Patients Menu **********************************/
// NOTE: The Patients Menu methods are no longer referenced by the JSF page

private Patient patient;
private List<Patient> patients;

private void initPatients() {
    patients = dataService.getPatients();
    if (patients.size() > 0) patient = patients.get(0);
}

public List<SelectItem> getPatients() {
    List<SelectItem> list = new ArrayList<SelectItem>();
    patients.forEach(patient -> list.add(new SelectItem(patient.getId(), patient.getFullName())));
    return list;
}

public Long getPatientId() {
    return patient == null ? 0 : patient.getId();
}

public void setPatientId(Long id) {
    patients.forEach(patient -> {
        if (patient.getId() == id) {
            this.patient = patient;
        }
    });
}

/************************ The Products Menu **********************************/
// NOTE: The Products Menu methods are no longer referenced by JSF page

private Product product;
private List<Product> products;

private void initProducts() {
    products = dataService.getProducts();
    if (products.size() > 0) product = products.get(0);
}

public List<SelectItem> getProducts() {
    List<SelectItem> list = new ArrayList<SelectItem>();
    if (patient != null) {
        products.forEach(product -> {
            if (product.getInsurance().equals(patient.getInsurance())) {
                list.add(new SelectItem(product.getId(), product.getName()));
            }
        });
    }
    return list;
}

public Long getProductId() {
    return product == null ? 0 : product.getId();
}

public void setProductId(Long id) {
    products.forEach(product -> {
        if (product.getId() == id) {
            this.product = product;
        }
    });
}
}

好成绩

糟糕的结果

对数差异 1

对数差异 2

这个问题一直没有解决。它是通过从头开始重新创建 Eclipse 项目而消失的;同时升级到 JSF 2.3 / CDI 1.2。