Qu'est-ce qui cause ce genre d'erreur dans Tomcat?
SEVERE: Exception loading sessions from persistent storage
Java.io.WriteAbortedException: writing aborted; Java.io.NotSerializableException:
bean.ProjectAreaBean
at Java.io.ObjectInputStream.readObject0(ObjectInputStream.Java:1333)
at Java.io.ObjectInputStream.readObject(ObjectInputStream.Java:351)
at Java.util.ArrayList.readObject(ArrayList.Java:593)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(
DelegatingMethodAccessorImpl.Java:25)
Serializable
Si vous obtenez un NotSerializableException
comme suit,
Java.io.NotSerializableException: bean.ProjectAreaBean
cela signifie simplement que la classe identifiée par le nom complet dans le message d'exception (qui est bean.ProjectAreaBean
dans votre cas) n'implémente pas l'interface Serializable
tout en il est attendu par le code derrière. Le corriger est relativement simple, laissez simplement la classe implémenter l'interface Serializable
.
package bean;
import Java.io.Serializable;
public class ProjectAreaBean implements Serializable {
private static final long serialVersionUID = 1L;
// ...
}
Le champ serialVersionUID
n'est pas nécessaire, mais fortement recommandé car il maintient la compatibilité binaire entre les différentes versions de la classe et les représentations sérialisées de ses instances. Ainsi, lorsque vous ajoutez plus tard un nouveau champ sérialisable à la classe, vous devez modifier le champ serialVersionUID
(généralement, il suffit de l'incrémenter de 1 pour éviter les problèmes lors de la désérialisation d'une instance d'une version plus ancienne). de la classe. Les IDE comme Eclipse offrent également une option pour (re) générer la valeur serialVersionUID
qui est fondamentalement un hachage calculé sur la base de tous les champs.
transient
Si votre classe Serializable
contient à son tour un champ/propriété référençant une instance d'une autre classe qui ne peut absolument pas être créée Serializable
(généralement, elles représentent des ressources, telles que InputStream
, Connection
, etc.), vous devez alors le marquer transient
. De cette façon, il sera ignoré lors de la sérialisation de la classe.
private transient SomeObject thisWillNotBeSerialized;
Vous devez comprendre qu'après la désérialisation, ce champ deviendrait toujours null
. Notez que le constructeur de la classe et les blocs d'initialisation ne sont pas invoqués pendant la désérialisation. Si vous souhaitez avoir un contrôle plus fin sur la sérialisation et la désérialisation, remplacez les méthodes readObject()
et writeObject()
. Vous pouvez trouver des exemples concrets dans les liens ci-dessous:
En ce qui concerne le pourquoi vous devez vous soucier de la sérialisation, c'est parce que la plupart des conteneurs de servlets Java comme Tomcat nécessitent des classes pour implémenter Serializable
chaque fois que des instances de ces classes sont stockées en tant qu'attribut de HttpSession
. En effet, le HttpSession
peut avoir besoin d'être enregistré sur le système de fichiers du disque local ou même transféré sur réseau lorsque le conteneur de servlet doit être arrêté/redémarré ou est placé dans un cluster de serveurs dans lequel la session doit être synchronisée.
Afin de pouvoir enregistrer Java objets sur le système de fichiers de disque local ou les transférer sur le réseau, ils doivent d'abord être convertis en un flux d'octets (essentiellement: un byte[]
ou un InputStream
) et cela n'est possible que si la classe derrière l'objet implémente Serializable
. L'interface Serializable
elle-même ne fait vraiment rien, c'est simplement un interface marqueur . Le code derrière fait simplement une vérification instanceof Serializable
Sur l'attribut de session pour agir en conséquence.
Vous devez faire bean.ProjectAreaBean
sérialisable.