我创建了一个ejb
@Stateless
@LocalBean
public class BasitBean {
public String helloBasit() {
return "Basit";
} //end of helloBasit()
} //end of class BasitBean
我从JSF中调用它,如
<h:body>
<h:outputLabel value="#{helloBasit.callBasit()}" />
</h:body>
@ManagedBean
@SessionScoped
public class HelloBasit {
@EJB
private BasitBean basitBean;
/** Creates a new instance of HelloBasit */
public HelloBasit() {
}
public String callBasit() {
return basitBean.helloBasit();
} //end of callBasit()
} //end of class HelloBasit
此代码工作正常。但是当我改变像这样的代码时
<h:body>
<h:outputLabel value="#{helloBasit.label}" />
</h:body>
@ManagedBean
@SessionScoped
public class HelloBasit {
@EJB
private BasitBean basitBean;
String label;
/** Creates a new instance of HelloBasit */
public HelloBasit() {
System.out.println();
String label = basitBean.helloBasit();
System.out.println(label);
}
public BasitBean getBasitBean() {
return basitBean;
}
public void setBasitBean(BasitBean basitBean) {
this.basitBean = basitBean;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
} //end of class HelloBasit
然后我得到了例外
SEVERE: Error Rendering View[/index.xhtml]
com.sun.faces.mgbean.ManagedBeanCreationException: Cant instantiate class: pk.mazars.basitMahmood.HelloBasit.
at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:193)
at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:102)
......
为什么我得到这个例外?当我的页面遇到#{helloBasit.label}
然后我的构造函数调用,实例变量初始化,将bean实例注入basitBean,然后bean方法应该调用时,流程应该是我理解的。但是在这种情况下,我在bean实例中得到null为什么?为什么以前的代码有效,但事实并非如此?如何从构造函数中调用bean?
谢谢。
答案 0 :(得分:7)
尝试将构造函数的内容移动到post构造函数中......
像这样@PostConstruct
private void init() {
System.out.println();
String label = basitBean.helloBasit();
System.out.println(label);
}
因为只有在启动托管bean之后才应该注入ejb bean
构造函数之后运行@PostConstruct
(之后由JSF创建托管bean本身),然后只将EJB注入bean并且可以访问...
答案 1 :(得分:0)
你的想法是正确的,但我看到一些可以解决的问题。
@LocalBean
注释。在这种情况下,无论是否有@LocalBean
注释,您都会产生相同的效果。如果你想让它明确,你可以离开。请参阅this。
确保从@ManagedBean
包中导入@SessionScoped
和javax.faces.bean
。
请看这个工作样本:
<强> EJB 强>
import javax.ejb.Stateless;
@Stateless
public class PersonService {
public String getName() {
return "Cloud Strife";
}
}
托管Bean
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class PersonBean {
@EJB
private PersonService ps;
private String name;
@PostConstruct
public void init() {
name = ps.getName();
}
public String getName() {
return name;
}
}
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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view contentType="text/html">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h1>Welcome, #{personBean.name}</h1>
</h:body>
</f:view>
</html>
如果你的值只应加载一次,比如你的bean构造,总是更喜欢带有@PostConstruct
注释的方法而不是构造函数。
此外,为了在呈现视图之前调用bean方法,您可以使用f:event
标记,例如:
<f:event type="preRenderView" listener="#{personBean.init}" />
我希望它有所帮助!