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

Glassfish et Payara Java Discussion :

Persistence Unit dans JNDI


Sujet :

Glassfish et Payara Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 169
    Points : 65
    Points
    65
    Par défaut Persistence Unit dans JNDI
    Bonjour,
    J'ai besoin qu'une même application Web déployée sous GlassFish accède une base de données qui sera différente selon le client qui se sera connecté. Cette application sera basée sur JPA, et étant donné que le nom de la base de données est dynamique, je ne peux pas utiliser un fichier persistence.xml pour définir un Persistence Unit.
    Dans mes recherches j'ai trouvé ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        public EntityManager getEntityManager() {
            if (em == null}
                try{
                    em = (EntityManager)(new InitialContext()).lookup("java:comp/ejb/EntityManager");
                } catch (Exception e){};
            }
            return em;
        }
    A l'url suivante : http://wiki.eclipse.org/EclipseLink/Examples/JPA/EMAPI
    Intéressant sauf que je ne vois pas comment créer un PU dans GlassFish !
    Quelqu'un aurait-il une solution ?
    Merci d'avance pour votre aide.

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    La base de données n'est pas définie au niveau du Persistence unit, mais au niveau du persistence unit factory. Il te faudra donc une factory différente pour chaque client.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    EntityManagerFactory managerFactory = null;
    Map<String, String> persistenceMap = new HashMap<String, String>();
     
    persistenceMap.put("javax.persistence.jdbc.url", "<url>");
    persistenceMap.put("javax.persistence.jdbc.user", "<username>");
    persistenceMap.put("javax.persistence.jdbc.password", "<password>");
    persistenceMap.put("javax.persistence.jdbc.driver", "<driver>");
     
    managerFactory = Persistence.createEntityManagerFactory("<current persistence unit>", persistenceMap);
    manager = managerFactory.createEntityManager();
    Et ce sera à toi de gérer l'instanciation du persistence unit et la transmission à tes composants. Le conteneur ne t'aidera pas là dessus, ce n'est pas prévu pour être utilisé comme ça.

    A noter aussi que qui dit de multiples factories, dit aussi multiplication des besoins en ressource du serveur, une factory contenant les metadata du modèle, les caches HQL, le cache de niveau 2, le connexion pool...

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 169
    Points : 65
    Points
    65
    Par défaut
    Bonjour,
    Merci pour cette réponse. Je suis bien conscient des problèmes que cela peut poser et du côté un "tordu" d'utiliser cette technologie dans le cadre d'une application multibases, mais c'est ça ou utiliser un accès classique JDBC et là je cale, je ne veux pas revenir à ce genre de solution, d'autant que j'ai un savoir faire équivalent en C# et ASP.NET qui me ferait gagner un temps précieux !
    Ta solution est intéressante, mais elle ne répond pas vraiment à ma question, en effet si cette ligne est possible (ce qui reste à démonter d'ailleurs) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    em = (EntityManager)(new InitialContext()).lookup("java:comp/ejb/EntityManager");
    Alors cela signifie qu'on doit pouvoir déposer un EntityManager dans le JNDI de GlassFish, ce qui me permettrait entre autres de bénéficier du pool de connections et autres facilités ;-)
    Donc si tu as des pistes là dessus je suis preneur, quitte d'ailleurs à passer sur du TOMCAT (TOMEE en réalité), même si Tomcat n'est pas vraiment JEE compatible.
    Merci encore.

    Citation Envoyé par tchize_ Voir le message
    La base de données n'est pas définie au niveau du Persistence unit, mais au niveau du persistence unit factory. Il te faudra donc une factory différente pour chaque client.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    EntityManagerFactory managerFactory = null;
    Map<String, String> persistenceMap = new HashMap<String, String>();
     
    persistenceMap.put("javax.persistence.jdbc.url", "<url>");
    persistenceMap.put("javax.persistence.jdbc.user", "<username>");
    persistenceMap.put("javax.persistence.jdbc.password", "<password>");
    persistenceMap.put("javax.persistence.jdbc.driver", "<driver>");
     
    managerFactory = Persistence.createEntityManagerFactory("<current persistence unit>", persistenceMap);
    manager = managerFactory.createEntityManager();
    Et ce sera à toi de gérer l'instanciation du persistence unit et la transmission à tes composants. Le conteneur ne t'aidera pas là dessus, ce n'est pas prévu pour être utilisé comme ça.

    A noter aussi que qui dit de multiples factories, dit aussi multiplication des besoins en ressource du serveur, une factory contenant les metadata du modèle, les caches HQL, le cache de niveau 2, le connexion pool...

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 169
    Points : 65
    Points
    65
    Par défaut
    Bonjour,
    Je viens de faire des tests et ... il semble au début que cela marche, mais en fait, il y a des problèmes avec les transactions qui ne sont pas démarrées, du coup la base de données physique n'est pas mise à jour !
    Je vais donc laisser tomber cette techno, trop aléatoire.
    Merci d'avoir essayé de répondre.
    Cordialement

    Citation Envoyé par clem_alain Voir le message
    Bonjour,
    Merci pour cette réponse. Je suis bien conscient des problèmes que cela peut poser et du côté un "tordu" d'utiliser cette technologie dans le cadre d'une application multibases, mais c'est ça ou utiliser un accès classique JDBC et là je cale, je ne veux pas revenir à ce genre de solution, d'autant que j'ai un savoir faire équivalent en C# et ASP.NET qui me ferait gagner un temps précieux !
    Ta solution est intéressante, mais elle ne répond pas vraiment à ma question, en effet si cette ligne est possible (ce qui reste à démonter d'ailleurs) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    em = (EntityManager)(new InitialContext()).lookup("java:comp/ejb/EntityManager");
    Alors cela signifie qu'on doit pouvoir déposer un EntityManager dans le JNDI de GlassFish, ce qui me permettrait entre autres de bénéficier du pool de connections et autres facilités ;-)
    Donc si tu as des pistes là dessus je suis preneur, quitte d'ailleurs à passer sur du TOMCAT (TOMEE en réalité), même si Tomcat n'est pas vraiment JEE compatible.
    Merci encore.

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 936
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 936
    Points : 4 356
    Points
    4 356
    Par défaut
    Ce n'est pas parce que vous avez raté quelque chose dans le setup des transactions que la solution est aléatoire.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 169
    Points : 65
    Points
    65
    Par défaut
    Bonjour,
    Il est possible que j'ai loupé quelque chose, mais je pense plutôt que mes contraintes et cette technologie sont contradictoires. Ma contrainte est dynamique (base de données à la demande) et la technologie est "statique" ; c'est le conteneur qui via les annotations, pilote les instanciations et par conséquent il doit connaître par avance la Base de données à gérer.
    La conclusion que j'en ai tiré, c'est que je dois repasser par un classique JDBC avec un loukUp sur un JNDI, cela fonctionne très bien, mais je perds tous les avantages de la technologie JPA. Bon c'est fait, c'est bouclé, j'ai opté pour une autre technologie que je maîtrise par ailleurs très bien, mais plus fondamentalement, je n'ai jamais une de réponse sur la faisabilité du code ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    em = (EntityManager)(new InitialContext()).lookup("java:comp/ejb/EntityManager");
    Et ce n'est pas un code pris n'importe où, cela vient quand même de : http://wiki.eclipse.org/EclipseLink/Examples/JPA/EMAPI
    Il est possible (probable) que je sois passé à côté de quelque chose, je voudrais quand même bien savoir comment on peut mettre en oeuvre ce code !
    Cordialement,

    Citation Envoyé par JeitEmgie Voir le message
    Ce n'est pas parce que vous avez raté quelque chose dans le setup des transactions que la solution est aléatoire.

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Le code que tu indique sert à récuperer manuellement l'entity manager jpa par défaut. En général on n'en a pas besoin à moins de vouloir récupérer celui ci depuis un endroit tordu dans le code.

    Ce code fait fondamentalement la même chose qu'écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     
        @PersistenceContext
        private EntityManager entityManager;
    dans un EJB

    Le problème c'est qu'un entitymanager ça sort d'une factory, et c'est la factory qui décide de la base de données à utiliser (serveur, password, schéma). Je ne pense pas que tu puisse utiliser tel quel les injection avec une connection jdbc configurée à la volée en fonction de l'utilisateur http. JE pense que tu va devoir te coltiner la gestion de l'entitymanager factory à la main ainsi que l'instanciation de l'entitymanager.

    Après si tu n'a que quelques bases de données, tu pourrait créer 2,3 4 ou 5 entitymanager différent, chacun avec leur datasource, injecter les 5 dans une ejb qui aurait une méthode de facade pour choisir celui à utiliser pour les appels. Pas top.

    Ces articles pourraient t'intéresser.

    http://www.hostettler.net/blog/2012/...multi-tenancy/
    https://www.tomas-dvorak.cz/posts/jpa-multitenancy/
    https://jcp.org/aboutJava/communityp...11/JavaEE7.pdf
    https://fr.slideshare.net/rcandidosi...s-with-java-ee

  8. #8
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 936
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 936
    Points : 4 356
    Points
    4 356
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Le code que tu indique sert à récuperer manuellement l'entity manager jpa par défaut. En général on n'en a pas besoin à moins de vouloir récupérer celui ci depuis un endroit tordu dans le code.

    Ce code fait fondamentalement la même chose qu'écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     
        @PersistenceContext
        private EntityManager entityManager;
    dans un EJB

    Le problème c'est qu'un entitymanager ça sort d'une factory, et c'est la factory qui décide de la base de données à utiliser (serveur, password, schéma). Je ne pense pas que tu puisse utiliser tel quel les injection avec une connection jdbc configurée à la volée en fonction de l'utilisateur http. JE pense que tu va devoir te coltiner la gestion de l'entitymanager factory à la main ainsi que l'instanciation de l'entitymanager.

    Après si tu n'a que quelques bases de données, tu pourrait créer 2,3 4 ou 5 entitymanager différent, chacun avec leur datasource, injecter les 5 dans une ejb qui aurait une méthode de facade pour choisir celui à utiliser pour les appels. Pas top.

    Ces articles pourraient t'intéresser.

    http://www.hostettler.net/blog/2012/...multi-tenancy/
    https://www.tomas-dvorak.cz/posts/jpa-multitenancy/
    https://jcp.org/aboutJava/communityp...11/JavaEE7.pdf
    https://fr.slideshare.net/rcandidosi...s-with-java-ee

    En JEE "pur", cela risque en effet d'être compliqué… par contre avec Spring c'est faisable : il y a tout ce qu'il faut pour créer des beans à la volée et les injecter.
    Pour ce qui est du nom JNDI de l'EntityManager, cela passe de toute façon via un persistence-context-ref dans le descripteur de déploiement (e.g. web.xml) donc on oublie le "dynamisme".

    Le véritable problème sous-jacent est la gestion du cycle de vie de l'entity manager factory : un utilisateur cela se connecte, se déconnecte (ou cela oublie de se déconnecter…), … mais la webapp, elle, continue sa propre vie…
    synchroniser la vie des EM factories à celle des connections de l'utilisateur risque d'être "amusant"… sans parler du coût d'une EM factory, comme vous l'évoquiez plus haut…

    Il y a quand même des solutions plus simples pour faire du multi-tenant que de s'emm… avec un tel design : avoir une connection JDBC par login d'utilisateur final est un bel anti-pattern.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 169
    Points : 65
    Points
    65
    Par défaut
    Citation Envoyé par JeitEmgie Voir le message
    avoir une connection JDBC par login d'utilisateur final est un bel anti-pattern.
    Ce n'est pas tout à fait ça, en fait la connexion JDBC est la même à chaque fois, c'est la base ciblée qui change, l'utilisateur final fournit trois informations : Login, MdP et Identifiant client, c'est ce dernier qui va donner la base cible.
    Je fonctionne comme ça depuis plus de dix ans sur différentes applications en ASP.NET/ C#. Ce genre de fonctionnement me permet d'avoir une seule application pour n clients.
    Bonnes fêtes de fin d'année à tous

  10. #10
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    D'accord avec toi, c'est le principe du SaaS, ce n'est pas une anti pattern de viser des tables / un shéma différent plutot que de multiplier les instances.

    Sauf que les api JPA n'ont jamais vraiment été prévues pour. Les api JPA supposent qu'elles peuvent analyser tes tables au démarrage, ce qui se complique quand chaque shéma peut avoir potentiellement des tables différentes. Soit tu va te coltiner le extension multi tenant de hibernate / eclipselink, soit tu va te coltiner du jdbc à l'ancienne

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 169
    Points : 65
    Points
    65
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    D'accord avec toi, c'est le principe du SaaS, ce n'est pas une anti pattern de viser des tables / un shéma différent plutot que de multiplier les instances.

    Sauf que les api JPA n'ont jamais vraiment été prévues pour. Les api JPA supposent qu'elles peuvent analyser tes tables au démarrage, ce qui se complique quand chaque shéma peut avoir potentiellement des tables différentes. Soit tu va te coltiner le extension multi tenant de hibernate / eclipselink, soit tu va te coltiner du jdbc à l'ancienne
    C'est exactement çà, et quand on a goûté à JPA, on a beaucoup de mal à revenir à JDBC, je suis actuellement en parallèle sur un projet JPA/Rest/Angular et c'est un vrai bonheur de ne pas se "farcir" les erreurs de requêtes SQL ;-)
    Sachant quand même que pour le moment j'en suis à la partie back-office, cela risque de changer un peu lorsque j'aborderai la partie métier proprement dite mais enfin, il y a un gain de productivité non négligeable.

  12. #12
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Si tu accepte d'être dépendant d'eclipselink, à mon avis ceci pourrait t'aller


    http://www.eclipse.org/eclipselink/d...t.htm#BABEGBIJ

    tu dois toujours construire l'entitymanager à la main mais tu gardera la pluspart de JPA.

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 169
    Points : 65
    Points
    65
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Si tu accepte d'être dépendant d'eclipselink, à mon avis ceci pourrait t'aller


    http://www.eclipse.org/eclipselink/d...t.htm#BABEGBIJ

    tu dois toujours construire l'entitymanager à la main mais tu gardera la pluspart de JPA.
    Bonjour,
    Cela tombe bien, j'ai choisi eclipselink plutôt qu'Hibernate qui me paraissait trop lourd pour une base d'une dizaine de tables et quelques centaines d'occurrences.
    Je vais donc regarder cela de près, mais au vu d'un coup d'oeil rapide, j'ai l'impression que cela impacte très sérieusement la base elle-même, à voir.
    Merci quand même et bonnes fêtes de fin d'année

Discussions similaires

  1. Changer unité dans un formulaire
    Par banania dans le forum VBA Access
    Réponses: 6
    Dernier message: 21/06/2007, 21h13
  2. nettoyer les persistence units
    Par toomsounet dans le forum NetBeans
    Réponses: 1
    Dernier message: 11/03/2007, 14h10
  3. [JBoss 4][EJB3] persistance.units NOTYETINSTALLED
    Par Zero dans le forum Wildfly/JBoss
    Réponses: 4
    Dernier message: 01/02/2007, 09h26
  4. Calcul des unités dans un entier 32bits
    Par hack-77 dans le forum Algorithmes et structures de données
    Réponses: 5
    Dernier message: 04/08/2006, 14h18
  5. Réponses: 9
    Dernier message: 27/10/2005, 18h15

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