![](/img/trans.png)
[英]Instance null after injecting @SessionScoped CDI bean into a JSF @ManagedBean
[英]After migration from JSF @ManagedBean to CDI @Named, constructor called multiple times and submitted input values always null
編輯:評論部分解決了我的問題! 問題是我對Scopes使用了錯誤的導入。
我有一個簡單的JSF應用程序(登錄,從數據庫中提取數據,允許用戶編輯數據)。 它運行良好,我想更新代碼使用CDI(Weld),但我遇到了麻煩。 我正在關注/查看: http://docs.jboss.org/weld/reference/latest/en-US/html/example.html
: http://docs.jboss.org/weld/reference/latest/en-US/html/example.html
沒有焊接的原始內容:
login.xhtml
<h:form id="inputForm">
<h:panelGrid columns="2" cellpadding="5" cellspacing="1">
<h:outputText id="nameDesc" value="Name"></h:outputText>
<h:inputText id="nameInput" value="#{login.loginName}" binding="#{name}"></h:inputText>
<h:outputText id="passwordDesc" value="Password"></h:outputText>
<h:inputSecret id="passwordInput" value="#{login.password}" binding="#{password}"></h:inputSecret>
</h:panelGrid>
<h:commandButton value="Login" action="#{login.login(name.value, password.value)}"/>
</h:form>
LoginBean.java:
@ManagedBean(name="login")
@SessionScoped
public class LoginBean implements Serializable {
private static final long serialVersionUID = 1L;
@ManagedProperty(value="#{db}")
private DatabaseBean db;
private String password;
private String loginName;
// other stuff and functions
public String getLoginName () {
return loginName;
}
public void setLoginName (String name) {
this.loginName = name;
}
public String getPassword () {
return password;
}
public void setPassword (final String password) {
this.password = password;
}
public void setDb(DatabaseBean db) {
this.db = db;
}
DatabaseBean.java:
@ManagedBean(name="db", eager=true)
@ApplicationScoped
public class DatabaseBean implements Serializable {
@PostConstruct
public void init() {
//... connect to database etc
}
}
---------我試圖讓它與Weld一起運行(僅從上面進行更改以使其更短):-------- LoginBean.java,從@ManagedBean更改為@Named ,為DatabaseBean添加了@Inject
@Named("login")
@SessionScoped
public class LoginBean implements Serializable {
// stuff
private @Inject DatabaseBean db;
}
DatabaseBean.java,從@ManagedBean更改為@Named:
@Named("db")
@ApplicationScoped
public class DatabaseBean implements Serializable {
}
LoginBean有一個函數:
public String login(String name, String password) {
System.out.println("login called"+name);
// other stuff
}
在我的第二個實現(我嘗試使用Weld的那個)中,print被調用一次:“login called”,用戶名為空(我用name.IsEmpty()檢查了它)。
我也嘗試過構造函數注入它:
loginBean.java
@Inject
public LoginBean(DatabaseBean db) {
System.out.println("constructor");
this.db = db;
}
當我這樣做時,我得到了很多“構造函數”打印,因此它被調用了好幾次,但我不明白為什么 - 我想這是問題,但只有一個LoginBean實例獲取輸入(用戶名和密碼)然后由於某種原因創建了許多新的。 這是為什么?
我使用Eclipse和Tomcat8來運行它。 謝謝你的閱讀!
托管bean構造函數多次調用
在生成/創建增強的子類/代理時,CDI可能比預期更頻繁地調用構造函數。 另請參見Field.get(obj)返回注入的CDI托管bean上的所有空值,而手動調用getter則返回正確的值 。 只是不要記錄構造函數調用,它只會讓自己迷惑。 @PostConstruct
是唯一有趣的方法。
print被調用一次:“login called”,用戶名為空(我用name.IsEmpty()檢查了這個)。
至於調用action方法時表單輸入值為null
的具體問題,因此@SessionScoped
CDI托管bean似乎在每次訪問時都會重新創建,這與@Dependent
作用域bean的行為相匹配。 當找不到有效的CDI托管bean作用域時,這是默認作用域。 另請參見JSF 2應用程序中的默認Managed Bean Scope是什么?
這反過來表明您從錯誤的包中導入了@SessionScoped
。 確保它來自javax.enterprise.context
包,而不是來自例如javax.faces.bean
。 JSF托管bean作用域無法識別為有效的CDI托管bean作用域。
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
@Named("login")
@SessionScoped
public class LoginBean implements Serializable {
// ...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.