@PostConstruct 中的 CDI 参数
Posted
技术标签:
【中文标题】@PostConstruct 中的 CDI 参数【英文标题】:CDI params in @PostConstruct 【发布时间】:2011-06-26 17:03:13 【问题描述】:我认为我的问题类似于this,但还没有发现它可以工作
<f:metadata>
<f:viewParam id="id" name="id" value="#detailsBean.id"/>
</f:metadata>
为什么我不能使用 @Named 来执行此操作并使用 CDI:
@Named
@RequestScoped
public class DetailsBean
private Contacts detailsContact;
@EJB
ContactsFacade contactsEJB;
private int id;
public DetailsBean()
System.out.println("details bean called");
@PostConstruct
public void onLoad()
detailsContact = contactsEJB.find(id);
我无法记录 id。
当然,@ManagedProperty 与 CDI 不兼容。
*****更新*****
一些xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="../template.xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="head">
<f:metadata>
<f:viewParam name="paginator" value="#contactsBean.contactsTablePaginator"/>
<f:viewParam name="rows" value="#contactsBean.contactsTableRows"/>
</f:metadata>
</ui:define>
<ui:define name="content">
<p:growl id="growl" showDetail="true"/>
<p:panel id="contactsPanel" >
<h:form id ="contactsForm">
<p:dataTable id="contactsTable" value="#contactsBean.contacts" selection="#detailsBean.detailsContact" var="contacts" widgetVar="contactsTable"
selectionMode="single" rowSelectListener="#contactsBean.rowSelect" rowUnselectListener="#contactsBean.rowUnSelect"
onRowUnselectUpdate="detailsForm" onRowSelectUpdate="detailsForm"
paginator="#contactsBean.contactsTablePaginator" rows="#contactsBean.contactsTableRows" rowsPerPageTemplate="5,10,15,25,50,100"
paginatorTemplate="RowsPerPageDropdown FirstPageLink PreviousPageLink CurrentPageReport NextPageLink LastPageLink">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search:" />
<p:inputText id="globalFilter" onkeyup="contactsTable.filter()" style="width:150px" />
</p:outputPanel>
</f:facet>
<p:column filterStyle="display:none" filterBy="#contacts.name" headerText="Name" style="width:200px">
<h:outputText value="#contacts.name" />
</p:column>
<p:column filterStyle="display:none" filterBy="#contacts.street" headerText="Street" style="width:280px">
<h:outputText value="#contacts.street" />
</p:column>
<p:column filterStyle="display:none" filterBy="#contacts.city" headerText="City" style="width:150px">
<h:outputText value="#contacts.city" />
</p:column>
<p:column filterStyle="display:none" filterBy="#contacts.state" headerText="State" style="width:50px">
<h:outputText value="#contacts.state" />
</p:column>
<p:column filterStyle="display:none" filterBy="#contacts.zip" headerText="Zip" style="width:100px">
<h:outputText value="#contacts.zip" />
</p:column>
<p:column filterStyle="display:none" filterBy="#contacts.country" headerText="Country" style="width:150px">
<h:outputText value="#contacts.country" />
</p:column>
<p:column filterStyle="display:none" filterBy="#contacts.sent" headerText="Sent" style="width:50px">
<h:outputText value="#contacts.sent" />
</p:column>
</p:dataTable>
<p:ajaxStatus >
<f:facet name="start">
<h:graphicImage value="../resources/images/ajax-loader-bar.gif" />
</f:facet>
<f:facet name="complete">
<h:graphicImage value="../resources/images/ajax-loader-bar-still.gif" />
</f:facet>
<f:facet name="default">
<h:graphicImage value="../resources/images/ajax-loader-bar-still.gif" />
</f:facet>
</p:ajaxStatus>
<br />
<p:commandLink value="View All" action="#contactsBean.viewAll" />
<p:commandLink value="Default View" action="#contactsBean.viewDefault" />
<p:commandLink value="Advanced Search" action="search?faces-redirect=true" />
<br />
</h:form>
<br />
</p:panel>
<br />
<br />
<h:form id="detailsForm">
<p:panel id="detailsPanel" visible="#detailsBean.visible" >
<h:panelGrid id="detailsPanelGrid" cellpadding="2" cellspacing="2" columns="3" >
<h:outputText value="Name :" />
<p:inputText id="name" value="#detailsBean.detailsContact.name" style="width:400px" />
<p:message for="name" />
<h:outputText value="Email :" />
<p:inputText id="email" value="#detailsBean.detailsContact.email" style="width:400px" validatorMessage="Must be a valid email address. EX: test@test.com" >
<f:validateRegex pattern="[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+"/>
<p:ajax event="blur" update="emailMsg" />
</p:inputText>
<p:message id="emailMsg" for="email" />
<h:outputText value="Street :" />
<p:inputText id="street" value="#detailsBean.detailsContact.street" style="width:400px" />
<p:message for="street" />
<h:outputText value="City :" />
<p:inputText id="city" value="#detailsBean.detailsContact.city" style="width:400px" />
<p:message for="city" />
<h:outputText value="State :" />
<p:inputText id="state" value="#detailsBean.detailsContact.state" style="width:400px" validatorMessage="Length is greater than 2" >
<f:validateLength maximum="2" />
<p:ajax event="blur" update="stateMsg" />
</p:inputText>
<p:message id="stateMsg" for="state" />
<h:outputText value="Country :" />
<p:inputText id="country" value="#detailsBean.detailsContact.country" style="width:400px" />
<p:message for="country" />
<h:outputText value="Phone :" />
<p:inputText id="phone" value="#detailsBean.detailsContact.phone" style="width:400px"/>
<p:message for="phone" />
<h:outputText value="Guests :" />
<p:inputText id="guests" value="#detailsBean.detailsContact.guests" style="width:400px"/>
<p:message for="guests" />
<h:outputText value="Arrival :" />
<p:calendar id="arrival" value="#detailsBean.detailsContact.arrival" showOn="button" />
<p:message for="arrival" />
<h:outputText value="Departure :" />
<p:calendar id="departure" value="#detailsBean.detailsContact.departure" showOn="button" />
<p:message for="departure" />
<h:outputText value="Message :" />
<p:inputTextarea id="message" effectDuration="30" style="width:400px;height:100px;" value="#detailsBean.detailsContact.message" />
<p:message for="message" />
<h:outputText value="Departure :" />
<p:calendar id="inserted" value="#detailsBean.detailsContact.inserted" showOn="button"/>
<p:message for="inserted" />
<h:outputText value="Sent :" />
<h:selectBooleanCheckbox id="sent" value="#detailsBean.detailsContact.sent" />
<p:message for="sent" />
<br />
</h:panelGrid>
<p:commandButton value="Submit" action="#detailsBean.updateContactDetails" update="contactsForm, growl, stateMsg" />
<p:commandButton value="Close" action="#detailsBean.handleClose" update="contactsForm, detailsForm" />
</p:panel>
</h:form>
</ui:define>
</ui:composition>
更多java代码:
package com.atlanticpkg.view.beans;
import com.atlanticpkg.model.entities.Contacts;
import com.atlanticpkg.util.FacesUtils;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
@Named(value = "detailsBean")
@RequestScoped
public class EditBean
private Contacts detailsContact;
private boolean visible = false;
@Inject
ContactsBean contactsBean;
public EditBean()
@PostConstruct
public void onLoad()
public void handleClose()
this.setVisible(false);
this.setDetailsContact(new Contacts());
public void updateContactDetails()
try
contactsBean.getContactsEJB().edit(detailsContact);
FacesUtils.addMessage(detailsContact.getName() + " was updated successfully!");
catch (Exception e)
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERROR", e.toString()));
甚至更多:
@Named(value = "contactsBean")
@RequestScoped
public class ContactsBean
@Inject
EditBean editBean;
@EJB
private ContactsFacade contactsEJB;
private List<Contacts> contacts = new ArrayList<Contacts>();
private boolean contactsTablePaginator = true;
private int contactsTableRows = 10;
private Contacts selectedContact = new Contacts();
public ContactsBean()
@PostConstruct
public void onLoad()
updateContactsList();
public String viewDefault()
contactsTablePaginator = true;
contactsTableRows = 10;
return "index?faces-redirect=true&includeViewParams=true";
public String viewAll()
contactsTablePaginator = false;
contactsTableRows = 100;
return "index?faces-redirect=true&includeViewParams=true";
public void updateContactsList()
contacts.clear();
contacts = contactsEJB.findAll();
public void rowSelect(SelectEvent event)
editBean.setVisible(true);
editBean.setDetailsContact((Contacts) event.getObject());
public void rowUnSelect(UnselectEvent event)
editBean.setVisible(false);
editBean.setDetailsContact(new Contacts());
inputText 框填充得很好。但是当我点击提交时,它说这些值为空。此代码与 SessionScope 完美配合。
警告:/admin/index.xhtml @104,109 value="#detailsBean.detailsContact.name":目标无法到达,'null' 返回 null javax.el.PropertyNotFoundException: /admin/index.xhtml @104,109 value="#detailsBean.detailsContact.name": 目标不可达,'null' 返回 null
当我选择数据表时,我可以看到它正在调用 EditBean。然后,当我单击提交按钮时,它会再次调用它。
【问题讨论】:
我相信 @PostConstruct 只会在 bean 初始化阶段被调用。因此,您的 onLoad() 方法可能不会被调用。 相关:***.com/questions/4888942/… 这个问题听起来有时值是空的,有时不是,所以看起来 bean 可能没有在需要时加载参数。 【参考方案1】:我遇到了和你完全相同的问题,通过使用外部上下文(包含 GET 参数)而不是 f:viewParam
来解决它。
在您的 @PostConstruct
方法中,只需使用类似的方式获取您的参数
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
【讨论】:
【参考方案2】:生命周期不允许您的方法。
首先,创建 bean(构造函数)。之后,执行依赖注入,然后执行 @PostConstruct
方法,然后评估 JSF 文件。 viewParam
在该文件中。因此,您必须注册另一个在填充视图参数后调用的侦听器。
我有一个@RequestScope
bean 的解决方案,但是如果 bean 的范围更长(比如 View ),那么这个方法在每个请求(包括 AJAX )之后执行,这可能是不需要的。
将此用于请求范围 bean:
<f:metadata>
<f:viewParam id="id" name="id" value="#detailsBean.id"/>
<f:event type="preRenderView" listener="#detailsBean.onLoad" />
</f:metadata>
对于@ViewScope
bean,我正在使用这个“hack”,它有效,但可能不是最佳实践。它做同样的事情,但可能不是正确的方法。
#detailsBean.onLoad()
<f:metadata>
<f:viewParam id="id" name="id" value="#detailsBean.id"/>
</f:metadata>
希望对你有帮助。
编辑:
您在这里使用了很多 AJAX。这个调用必须至少登陆ViewScoped
bean。 View Scope 与RequestScope
类似,但需要更长的时间 - 直到离开页面。
但我还没有全部阅读,有很多代码,如果 ViewScope 没有帮助,那么也许你应该提供一小段有问题的代码,以便有机会找到并专注于真正的问题。
【讨论】:
谢谢。所以看起来 viewParams 更适合 SessionScoped bean?这很有趣,因为我的想法正好相反。我试图为每个页面呈现一个新的 bean,并且没有任何内容从页面到页面。我在想请求范围是最好的方法。我猜不会。当我去更新它时,它仍然没有解决我的其他问题,其中 detailsContact 为空。就像只要点击提交按钮,它就会创建一个新的 detailsContact。我认为请求比这长一点。 @dham:我认为页面的最佳范围是请求或查看(当您使用 AJAX 时)。更长的范围是多余的。使用带有 RequestScope 的事件侦听器很好。你的另一个问题是什么?我找不到它解释。如果你能向我们展示一些代码并描述它会很好,因为我不明白它。 您好,我会用这个问题更新我的帖子。我有数据表,然后我选择一行并将我带到另一个页面。我使用请求范围来使用 EJB 来填充 inputText 字段。我正在使用您向我展示的侦听器方法。这些字段填充得很好,但是当我提交更改时,我收到一个错误,即字段实际上为空。这很奇怪。即使我不去其他页面进行编辑,我也有同样的问题。 是否可以将 ViewScoped 与命名注释一起使用?似乎没有与之合作。我猜我将不得不使用 ManagedBean javax.faces 注释。 @dham 我不知道,我总是使用带有属性名称的 ManagedBean以上是关于@PostConstruct 中的 CDI 参数的主要内容,如果未能解决你的问题,请参考以下文章
JAX-WS 和 CDI 不能在 WAS Liberty Profile 8.5.5.6 上一起工作
使用 CDI 而不是 @ManagedBean: UnproxyableResolutionException 因为超类没有无参数构造函数