0

在我尝试修复非标准名称之前,视图和 bean 一直在工作,现在我已经断开了两者之间的联系。奇怪的是,“返回”按钮有正确的链接,但内容没有显示,也没有记录。为什么 Detail.getComments() 不执行?

我一直在阅读焊接文档并试图更好地理解@Inject。似乎也存在我不理解的生命周期问题。如果它不是生命周期,那么我什至无法推测为什么 Detail.getComments() 从未在 glassfish 日志中显示:

INFO: MessageBean.getModel..
INFO: SingletonNNTP.returning messages..
INFO: MessageBean.getModel..
INFO: SingletonNNTP.returning messages..
INFO: MessageBean.getModel..
INFO: SingletonNNTP.returning messages..
INFO: Detail..
INFO: Detail.getId..null
INFO: Detail.getId..SETTING DEFAULT ID
INFO: Detail.onLoad..2000
INFO: Detail.getId..2000
INFO: Detail.getId..2000
INFO: Detail.setId..2000
INFO: Detail.getId..2019
INFO: ..Detail.setId 2019
INFO: Detail.back..
INFO: Detail.getId..2019
INFO: ..Detail.back 2,018
INFO: Detail.getId..2019

值 2000 是默认值,仅在 id==null 时才会发生,它永远不会发生这种情况。它应该立即引入该属性。所以,我不确定这是否是范围(我现在才发现 CDI 不支持 @SessionScoped)、生命周期或其他问题。也许我需要在那个变量上使用@Inject?

视图,detail.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:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
    <body>
        <f:metadata>
            <f:viewParam name="id" id="id" value="#{detail.id}" />
        </f:metadata>
        <ui:composition template="./complexTemplate.xhtml">
            <ui:define name="top">
                <h:link value="back" outcome="detail" includeViewParams="true">
                    <f:param name="id" value="#{detail.back}"/>
                </h:link>
            <ui:define name="content">
                <h:outputText value="#{detail.content}" rendered="false"/>
            </ui:define>
            <ui:define name="bottom">
                bottom
            </ui:define>
        </ui:composition>
    </body>
</html>

和支持bean:

package net.bounceme.dur.nntp;

import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;
import javax.mail.Message;

@Named
@ConversationScoped
public class Detail  implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final Logger logger = Logger.getLogger(Detail.class.getName());
    private static final Level level = Level.INFO;
    private String id = null;       //should never get default value in getter
    private Message message = null;
    private SingletonNNTP nntp = SingletonNNTP.INSTANCE;
    private String forward = null;  //id + 1
    private String back = null;     //id - 1
    private String content = null;  //message.content

    public Detail() {
        logger.log(level, "Detail..");
    }

    @PostConstruct
    private void onLoad() {
        logger.log(level, "Detail.onLoad..{0}", getId());
    }

    public Message getMessage() {
        logger.log(level, "Detail.getMessage..");
        return message;
    }

    public void setMessage(Message message) {
        logger.log(level, "Detail.setMessage..");
        this.message = message;
    }

    public String getId() {
        logger.log(level, "Detail.getId..{0}", id);
        if (id == null) {
            logger.log(level, "Detail.getId..SETTING DEFAULT ID");
            id = String.valueOf(2000);
        }
        return id;
    }

    public void setId(String id) throws Exception {
        logger.log(level, "Detail.setId..{0}", getId());
        this.id = id;
        logger.log(level, "..Detail.setId {0}", getId());
    }

    public String getForward() {
        logger.log(level, "Detail.forward..");
        int f = Integer.parseInt(getId());
        f = f + 1;
        logger.log(level, "..Detail.forward {0}", f);
        forward = String.valueOf(f);
        return forward;
    }

    public void setForward(String forward) {
        this.forward = forward;
    }

    public String getBack() {
        logger.log(level, "Detail.back..");
        int b = Integer.parseInt(getId());
        b = b - 1;
        logger.log(level, "..Detail.back {0}", b);
        back = String.valueOf(b);
        return back;
    }

    public void setBack(String back) {
        this.back = back;
    }

    public String getContent() throws Exception {
        logger.log(level, "Detail.getContent..{0}", getId());
        message = nntp.getMessage(Integer.parseInt(getId()));
        content = message.getContent().toString();
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

根据上面的日志,它似乎从未调用过 Detail.getContent(),尽管它是视图的一部分: <h:outputText value="#{detail.content}" rendered="false"/>

奇怪的是,在我更改此类以更好地遵循命名约定之前调用了 Detail.content()。我正在阅读一些WeldOracle Java EE 6 文档,但完全不介意被引导到一本精美的手册。我发现描述这一点的文档总是使用@ManagedBeans,但是我不是。正如@Kawu在这个答案中所描述的,似乎有很多陷阱。

在 id 字段中添加 @Inject 会导致部署错误:

init:
deps-module-jar:
deps-ear-jar:
deps-jar:
library-inclusion-in-archive:
library-inclusion-in-manifest:
compile:
compile-jsps:
In-place deployment at /home/thufir/NetBeansProjects/NNTPjsf/build/web
Initializing...
deploy?DEFAULT=/home/thufir/NetBeansProjects/NNTPjsf/build/web&name=NNTPjsf&contextroot=/NNTPjsf&force=true failed on GlassFish Server 3.1.2 
 Error occurred during deployment: Exception while loading the app : WELD-001408 Unsatisfied dependencies for type [String] with qualifiers [@Default] at injection point [[field] @Inject private net.bounceme.dur.nntp.Detail.id]. Please see server.log for more details.
/home/thufir/NetBeansProjects/NNTPjsf/nbproject/build-impl.xml:749: The module has not been deployed.
See the server log for details.
BUILD FAILED (total time: 9 seconds)

当然,注入 String 不是问题,也许是bug

4

1 回答 1

4

我理解你的挫败感,我认为问题更多的是你的设置/理解。但是,仍然很难找到任何真正的问题来回答,也许您下次可以尝试拆分您的问题。

以下是一些答案:

为什么 Detail.getComments() 不执行?

嗯,也许是因为它不在豆子里?我猜你正在重新考虑detail.getContent

根据上面的日志,它似乎从未调用过 Detail.getContent(),尽管它是视图的一部分:

试试rendered = true:-)

@PostConstruct
private void onLoad() {
    logger.log(level, "Detail.onLoad..{0}", getId());
}

您已经在 getter 中加入了大量的逻辑。尝试使用现场调试,而不是使用吸气剂...

值 2000 是默认值,仅在 id==null 时才会发生,它永远不会发生这种情况。

看起来这private String id = null;是一个完美的解释为什么 id将为空。

请记住,JSF、CDI 和 Java EE 等现代框架在幕后做了很多工作,使用反射、代理和拦截器。例如,不要依赖于对何时(以及多久)调用构造函数的经典理解。

同样,考虑将初始化逻辑从 getter 移开。@PostConstruct 将是 Java EE 规范之父为其选择的地方。

老实说:看起来没有什么特别错误的,但是你的代码有点乱,而且非常难以理解和遵循。

尝试删除像这样的所有间接...

int b = Integer.parseInt(getId());

...一切都会看起来好多了。

哦,你为整个班级声明一个固定的日志级别有什么具体原因吗?尝试这样的事情

private static final Logger LOG = Logger.getLogger(Some.class);
...
LOG.info("...");

希望这能给你一个开始。随意发布更多问题,最好短一点,并回答单一、孤立的方面。

于 2012-04-12T14:22:09.550 回答