-1

参考我以前的问题,为什么 @PostConstruct 方法不可运行?

glassfish 给出:

INFO: MessageBean..
INFO: MessageBean.getModel..
INFO: SingletonNNTP.getMessages..
INFO: MessageBean.getModel..
INFO: SingletonNNTP.getMessages..
INFO: SingletonNNTP.setIndex..2,205
INFO: SingletonNNTP.setIndex..2,205
INFO: SingletonNNTP.setIndex..2,206
INFO: SingletonNNTP.setIndex..2,206
INFO: SingletonNNTP.setIndex..2,207
INFO: SingletonNNTP.setIndex..2,207
INFO: SingletonNNTP.setIndex..2,208
INFO: SingletonNNTP.setIndex..2,208
INFO: SingletonNNTP.setIndex..2,209
INFO: SingletonNNTP.setIndex..2,209
INFO: SingletonNNTP.setIndex..2,210
INFO: SingletonNNTP.setIndex..2,210
INFO: SingletonNNTP.setIndex..2,211
INFO: SingletonNNTP.setIndex..2,211
INFO: SingletonNNTP.setIndex..2,212
INFO: SingletonNNTP.setIndex..2,212
INFO: SingletonNNTP.setIndex..2,213
INFO: SingletonNNTP.setIndex..2,213
INFO: SingletonNNTP.setIndex..2,214
INFO: SingletonNNTP.setIndex..2,214
INFO: SingletonNNTP.setIndex..2,215
INFO: SingletonNNTP.setIndex..2,215
INFO: MessageBean.getModel..
INFO: SingletonNNTP.getMessages..
INFO: Detail..
WARNING: /foo/detail.xhtml @9,67 value="#{detail.id}": org.jboss.weld.exceptions.WeldException: WELD-000049 Unable to invoke [method] @PostConstruct public net.bounceme.dur.nntp.Detail.configBean() on net.bounceme.dur.nntp.Detail@c8e43a
javax.el.ELException: /foo/detail.xhtml @9,67 value="#{detail.id}": org.jboss.weld.exceptions.WeldException: WELD-000049 Unable to invoke [method] @PostConstruct public net.bounceme.dur.nntp.Detail.configBean() on net.bounceme.dur.nntp.Detail@c8e43a
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
    at javax.faces.component.UIOutput.getValue(UIOutput.java:169)
    at javax.faces.component.UIInput.validate(UIInput.java:972)
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1233)
    at javax.faces.component.UIInput.processValidators(UIInput.java:698)
    at javax.faces.component.UIViewParameter.processValidators(UIViewParameter.java:273)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214)
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1172)
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1542)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:849)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:746)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1045)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:228)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:722)
Caused by: org.jboss.weld.exceptions.WeldException: WELD-000049 Unable to invoke [method] @PostConstruct public net.bounceme.dur.nntp.Detail.configBean() on net.bounceme.dur.nntp.Detail@c8e43a
    at org.jboss.weld.bean.AbstractClassBean.defaultPostConstruct(AbstractClassBean.java:508)
    at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.postConstruct(ManagedBean.java:174)
    at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:291)
    at org.jboss.weld.context.AbstractContext.get(AbstractContext.java:107)
    at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:90)
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:79)
    at net.bounceme.dur.nntp.Detail$Proxy$_$$_WeldClientProxy.getId(Detail$Proxy$_$$_WeldClientProxy.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:363)
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:138)
    at com.sun.el.parser.AstValue.getValue(AstValue.java:183)
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:224)
    at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50)
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
    ... 38 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:264)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:52)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:137)
    at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:260)
    at org.jboss.weld.introspector.jlr.WeldMethodImpl.invoke(WeldMethodImpl.java:174)
    at org.jboss.weld.bean.AbstractClassBean.defaultPostConstruct(AbstractClassBean.java:506)
    ... 56 more
Caused by: java.lang.NumberFormatException: null
    at java.lang.Integer.parseInt(Integer.java:454)
    at java.lang.Integer.parseInt(Integer.java:527)
    at net.bounceme.dur.nntp.Detail.configBean(Detail.java:29)
    ... 66 more

INFO: Detail..

我之前得到了更好的输出,其中 bean 被实例化但使用默认值并且没有及时获取 URL 参数,因此一些字段被填充而一些没有。

如果我的 Java 代码不清楚,请告诉我不清楚的地方。例如,我知道没有更好的方法将字符串解析为整数。请参阅此处的评论。

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 LOG = Logger.getLogger(Detail.class.getName());
    private String id = null;
    private Message message = null;
    private SingletonNNTP nntp = SingletonNNTP.INSTANCE;
    private int forward = 0;
    private int back = 0;

    public Detail() {
        LOG.info("Detail..");
    }

    @PostConstruct
    public void configBean() {
        int intId = Integer.parseInt(id);
        try {
            nntp.setIndex(intId);
            message = nntp.getMessage();
        } catch (Exception ex) {
            LOG.info("Detail.configBean..failed to set message");
        }
        setForward(intId + 1);
        setBack(intId - 1);
    }

    public Message getMessage() throws Exception {
        LOG.info("Detail.getMessage.." + getId());
        return message;
    }

    public void setMessage(Message message) {
        LOG.info("Detail.setMessage..");
        this.message = message;
    }

    public String getId() throws Exception {
        LOG.info("Detail.getId.." + id);
        if (id == null) { //should never be null, should get from URL as param
            LOG.info("..setting default id");
            id = String.valueOf(2000);
        }
        return id;
    }

    public void setId(String id) throws Exception {
        LOG.info("Detail.setId.." + id);
        this.id = id;
    }

    public int getForward() throws Exception {
        LOG.info("Detail.getForward.." + forward);
        return forward;
    }

    public void setForward(int forward) {
        LOG.info("Detail.setForward.." + forward);
        this.forward = forward;
    }

    public int getBack() throws Exception {
        LOG.info("Detail.setBack.." + back);
        return back;
    }

    public void setBack(int back) {
        LOG.info("Detail.setBack.." + back);
        this.back = back;
    }
}

和观点:

<?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">
                <div style="float: left">
                    <h:link value="back" outcome="detail" includeViewParams="true">
                        <f:param name="id" value="#{detail.back}"/>
                    </h:link>
                </div>
                <div style="float: right">
                    <h:link value="forward" outcome="detail" includeViewParams="true">
                        <f:param name="id" value="#{detail.forward}"/>
                    </h:link>
                </div>
                <p align="center"><h:outputText value="#{detail.message.messageNumber}" /></p>
            </ui:define>
            <ui:define name="left">
                <h:outputText value="#{detail.message.sentDate}" /><p/>
                <h:outputText value="#{detail.message.subject}"/><p/>
            </ui:define>
            <ui:define name="right">
            </ui:define>
            <ui:define name="content">
                <h:outputText value="#{detail.message.content}" escape="false"/>
            </ui:define>
            <ui:define name="bottom">
            </ui:define>
        </ui:composition>
    </body>
</html>

我对此的看法是,在 @PostConstruct 之后调用将 URL 参数作为方法参数的 getter/setter 方法,导致 bean 处于不确定状态。bean 已被实例化,但尚未使用 URL 参数中的值初始化字段。这一点,我无法确定 bean 是否已使用 URL 参数初始化。

以前我有输出,这更清楚,但目前我只能产生这个错误。

出于实际目的,我刚刚将@PostConstruct 方法的内容移动到 Detail.setId(String),这至少有效。查看 oracle文档,我只是没有直接看到这一点,但是我从这些文档中得出的含义是使用转换器,这也是之前建议的。

我更好奇而不是实际实现一个转换器,因为它似乎是一种非常复杂的方式来做一件简单的事情。但是,@PostConstruct 中的“逻辑”正确地属于转换器吗?

上面的代码不是我实际使用的,它只是针对这个问题,这就是为什么“逻辑”起作用的原因,不是在 @PostConstruct 方法中,而是在 setId() 方法中。

4

1 回答 1

3

尝试使用 @PostConstruct 毫无意义,因为据我所知,该方法在读取参数的 CDI 魔术之前执行。

哎呀,那么规范一定是错误的:) 伙计,您的代码看起来很乱,您的项目设置可能也是如此?

于 2012-04-13T08:47:12.923 回答