2010-10-03 7 views
9

Hallo Ich benutze eine ViewScoped Bean das Problem ist, dass wenn ich es anrufe bekomme ich die NotSerializableException.ViewScoped Bean Ursache NotSerializableException

Dies ist der Code meiner 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; 
    } 
} 

Ich erhalte die folgende Ausnahme:

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

Jede Lösung für dieses Problem ?? Bitte Hilfe!

+1

Sehr ähnliche Frage, mit der Auflösung, hier: http://stackoverflow.com/questions/3180963/spring-session-scoped-beans-controllers-and-references-to-services-in-terms-of – skaffman

Antwort

6

Ein weiteres Problem ist, dass MyFaces standardmäßig Serialisierung von Zustand, auch wenn Status auf dem Server (der Standard) gespeichert wird. Dies wiederum erfordert erfordert Ansicht Bereich Backing-Beans serialisierbar sein.

Die Vorteile dieses Ansatzes ist, dass Geschichte wirklich Geschichte ist. Wenn Sie zu einer früheren Ansichtsversion zurückkehren (mit der Zurück-Schaltfläche), erhalten Sie zu diesem Zeitpunkt tatsächlich die genaue Version der Backing-Bean.

Die Con ist, dass es scheint, die Injektion von Diensten zu brechen (und unabhängig von diesem Problem, ist ein großer Leistungshit). Die genau gleichen Probleme treten auf, wenn ein EJB-Dienst injiziert wird.

Es gibt einen Kontext-Parameter, die Sie in web.xml setzen können dieses Verhalten zu deaktivieren:

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

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

Übrigens hat Mojarra eine ähnliche Einstellung, aber es ist die Standardeinstellung false.

0

Ich habe eine Lösung für dieses Problem auf my own question about this same problem, die wie folgt geht: statt die Spring Bohnen über EL in einer @ManagedProperty Annotation injizieren (ausgeführt auf der ManagedBean-Initialisierung), erhalten Sie die Beans zur Evaluierung der EL zur Laufzeit.

Mit diesem Ansatz Ihre JSF Bean sollte wie folgt aussehen:

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

Und hier ist es die verwendete Utility-Klasse 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); 
    } 
} 

Diese die Spring-Bean-Eigenschaft beseitigt (auf Kosten von ein paar mehr EL-Bewertungen), wodurch die Serialisierungsprobleme vermieden werden, die Eigenschaft an erster Stelle zu haben.

0

Alles in ViewScoped Bean wird in ViewState gespeichert. Sie können die ViewState-Serialisierung in der Sitzung ausschalten, aber Sitzungen selbst können serialisiert werden, und das Problem wird an anderer Stelle auftreten. Die Lösung mit Spring ist zu verwenden Serializable Proxy.

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

Frühling Bohnen werden in Proxy eingewickelt, das heißt serializable, und der umhüllte Referenz ist vergänglich, so ist es aus der Feder Kontext nach der Deserialisierung wieder lesen.

Es ist technisch ähnlich zu elias Antwort, nur müssen Sie nicht diesen Code selbst für jede Bean schreiben. Sie verwenden aop.

Sie können meine Frage sehen: JSF beans and serializability issue für mehr Kontext.