IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Wicket Java Discussion :

Problème avec les modèles


Sujet :

Wicket Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de stouf()
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 89
    Par défaut Problème avec les modèles
    Bonjour,

    Je suis entrain de faire le tuto sur les modèle de "Jawher Moussa" et j'ai une petite erreur quand j'appuie sur le submit.

    Voici le code du Login (pour le dao et la classe pojo c'est comme dans le tuto)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
     
    package com.myapp.wicket;
     
    import com.myapp.dao.IUserDao;
    import com.myapp.dao.UserDao;
    import com.myapp.pojo.User;
    import org.apache.wicket.markup.html.form.Form;
    import org.apache.wicket.markup.html.form.PasswordTextField;
    import org.apache.wicket.markup.html.form.TextField;
    import org.apache.wicket.model.CompoundPropertyModel;
    import org.apache.wicket.model.LoadableDetachableModel;
     
    /**
     *
     * @author stouf
     */
    public class Login extends BasePage {
     
        private User user = new User();
     
        public Login() {
            super ();
            Form form = new Form( "loginForm", 
                    new CompoundPropertyModel( new LoadableDetachableModel(){
                @Override
                protected Object load(){
                    return new User();
                }
            } ) ) {
     
                @Override
                protected void onSubmit(){
                    IUserDao userDao = new UserDao();
                    userDao.insert( user );
                }
            };
     
            form.add( new TextField( "login" ) );
            form.add( new PasswordTextField( "password" ) );
            add(form);
        }
    }
    Voici l'erreur que j'ai eu

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    Error serializing object class com.myapp.wicket.Login [object=[Page class = com.myapp.wicket.Login, id = 2, version = 0]]
    org.apache.wicket.util.io.SerializableChecker$WicketNotSerializableException: Unable to serialize class: com.myapp.pojo.User
    Field hierarchy is:
      2 [class=com.myapp.wicket.Login, path=2]
        private com.myapp.pojo.User com.myapp.wicket.Login.user [class=com.myapp.pojo.User] <----- field that is not serializable
            at org.apache.wicket.util.io.SerializableChecker.check(SerializableChecker.java:349)
            at org.apache.wicket.util.io.SerializableChecker.checkFields(SerializableChecker.java:618)
            at org.apache.wicket.util.io.SerializableChecker.check(SerializableChecker.java:541)
            at org.apache.wicket.util.io.SerializableChecker.writeObjectOverride(SerializableChecker.java:687)
            at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:322)
            at org.apache.wicket.util.io.IObjectStreamFactory$DefaultObjectStreamFactory$2.writeObjectOverride(IObjectStreamFactory.java:127)
            at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:322)
            at org.apache.wicket.util.lang.Objects.objectToByteArray(Objects.java:1097)
            at org.apache.wicket.protocol.http.pagestore.AbstractPageStore.serializePage(AbstractPageStore.java:199)
            at org.apache.wicket.protocol.http.pagestore.DiskPageStore.storePage(DiskPageStore.java:814)
            at org.apache.wicket.protocol.http.SecondLevelCacheSessionStore$SecondLevelCachePageMap.put(SecondLevelCacheSessionStore.java:327)
            at org.apache.wicket.Session.requestDetached(Session.java:1390)
            at org.apache.wicket.RequestCycle.detach(RequestCycle.java:1113)
            at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1385)
            at org.apache.wicket.RequestCycle.request(RequestCycle.java:498)
            at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:444)
            at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:282)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:313)
            at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:287)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:218)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
            at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
            at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:98)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:222)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
            at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:166)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
            at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
            at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
            at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096)
            at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:288)
            at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:647)
            at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:579)
            at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:831)
            at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
            at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
            at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
            at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
            at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
    Caused by: java.io.NotSerializableException: com.myapp.pojo.User
            at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
            at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
            at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
            at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
            at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
            at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
            at org.apache.wicket.util.io.IObjectStreamFactory$DefaultObjectStreamFactory$2.writeObjectOverride(IObjectStreamFactory.java:119)
            ... 39 more
    Merci d'avance pour votre aide

    Stouf()

  2. #2
    Membre émérite

    Inscrit en
    Décembre 2004
    Messages
    584
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 584
    Par défaut
    salut

    Le message d'erreur dit "java.io.NotSerializableException: com.myapp.pojo.User", autrement dit ta classe User n'implémente pas l'interface Serializable.

    Ceci dit, cela ne devrait pas poser de problème vu que tu utilises un LoadabaleDetachableModel, autrement dit ton utilisateur est chargé (load) à chaque premier appel de chaque "request cycle".

    Aussi, d'où vient l'erreur ?

    La réponse réside là :
    private User user = new User();
    En effet, tu attaches un user à ta page. Or ta page est sérialisée entre chaque appel (chaque request cycle), donc entre le moment où elle est créée, affichée, puis qu'une action utilisateur te la renvoie.

    Aussi, si tu supprimes ce champ de ta page, ton erreur disparaitra.

    Enfin, tu créés un nouvel utilisateur à chaque usage de ta page, est ce voulu ?
    Dans le même ordre d'idée, je pense que ton TextField doit toujours être rempli à chaque validation, nous sommes d'accord ? Si oui, utilises plutot un RequiredTextField

    ++

  3. #3
    Membre confirmé Avatar de stouf()
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 89
    Par défaut
    Bonjour Zedros,

    Merci pour ta réponse constructive et pleine de bon sens

    juste une petite remarque, si je retire le "private User user = new User()" alors dans ma classe DAO ( userDao.insert( user ); ) je lui passe comment l'utilisateur ?

    Pour les champs requis, je connais bien mais je faisais juste un test ou deux sur les modèles et donc j'ai fait au plus simple et plus rapide

    Merci
    Stouf()

  4. #4
    Membre émérite

    Inscrit en
    Décembre 2004
    Messages
    584
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 584
    Par défaut
    Citation Envoyé par stouf() Voir le message

    Merci pour ta réponse constructive et pleine de bon sens


    Citation Envoyé par stouf() Voir le message
    juste une petite remarque, si je retire le "private User user = new User()" alors dans ma classe DAO ( userDao.insert( user ); ) je lui passe comment l'utilisateur ?
    Bonne question

    En fait, quand tu associes directement un modèle avec un composant, dans ton cas via le constructeur, tu définies le DefaultModel lié au composant. Cela peut aussi se faire directement via un setDefaultModel(model) voir un setDefaultModelObject(object). Pour récupérer le defaultModel, tu fais ensuite un getDefaultModel() sur ton composant en question (soit ton formulaire là) (NB : regarde via l'autocomplémention les différentes variantes proposées).

    Seul défaut à cette approche : tu perds le type en chemin, lors de tes getDefaultModel* tu devras alors caster. Pour éviter la chose, tu peux passer par un champ de ta classe.

    Par contre, je te conseille fortement de mettre un modèle dans ton champ. Et tu peux toujours utilier le defaultmodelobject. Par exemple dans ton cas ça donnerait ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class Foo{
    LoadableDetachableModel myBarModel ;
     
    public Foo(String id){
                super(id);
                myBarModel = new LoadableDetachableModel(){
                @Override
                protected Object load(){
                    return new User();
                }
                 setDefaultModel(new CompoundPropertyModel(myBarModel));
          }
    }
    Dernière remarque : avec le temps, je deviens moins emballé par le CompoundPropertyModel. Il y a déjà ce cast obligatoire dès que tu accèdes au defaultobjectmodel. Cela peut arriver assez fréquemment et c'est pas tip top.

    Il t'impose également une correspondance parfaite entre ton objet et tes wicket:id, pas top pour le refactoring.

    De plus, si un de tes composants doit avoir un différent modèles, il est vite inutile. De même, pour avoir un composant sans modèle, tu dois alors le dire explicitement, via :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new FileUploadField("myUpload",new Model(null));
    Bref, je suis un peu mitigé J'aime bien les new Composant("id", new PropertyModel(myBarModel,"chemin")); en fait.

    voili voilou
    ++

  5. #5
    Membre confirmé Avatar de stouf()
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    89
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 89
    Par défaut
    dans le cas ou je fais un PropertyModel alors ma classe User devra faire un "implements Serializable" ?

    Pas facile ces modèles

    Merci Zedros

  6. #6
    Membre émérite

    Inscrit en
    Décembre 2004
    Messages
    584
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 584
    Par défaut
    Citation Envoyé par stouf() Voir le message
    dans le cas ou je fais un PropertyModel alors ma classe User devra faire un "implements Serializable" ?
    Hum, mon exemple n'est peut être pas le mieux codé/pensé/expliqué : tu peux très bien mettre un LoadableDetachableModel dans le champ associé à ta classe, puis seulement après l'accéder via des propertymodel. Tient, d'ailleurs, mon code est faux, il aurait fallu écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new Composant("id", new PropertyModel(myBarModel.getObject(),"chemin"));
    Citation Envoyé par stouf() Voir le message
    Pas facile ces modèles
    Je dirai plutôt "pas si facile" lol En fait, je suis d'accord, c'est, du moins perso, un des rares points que j'ai trouvé/trouve encore parfois un peu ardu avec Wicket. Ceci dit, ces modèles aident énormément à construire aisément des pages hautement dynamiques, leur plus value vaut donc bien quelques efforts.

    Perso, ce qui m'a beaucoup aidé est cette petite phrase : "un modèle n'est qu'une indirection (un wrapper) autour des données afin de déterminer comment on y accède".

    Cette phrase à quelques corrolaires : ne pas utiliser sans réfléchir/comprendre des modèles de partout, mettant un modèle dans un autre afin de satisfaire tel ou tel attribut d'une méthode.

    Au contraire, ne pas hésiter à aller cherche l'objet, via IModel.getObject, puis à le remettre dans un autre modèle. Après tout, ce modèle ne fait que dire s'il s'agit de lecture seule, d'une lecture unique, de nouvel accès à ton objet à chaque lecture ou d'un chargement initial suivi d'un accès à l'objet chargé (NB : je laisse au lecteur, à titre d'exercice, l'association avec les modèles correspondants ).

    Pour finir, tu peux utiliser tes propres modèles au besoin, et notamment dans les cas où tu utilises des entités. Là où je bosse on a d'ailleurs un EntityModel tip top, qui s'occupe de charger la bête au besoin puis de le réattacher si on n'est plus dans le même request cycle (les DAO étant souvent thread locaux, un nouveau request cycle indique un nouveau thread). Mon tech lead est absent cette semaine, mais je vais voir avec lui la semaine pro si je peux publier plus de détails de la bête

    ++

    NB : un petit résolu serait bienvenu

  7. #7
    Membre émérite

    Inscrit en
    Décembre 2004
    Messages
    584
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 584
    Par défaut
    Citation Envoyé par ZedroS Voir le message
    La réponse réside là :
    private User user = new User();
    En effet, tu attaches un user à ta page. Or ta page est sérialisée entre chaque appel (chaque request cycle), donc entre le moment où elle est créée, affichée, puis qu'une action utilisateur te la renvoie.

    Aussi, si tu supprimes ce champ de ta page, ton erreur disparaitra.
    ++
    hey, j'l'avais dit là moué

    lol

    ++

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec les relations dans mon modèle
    Par wam35 dans le forum Schéma
    Réponses: 3
    Dernier message: 21/01/2008, 20h22
  2. Problème avec les apostrophes
    Par misterbillyboy dans le forum Requêtes
    Réponses: 2
    Dernier message: 15/07/2003, 16h39
  3. Problème avec les fichiers .JPG
    Par cprogil dans le forum Langage
    Réponses: 5
    Dernier message: 10/06/2003, 15h44
  4. []Problème avec les formulaires Outlook
    Par Invité dans le forum Outlook
    Réponses: 6
    Dernier message: 05/12/2002, 09h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo