您好我正在使用ViewScoped Bean问题是,当调用它时,我得到了NotSerializableException。
这是我的Managed Bean的代码:
@ManagedBean(name="demandesBean")
@ViewScoped
public class DemandesBean implements Serializable {
private static final long serialVersionUID = 1L;
@ManagedProperty(value="#{demandeService}")
private DemandeService demandeService; //A Spring Service
@ManagedProperty(value="#{loginBean}")
private LoginBean loginBean;
private DemandeVO newDemande;
@PostConstruct
public void initData() {
newDemande = new DemandeVO();
}
public void doAjouterDemande(ActionListener event) {
demandeService.createDemande(newDemande, loginBean.getUsername());
newDemande = new DemandeVO();
}
public List<DemandeVO> getListDemande() {
return demandeService.getAllDemandesByUser(loginBean.getUsername());
}
public DemandeService getDemandeService() {
return demandeService;
}
public void setDemandeService(DemandeService demandeService) {
this.demandeService = demandeService;
}
public LoginBean getLoginBean() {
return loginBean;
}
public void setLoginBean(LoginBean loginBean) {
this.loginBean = loginBean;
}
public DemandeVO getNewDemande() {
return newDemande;
}
public void setNewDemande(DemandeVO newDemande) {
this.newDemande = newDemande;
}
}
我接受以下例外:
GRAVE: Exiting serializeView - Could not serialize state: com.bull.congesJBPM.serviceImpl.DemandeServiceImpl
java.io.NotSerializableException: com.bull.congesJBPM.serviceImpl.DemandeServiceImpl
解决这个问题的任何方法?请帮忙 !
答案 0 :(得分:7)
另一个问题是MyFaces默认情况下会进行状态序列化,即使状态正在服务器上保存(默认值)。轮到需要视图作用域支持bean可序列化。
这种方法的优点在于历史是真正的历史。当您返回到先前的视图版本(使用后退按钮)时,您实际上获得了当时支持bean的确切版本。
可以理解的是,它似乎打破了服务的注入(与此问题无关,是一个重大的性能损失)。注入EJB服务时会出现完全相同的问题。
您可以在web.xml中放置一个上下文参数来禁用此行为:
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>false</param-value>
</context-param>
请参阅http://wiki.apache.org/myfaces/Performance
顺便提一下,Mojarra有类似的设置,但默认为false。
答案 1 :(得分:0)
我在my own question about this same problem上发布了这个问题的解决方案,就像这样:不是通过EL在@ManagedProperty
注释中注入Spring bean(在ManagedBean初始化上执行),而是获取bean在运行时评估EL。
使用这种方法,您的JSF bean应如下所示:
@ManagedBean(name="demandesBean")
@ViewScoped
public class DemandesBean implements Serializable {
private static final long serialVersionUID = 1L;
private static DemandeService demandeService() {
return SpringJSFUtil.getBean("demandeService");
}
// ...
public void doAjouterDemande(ActionListener event) {
demandeService().createDemande(newDemande, loginBean.getUsername());
newDemande = new DemandeVO();
}
// ...
这里是使用过的实用程序类 SpringJSFUtil.java :
import javax.faces.context.FacesContext;
public class SpringJSFUtil {
public static <T> T getBean(String beanName) {
if (beanName == null) {
return null;
}
return getValue("#{" + beanName + "}");
}
@SuppressWarnings("unchecked")
private static <T> T getValue(String expression) {
FacesContext context = FacesContext.getCurrentInstance();
return (T) context.getApplication().evaluateExpressionGet(context,
expression, Object.class);
}
}
这消除了Spring bean属性(以进行更多EL评估为代价),从而避免了将属性放在首位的序列化问题。
答案 2 :(得分:0)
ViewScoped bean中的所有内容都存储在ViewState中。您可以在会话中关闭ViewState序列化,但会话本身可以序列化,然后问题将在其他地方出现。
使用Spring的解决方案是使用 Serializable Proxy 。
<aop:scoped-proxy proxy-target-class="true"/>
Spring bean包含在代理中,可序列化,并且包装引用是瞬态的,因此在反序列化后从spring上下文中重新读取它。
技术上类似于elias答案,只是你不需要为每个bean自己编写代码。您使用 aop 。
您可以查看我的问题:JSF beans and serializability issue了解更多背景信息。