2010-10-03 9 views
9

Ciao Sto usando un bean ViewScoped Il problema è che quando lo chiami ricevo NotSerializableException.ViewScoped Bean causa NotSerializableException

Questo è il codice della mia Bean Managed:

@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; 
    } 
} 

ricevo la seguente eccezione:

GRAVE: Exiting serializeView - Could not serialize state: com.bull.congesJBPM.serviceImpl.DemandeServiceImpl 
java.io.NotSerializableException: com.bull.congesJBPM.serviceImpl.DemandeServiceImpl 

Qualsiasi correzione per questo problema ?? Per favore aiuto !

+1

Domanda molto simile, con risoluzione, qui: http://stackoverflow.com/questions/3180963/spring-session-scoped-beans-controllers-and-references-to-services-in-terms-of – skaffman

risposta

6

Un altro problema è che MyFaces per impostazione predefinita esegue la serializzazione dello stato, anche quando lo stato viene salvato sul server (impostazione predefinita). Questo nel suo turno richiede visualizzare i bean di supporto con scope per essere serializzabili.

I professionisti di questo approccio sono che la storia è veramente storia. Quando si torna a una versione precedente della vista (usando il pulsante Indietro), si ottiene effettivamente la versione esatta del backing bean in quel momento.

Il problema è che sembra interrompere l'iniezione di servizi (e non correlato a questo problema, è un grande successo di prestazioni). Lo stesso identico problema si verifica quando si inserisce un servizio EJB.

C'è un parametro di contesto che si può mettere in web.xml per disattivare questo comportamento:

<context-param> 
    <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name> 
    <param-value>false</param-value> 
</context-param> 

Vedi http://wiki.apache.org/myfaces/Performance

Per inciso, Mojarra ha un'impostazione simile, ma c'è il valore predefinito è falso.

0

ho postato una soluzione per questo problema su my own question about this same problem, che va come questo: invece di iniettare i bean Spring attraverso EL in un @ManagedProperty di annotazione (eseguita su l'inizializzazione ManagedBean), si ottengono i fagioli che valutano l'EL in fase di esecuzione.

Con questo approccio, il bean JSF dovrebbe essere così:

@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(); 
    } 
    // ... 

E qui è la classe di utilità utilizzato 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); 
    } 
} 

Questo elimina la proprietà bean Spring (a costo di fare qualche altra valutazione EL), evitando così i problemi di serializzazione di avere la proprietà al primo posto.

0

Tutto nel bean ViewScoped è memorizzato in ViewState. È possibile disattivare la serializzazione di ViewState in sessione, ma le sessioni stesse possono essere serializzate e quindi il problema si presenterà altrove.

La soluzione con Spring è utilizzata Serializable Proxy.

<aop:scoped-proxy proxy-target-class="true"/> 

bean Spring sono avvolti in proxy, cioè serializzabile, e il riferimento avvolto è transitoria, quindi viene riletto dal contesto molla dopo la deserializzazione.

È tecnicamente simile alla risposta elias, solo che non è necessario scrivere quel codice per ciascun bean. Si utilizza aop.

Puoi vedere la mia domanda: JSF beans and serializability issue per più contesto.