View scope: java.io.Notserialisableexception: javax.face.composant.HTML.HtmlInputText
il y a une erreur chaque fois qu'un bouton appelle une action à partir du back-bean. S'applique seulement aux haricots avec une portée de vue et je n'ai pas trouvé un moyen de le corriger sans régression sur d'autres modules dans le code.
DefaultFacele E Exiting serializeView - Could not serialize state: javax.faces.component.html.HtmlInputText
java.io.NotSerializableException: javax.faces.component.html.HtmlInputText
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
ou aussi:
com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0014E: Uncaught service() exception
root cause Faces Servlet: ServletException: /jspFiles/jsf/Deployments/editQueue.faces No saved view state could be found for the view identifier /jspFiles/jsf/Deployments/editQueue.faces
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:205)
Caused by: javax.faces.application.ViewExpiredException: /jspFiles/jsf/Deployments/editQueue.faces No saved view state could be found for the view identifier: /jspFiles/jsf/Deployments/editQueue.faces
at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute (RestoreViewExecutor.java:128)
faces-config.xml
<managed-bean>
<managed-bean-name>pc_EditQueue</managed-bean-name>
<managed-bean-class>pagecode.jspFiles.jsf.deployments.EditQueue</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
<managed-property>
<property-name>queueDeploymentBean</property-name>
<value>#{queueDeploymentBean}</value>
</managed-property>
</managed-bean>
web.xml
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>true</param-value>
</context-param>
haricot:
@ManagedBean
@ViewScoped
public class EditQueue extends PageCodeBase implements Serializable {
private static final long serialVersionUID = -1L;
public String doButtonAddAction() {
// calls manager (long)
FacesUtil.setViewMapValue("queueDeploymentBean", queueDeploymentBean);
return "";
}
j'ai lu ce suggestion pour mettre SERIALIZE_STATE_IN_SESSION à false et en effet cette solution fonctionne pour cette vue portée bean. Cependant, ce correctif coûte cher: de nombreux modules existants dans l'application ne fonctionnent plus, donc je ne peux pas utiliser ce correctif là-bas. Parmi les régressions observées, on peut citer:
// returns null must be changed with FacesUtil.getSessionMapValue("userId");
getSessionScope().get("userId");`
// returns null must be changed with FacesUtil.getViewMapValue("linkerBean");
linkerBean = (Linker) getManagedBean("linkerBean");`
// NPE so must be changed with FacesContext.getCurrentInstance().addMessage(...)
getFacesContext().addMessage(...)`
donc mes questions sont:
- pourquoi L'Exception Notserialisableexception même si la fève met en œuvre sérialisable ?
- y a-t-il un moyen d'appliquer le param SERIALIZE_STATE_IN_SESSION sur seulement un sous-ensemble des haricots ou non ?
-
y a-t-il une autre solution pour que mon point de vue sur la portée puisse fonctionner (sans avoir à les Modifier pour demander la portée ou autrement) ?
WebSphere 8.0.0.3, Java 1.6.0, JSF 2.0, RichFaces 4.2.3.Final
1 réponses
pourquoi L'Exception Notserialisableexception même si la fève met en œuvre sérialisable ?
non seulement le haricot doit être sérialisable, mais toutes ses propriétés (et toutes leurs propriétés imbriquées etc) doivent également être sérialisables. Le nom de la classe offensante non-serialisable peut facilement être trouvé dans le message d'exception:
java.io.NotSerializableException: javax.faces.component.html.HtmlInputText
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
cela suggère que vous liez un <h:inputText>
composant pour le haricot comme ci-dessous:
<h:inputText binding="#{bean.fooInput}" ...>
private UIComponent fooInput;
ceci est en effet illégal lorsque le haricot n'est pas visé par la demande. Les instances UIComponent
ont une portée de requête et ne peuvent pas être partagées entre plusieurs requêtes. De plus, les instances UIComponent
sont et non sérialisables. Seul leur état l'est, mais JSF s'en inquiétera tout seul.
vous devez supprimer la propriété fooInput
et vous avez besoin pour chercher une solution différente pour le problème pour lequel vous avez pensé à tort que la liaison du composant à une vue scoped bean serait la bonne solution.
-
si vous avez l'intention d'y accéder ailleurs dans la vue, par exemple
#{bean.fooInput.value}
, alors liez-le simplement à la portée de Facelet sans la nécessité d'une propriété de haricot:<h:inputText binding="#{fooInput}" ...>
il sera disponible ailleurs dans la même Vue via
#{fooInput.xxx}
.<h:inputText ... required="#{empty fooInput.value}" />
-
si vous avez l'intention de programmer un attribut de Composant à l'intérieur de la fève, par exemple
fooInput.setStyleClass("someClass")
, oufooInput.setDisabled(true)
, alors vous devriez lier l'attribut spécifique dans la vue au lieu de l'ensemble du composant:<h:inputText ... styleClass="#{bean.styleClass}" /> ... <h:inputText ... disabled="#{bean.disabled}" />
-
si vous êtes absolument certain que vous avez besoin d'obtenir une main entière
UIComponent
instance dans le bean pour quelque raison que ce soit, puis saisir manuellement dans la portée locale de la méthode au lieu de le lier:public void someMethod() { UIViewRoot view = FacesContext.getCurrentInstance().getViewRoot(); UIComponent fooInput = view.findComponent("formId:fooInputId"); // ... }
mais mieux vaut poser une question ou chercher une réponse comment résoudre le problème concret différemment sans avoir besoin de saisir un composant entier dans la fève de soutien.
voir aussi:
en ce qui concerne le ViewExpiredException
, cela a des motifs différents qui est développé plus en détail dans javax.face.application.ViewExpiredException: ne peut pas être restaurée .