我有以下托管bean:
@ApplicationScoped
public class ApplicationBean {
// ...
}
@SessionScoped
public class SessionBean implements Serializable {
@ManagedProperty("#{applicationBean}")
private ApplicationBean applicationBean;
// ...
}
将其部署到具有多个节点的服务器群集。当HTTP会话在另一个节点上序列化时会发生什么?
ApplicationBean
未序列化,因为它未实现Serializable
。它会被@ManagedProperty
重新注入吗?或者它会以某种方式实际序列化?
答案 0 :(得分:12)
当HTTP会话将在另一个节点上序列化时会发生什么?
所有HTTP会话属性也将被序列化,包括会话范围的JSF托管bean。将跳过任何不可序列化的bean属性。在另一个节点上反序列化期间,您将在所有不可序列化的bean属性上面临NotSerializableException
。标记属性transient
将修复该异常,但在反序列化后该属性仍将保留null
。
是否会被@ManagedProperty重新注入?或者它会以某种方式实际序列化?
不。它不会被重新注入。在@ManagedProperty
的情况下,您必须手动处理此问题。
一种有点幼稚且容易出错的方法是摆脱@ManagedProperty
并在getter中执行延迟加载(因此,自己就像代理一样):
private transient ApplicationBean applicationBean;
public ApplicationBean getApplicationBean() {
if (applicationBean == null) {
FacesContext context = FacesContext.getCurrentInstance();
applicationBean = context.getApplication().evaluateExpressionGet(context, "#{applicationBean}", ApplicationBean.class);
}
return applicationBean;
}
并在整个代码中使用getter,而不是直接引用该属性。
更好的方法是使其成为EJB或CDI托管bean。它们完全透明地创建并作为可序列化代理注入,您永远不必担心它们的序列化。
因此,要么使它成为EJB:
import javax.ejb.Singleton;
@Singleton
public class ApplicationBean {
// ...
}
import javax.ejb.EJB;
import.javax.faces.bean.ManagedBean;
import.javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class SessionBean implements Serializable {
@EJB
private ApplicationBean applicationBean;
// ... (no setter/getter necessary!)
}
或者,将它们作为CDI托管bean:
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
@Named
@ApplicationScoped
public class ApplicationBean {
// ...
}
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@SessionScoped
public class SessionBean implements Serializable {
@Inject
private ApplicationBean applicationBean;
// ... (also here, no setter/getter necessary!)
}
答案 1 :(得分:0)
我正面临类似的问题。
我有一个Quartz调度程序,每x秒运行一次。
Quartz的Job更新了我的应用程序作用域bean中的项目列表。
我使用下面显示的静态方法获取应用程序bean。
当我部署应用程序时,它运行良好,但是当用户输入Web应用程序时,FacesContext.getCurrentInstance()始终返回null。
public static <T> T getBean(final String beanName, final Class<T> beanClass) {
FacesContext facesContext = FacesContext.getCurrentInstance();
T result = null;
if (facesContext != null) {
Application application = facesContext.getApplication();
if (application != null) {
String expresionBeanName = "#{" + beanName + "}";
result = application.evaluateExpressionGet(facesContext, expresionBeanName, beanClass);
}
}
return result;
}
@ManagedBean
@ApplicationScoped
public class ApplicationBean implements Serializable { ... }