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

Java Discussion :

invoke, getMethod et méthodes génériques


Sujet :

Java

  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2012
    Messages : 91
    Par défaut invoke, getMethod et méthodes génériques
    Salut !
    Je suis novice en programmation Java et j'ai lu quelque part que :
    [La méthode "invoke"] permet de lancer une méthode sur un objet, et éventuellement de récupérer un résultat, et ceci en récupérant la liste des paramètres et le nom de la méthode [...]. Cela pose quelques problèmes pour les méthodes génériques ayant pour paramètre le type Object mais qu'on désire appeler avec un paramètre d'un type dérivé. En effet, getMethod cherchera la méthode dont le paramètre a pour type le type dérivé en question, et comme il ne le trouvera pas il renverra une exception.
    Il se trouve que je suis justement dans cette situation.
    Quelqu'un pourrait me coacher pour mieux appréhender Java (et en passant me donner une idée pour contourner le problème évoqué plus haut )?

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Normalement tu devrais bien connaître la méthode que tu cherches à appeler, et donc tu ne risques pas de te tromper sur les types des paramètres.

    Pourrais-tu nous parler un peu plus de ce qui te gène ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2012
    Messages : 91
    Par défaut
    En fait, j'ai une classe qui me sert à faire des opérations sur une base de données. Elle est ainsi :
    public class DAO<T> implements IDAO<T> {

    protected EntityManager em = Persistence.createEntityManagerFactory("MaPersistencePU").createEntityManager();

    protected Transaction trans;
    private T objet;

    public DAO() { }

    public DAO(T objet) { this.objet = objet; }

    public T enregistrerObjet(T t) {
    try{
    em.getTransaction().begin();
    objet=t;
    em.persist(objet);
    em.flush();
    em.getTransaction().commit();
    return objet;
    }
    finally{
    em.close();
    }
    }

    public T modifierObjet(T t) {
    try{
    em.getTransaction().begin();
    objet=t;
    T e = em.merge(objet);
    objet=e;
    em.getTransaction().commit();
    return objet;
    }
    finally{
    em.close();
    }
    }
    .
    .
    .
    Je veux laisser tomber les opérations sur la transaction
    em.getTransaction().begin();
    et
    em.getTransaction().commit();
    puisque je compte gérer la persistence autrement côté serveur (c'est une application web). Mais néanmoins, pour mes tests, il faut que je puisse faire des opérations en local.
    D'où la classe service :
    public class Services{

    public T executer(Method methode, T objet, Object ... parametres) {
    EntityManager em = Persistence.createEntityManagerFactory("MaPersistencePU").createEntityManager();
    try {
    em.getTransaction().begin();
    try {
    methode.invoke(objet,parametres[0]);
    } catch (IllegalAccessException ex) {
    Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalArgumentException ex) {
    Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvocationTargetException ex) {
    Logger.getLogger(Services.class.getName()).log(Level.SEVERE, null, ex);
    }
    em.getTransaction().commit();
    }
    finally{
    em.close();
    }
    return objet;
    }
    que je veux utiliser pour "appeler" mes méthodes en y ajoutant les opérations sur la transaction.
    Mais j'obtiens toujours une erreur quand j'utilise le "invoke" avec une instance de ma classe DAO.
    Dans cette instruction par exemple :
    Services serv = new Services();
    DAO<Utilisateur> daoUtil = new DAO<Utilisateur>(utilisateur);
    try {
    Method m = daoUtil.getClass().getMethod("enregistrerObjet",utilisateur.getClass()); serv.executer(m, daoUtil, utilisateur);
    } catch (NoSuchMethodException ex) {
    Logger.getLogger(Inscription.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SecurityException ex) {
    Logger.getLogger(Inscription.class.getName()).log(Level.SEVERE, null, ex);
    }
    Voilà toute l'histoire. Jespère que je ne me suis pas trop "embrouillé" vu que je ne suis pas très avancé en java.

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Bon, ok, c'est compliqué.

    Donc en gros ton problème est comme ça : tu as une classe

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class A<T> {
     
      public void faireTruc(T truc) {
     
      }
     
    }
    Et tu te demandes comment récupérer la méthode faireTruc() avec Class.getMethod().
    Le problème étant que T est un type paramètre, et que tu ne sais donc pas quelle classe donner à getMethod() pour le représenter.

    Apparemment tu as déjà compris que :
    - après la compilation, donc par exemple pendant que le programme s'exécute, les génériques ça n'existe plus. Ils ont été "effacés".
    - getMethod() s'utilise pendant l'exécution du programme, donc après compilation, donc les génériques n'existent plus à ce moment-là.

    Voici à quoi ressemble la classe A après effacement des génériques :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class A {
     
      public void faireTruc(Object truc) {
     
      }
     
    }
    - Le <T>, paramètre de la classe A, n'existe tout simplement plus, la classe A n'est plus générique, elle n'a pas de paramètre.
    - Toute utilisation de T a été remplacée par Object.

    Pourquoi "Object" ?
    parce que class A<T> est un raccourci pour écrire class A<T extends Object>.

    En réalité les types paramètres de classe et de méthode, étendent toujours un type, et par défaut c'est Object, la classe ascendante de tous les types objets.

    "Effacer" les génériques, consiste à remplacer leurs utilisations par des types dits "réifiés", qui existent à l'exécution. En l'occurence, dans mon exemple simple, remplacer T par Object, parce que <T extends Object> et que Object est un type type qui existe lors de l'exécution (vu que c'est la classe Object, ascendante de tout.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2012
    Messages : 91
    Par défaut
    J'ai remplacé tous les <T> par <Object> mais je n'ai toujours pas de succès.
    Il y a toujours une "java.lang.NoSuchMethodException" à l'exécution.

  6. #6
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2012
    Messages : 91
    Par défaut
    Oops, j'ai résolu ce problème. Il a suffit de créer mon instance daoUtil avec "Object.class" plutôt que "Utilisateur.class".
    Néanmoins, je ne suis pas au bout de mes peines. Je suis maintenant à une "java.lang.reflect.InvocationTargetException". Je risque de perdre tous mes cheveux à cette allure

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par Fandyz Voir le message
    J'ai remplacé tous les <T> par <Object> mais je n'ai toujours pas de succès.
    Ça ressemble pas à ce que j'ai dit de faire.
    J'ai dit de transformer mon exemple 1 en exemple 2. Notamment, les <T> ne sont pas remplacés, mais supprimés.

    Si c'est ce que tu as essayé de faire, tu as mal décris ta méthode. Si tu ne peux pas faire mieux, montre-nous le résultat.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Je vois que tu as corrigé l'erreur précédente.

    Citation Envoyé par Fandyz Voir le message
    Néanmoins, je ne suis pas au bout de mes peines. Je suis maintenant à une "java.lang.reflect.InvocationTargetException". Je risque de perdre tous mes cheveux à cette allure
    Ça, ça montre que l'appel à la méthode a bien marché.
    Par contre, ce que fait cette méthode, ça ça a généré une exception.
    Il faut regarder la cause, dans la stacktrace.

    (Au passage, il faut toujours regarder et donner la stacktrace.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2012
    Messages : 91
    Par défaut
    Quand j'étais dans ce modèle
    public T enregistrerObjet(T t) {
    try{
    em.getTransaction().begin();
    objet=t;
    em.persist(objet);
    em.flush();
    em.getTransaction().commit();
    return objet;
    }
    finally{
    em.close();
    }
    }
    ,
    tout marchait normalement. J'ai même fait des enregistrements avec.
    Je suis passé à cette structure :
    public T enregistrerObjet(T t) {
    objet=t;
    em.persist(objet);
    em.flush();
    return objet;
    }
    et je comptais utiliser la classe Services pour reconstituer les instructions telles qu'elles étaient dans le premier modèle.

    Voilà l'exception que j'obtiens (en entier) :
    29 mai 2012 15:59:28 org.skan.ExoSpace.service.Services executer
    GRAVE: null
    java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.skan.ExoSpace.service.Services.executer(Services.java:29)
    at exospace.EnregistrerUtilisateur.btEnregActionPerformed(EnregistrerUtilisateur.java:163)
    at exospace.EnregistrerUtilisateur.access$000(EnregistrerUtilisateur.java:31)
    at exospace.EnregistrerUtilisateur$1.actionPerformed(EnregistrerUtilisateur.java:70)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
    at java.awt.Component.processMouseEvent(Component.java:6290)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
    at java.awt.Component.processEvent(Component.java:6055)
    at java.awt.Container.processEvent(Container.java:2039)
    at java.awt.Component.dispatchEventImpl(Component.java:4653)
    at java.awt.Container.dispatchEventImpl(Container.java:2097)
    at java.awt.Component.dispatchEvent(Component.java:4481)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4575)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4236)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4166)
    at java.awt.Container.dispatchEventImpl(Container.java:2083)
    at java.awt.Window.dispatchEventImpl(Window.java:2482)
    at java.awt.Component.dispatchEvent(Component.java:4481)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:648)
    at java.awt.EventQueue.access$000(EventQueue.java:84)
    at java.awt.EventQueue$1.run(EventQueue.java:607)
    at java.awt.EventQueue$1.run(EventQueue.java:605)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
    at java.awt.EventQueue$2.run(EventQueue.java:621)
    at java.awt.EventQueue$2.run(EventQueue.java:619)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:618)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:178)
    at java.awt.Dialog$1.run(Dialog.java:1044)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:646)
    at java.awt.EventQueue.access$000(EventQueue.java:84)
    at java.awt.EventQueue$1.run(EventQueue.java:607)
    at java.awt.EventQueue$1.run(EventQueue.java:605)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
    at java.awt.EventQueue$2.run(EventQueue.java:621)
    at java.awt.EventQueue$2.run(EventQueue.java:619)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:618)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
    Caused by: javax.persistence.TransactionRequiredException:
    Exception Description: No transaction is currently active
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.throwCheckTransactionFailedException(EntityTransactionWrapper.java:113)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.checkForTransaction(EntityTransactionWrapper.java:50)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction(EntityManagerImpl.java:1666)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:744)
    at org.skan.ExoSpace.dao.DAO.enregistrerObjet(DAO.java:39)
    ... 61 more

  10. #10
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Ben...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Caused by: javax.persistence.TransactionRequiredException:
    Exception Description: No transaction is currently active
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.throwCheckTransactionFailedException(EntityTransactionWrapper.java:113)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.checkForTransaction(EntityTransactionWrapper.java:50)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction(EntityManagerImpl.java:1666)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:744)
    at org.skan.ExoSpace.dao.DAO.enregistrerObjet(DAO.java:39)
    ... 61 more
    L'exception est claire, le message est clair, et à mon avis la pile serait claire pour quelqu'un qui travaille sur ce programme.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2012
    Messages : 91
    Par défaut
    C'est vrai que vu comme ça c'est très clair.
    J'ai encore des progrès à faire dans l'interprétation des exceptions.
    J'ai pourtant fait
    em.getTransaction().begin();
    avant le "invoke()" et
    em.getTransaction().commit();
    après.
    Je ne sais vraiment pas quel est le problème.

  12. #12
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Sur ce point-là je ne suis pas compétent, je n'utilise Hibernate et consorts que dans les clous par défaut.

    Mais ça c'est une question sur la persistance, pas sur la réflectivité.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  13. #13
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2012
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2012
    Messages : 91
    Par défaut
    Eureka!!!
    Je crois que j'ai trouvé!
    J'ai récupéré l'EntityManager de mon instance DAO que j'ai affecté à mon instance Services. Ainsi, tous deux fonctionnent sur le même EntityManager.
    Un test est passé (enfin) sans erreur.
    Merci beaucoup pour ton aide THELVIN.

Discussions similaires

  1. Méthode générique qui renvoie une Map
    Par stof dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 01/03/2010, 14h37
  2. Réponses: 2
    Dernier message: 07/12/2009, 16h50
  3. Méthode (générique) de récupération de config
    Par je®ome dans le forum Linux
    Réponses: 5
    Dernier message: 06/05/2009, 09h43
  4. Réponses: 10
    Dernier message: 04/03/2008, 15h13
  5. [jse5/generics] Méthodes génériques
    Par palnap dans le forum Langage
    Réponses: 5
    Dernier message: 04/03/2008, 12h14

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