bean,@ Inject和params的CDI生命周期 [英] CDI lifecycle of bean, @Inject and params

查看:100
本文介绍了bean,@ Inject和params的CDI生命周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试修复非标准名称之前,视图和bean一直有效,现在我断开了两者之间的连接.奇怪的是,后退"按钮具有正确的链接,但是内容既不显示也不记录.为什么Detail.getComments()不执行?

The view and bean were working until I tried to fix non-standard names, and I've now broken the connection between the two. Oddly, the "back" button has the correct link, but content just doesn't show, nor log. Why doesn't Detail.getComments() execute?

我一直在浏览

I've been going through the weld docs and trying to better understand @Inject. There seems to be a lifecycle problem which I don't understand, either. If it's not lifecycle, then I cannot even speculate as to why Detail.getComments() never shows in the glassfish logs:

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?

The value 2000 is a default, which only happens when id==null, which it never should. It should pull in that attribute right away. So, I'm not sure whether that's a problem with the scope (I only just now found out that CDI doesn't support @SessionScoped), the lifecycle, or something else. Perhaps I need to use @Inject on that variable?

视图detail.xhtml:

The view, 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"/>

which never seems to have, according to the above logs, Detail.getContent() invoked, despite that being part of the view: <h:outputText value="#{detail.content}" rendered="false"/>

奇怪的是,在我更改此类以更好地遵循命名约定之前,调用了Detail.content().我正在经历一些 Weld Oracle Java EE 6文档,但不要紧定向到精美的手册.我发现描述此文档的文档总是使用@ManagedBeans,但我不是. @Kawu在答案中所述,似乎有很多陷阱.

It's odd in that Detail.content() was getting invoked prior to my changing this class to better follow naming conventions. I'm going through some Weld and Oracle Java EE 6 docs, but don't at all mind being directed to a fine manual. The docs I find describing this are invariably using @ManagedBeans, however, which I am not. There seem many gotchas, as described in this answer by @Kawu.

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

Adding @Inject to the id field causes a deploy error:

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)

当然,注入字符串不是问题,也许是 bug

Surely, injecting a String isn't the problem, perhaps it's a bug.

推荐答案

我理解您的无奈,而我看到的问题更多是您的设置/理解.但是,仍然很难找到任何真正的问题要回答,也许您下次可以尝试分解问题.

I understand your frustration, and I see that the problem is more your setup / understanding in general. But still, it's pretty hard to find any real questions to answer, maybe you can try to split your problems next time.

以下是一些答案:

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

Why doesn't Detail.getComments() execute?

嗯,也许是因为它不在bean中?我猜您是改用detail.getContent吗?

Hm, maybe because it's not in the bean? I guess that you are refrerring to detail.getContent instead?

根据上面的日志,

似乎从来没有, 尽管是视图的一部分,但调用了Detail.getContent():

which never seems to have, according to the above logs, Detail.getContent() invoked, despite that being part of the view:

尝试rendered = true:-)

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

您已经在吸气剂中添加了很多逻辑.尝试使用字段而不是使用getter进行调试...

You've put an awful lot of logic into the getter. Try debugging with the field, not with the getter...

默认值为2000,该值仅在id == null时才会发生,而从不应该.

The value 2000 is a default, which only happens when id==null, which it never should.

private String id = null;似乎是对为什么 为空的完美解释.

It looks like private String id = null; is a perfect explanation why id will be null.

请谨记,诸如JSF,CDI和Java EE之类的现代框架会使用反射,代理和拦截器在幕后做很多事情.例如,不要依赖于经典的理解何时调用构造函数(以及调用频率)的方法.

Try to keep in mind that modern frameworks like JSF, CDI and Java EE do a lot of stuff behind the scenes, using reflection, proxies and interceptors. Don't rely on classical understanding of when (and how often) a constructor is called, for example.

同样,请考虑将初始化逻辑从吸气剂上移开. @PostConstruct将是Java EE规范之父为之选择的地方.

Again, consider moving your initialisation logic away from the getter. @PostConstruct would be the place that the fathers of the Java EE-spec had chosen for it.

说实话:看起来没有什么错,但是您的代码有点混乱,而且很难理解和遵循.

To be honest: Nothing looks extremely wrong, but your code is kind of messy, and extremely hard to understand and to follow.

尝试删除所有这种间接方式...

Try removing all indirections like this one...

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

...一切都会好起来的.

... and everything will look much better.

哦,您为整个类声明一个固定的日志级别有特定的原因吗?尝试这样的事情

Oh, and is there a specific reason why you declare a fixed log-level for the whole class? Try something like this

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

希望可以让您开始.随时发布其他问题,最好是简短一些,而且要回答一个孤立的问题.

Hope that gives you a start. Feel free to post further questions, preferably a bit shorter and with single, isolated aspects to answer.

这篇关于bean,@ Inject和params的CDI生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆