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

JPA Java Discussion :

JPA - Utiliser une transaction unique à travers plusieurs appels à un service d'intégration


Sujet :

JPA Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de Lordsephiroth
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 199
    Par défaut JPA - Utiliser une transaction unique à travers plusieurs appels à un service d'intégration
    Bonjour à tous,

    Une petite question par rapport à JPA. Je travaille avec EJB3, Java6, JBoss 5.1.0 et un Eclipse EE pour Web Developers en version Helios. Nous utilisons des transactions CMT pour le moment.

    Les différents couches de mon application n'ont rien d'innovant et sont :
    - business (logique applicative travaillant sur des DTO)
    - model (validation des valeurs des DTO)
    - integration (persistence, transforme les DTO en entités pour des fonctions find(), insert(), update(), delete(), ...)
    - integration.entity (objets entités)

    Depuis ma couche applicative, après une logique métier complexe, je me retrouve à vouloir enregistrer différentes listes d'objets DTO (généralement en update() plutôt qu'en insert(), admettons qu'il n'y a que des mises à jour). Je dois le réaliser au sein d'une et une seule transaction.

    Auriez-vous des directives à me conseiller pour réaliser ça ?

    Je ne comprends pas comment, depuis ma couche applicative, initialiser une transaction que je passe ensuite à chaque appel à ma couche d'intégration. Je n'ai pas d'objet EntityManager au niveau de mon service applicatif, en tout cas pour le moment.

    La fin de mon code applicatif ressemble à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for(PersonDTO person: persons){
    	personIntegrationService.save(person);
    }
    for(VehiculeDTO vehicule: vehicules){
    	vehiculeIntegrationService.save(vehicule);
    }
    ... autres appels de persistence
    Comment faire pour que "save()" ne fasse pas de commit lorsque la fonction se termine ?
    Y a-t-il moyen de faire ça en restant en CMT ?
    Ou dois-je obligatoirement changer les transactions de l'application pour passer de CMT à BMT et réaliser le begin() et commit() dans la couche applicative ?
    Et dans ce cas, j'aurais besoin d'obtenir un objet UserTransaction dans ma couche applicative, ne serait-ce donc pas contraire aux bonnes pratiques ?

    Je cherche avant-tout une façon propre et maintenable, sinon je peux toujours réaliser un service d'intégration particulier pour lequel j'utilise des transaction BMT et qui prend autant de listes de DTO en paramètres que j'ai d'objets DTO différents et qui persiste le tout entre un begin() et un commit(). C'est pour le moment la seule façon que je vois, mais il y a probablement nettement mieux.

    Merci d'avance pour vos suggestions.

  2. #2
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Par défaut
    Je connais rien à JPA mais la solution me semble être:
    Avoir un ConnectionManager et un TransactionManager.
    Le TransactionManager est un attribut du ConnectionManager.
    Et tu partages ton ConnectionManager entre tes IntegrationService.

    En tout cas c'est le design adopté pour la modèle transactionnel
    Java : Cours et tutoriels - FAQ - Java SE 8 API - Programmation concurrente
    Ceylon : Installation - Concepts de base - Typage - Appels et arguments

    ECM = Exemple(reproduit le problème) Complet (code compilable) Minimal (ne postez pas votre application !)
    Une solution vous convient ? N'oubliez pas le tag
    Signature par pitipoisson

  3. #3
    Membre confirmé Avatar de Lordsephiroth
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 199
    Par défaut
    Je ne suis pas sûr que la réponse convienne pour JPA. Avec une approche CMT, les transactions ne sont normalement pas manuellement traitées par le programmeur. Le conteneur applicatif se charge d'ouvrir et de fermer les transactions quand il le faut. Il est possible naturellement d'altérer le comportement du conteneur applicatif, ce que je cherche justement à faire.

    Dans l'approche BMT, il est vrai que le programmeur se charge lui-même d'ouvrir et de fermer les transactions. Dans le cadre de JPA, cela reviendrait je suppose à injecter un EntityManager au niveau de mon service applicatif et d'y ouvrir une transaction par getTransaction().begin(), puis de passer cet EntityManager pour chaque appel à mes services d'intégration, et de finalement appeler getTransaction.commit() après le dernier appel. Actuellement tout est réalisé avec des CMT, j'aurais donc préféré éviter cette solution qui impliquerait de changer la stratégie des entités pour passer en BMT (et donc de gérer les transactions manuellement pour l'application entière, ce qui induit un coût non négligeable en développement).

    J'ai vu dans ce topic du forum que'une annotation devrait permettre de réutiliser une transaction ouverte par l'appelant... je suppose donc que l'exemple est en stratégie CMT puisque la configuration est faite à l'aide d'annotations et non par programmation... Je n'arrive pourtant pas à voir exactement d'ou vient la transaction du parent, comment l'ouvrir, etc... puisqu'on ne s'en occupe généralement jamais en stratégie CMT.

  4. #4
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Par défaut
    Ca me fait penser aux aspects de transaction que fournie Spring.
    Le principe tu as une classe DAO avant chaque méthode du DAO Spring ouvre une connection et une transaction, s'il n'y a pas d'exception il commit la transaction sinon rollback, puis ferme la transaction et la connection.

    Dans un contexte comme celui-ci, tu peux avoir une méthode DAO qui appelles d'autres méthodes du DAO, Spring utilise la même connection et la même transaction.

    De toutes façons il y a bien quelqu'un qui doit fournir la connection à tes IntegrationService ?

    Pour info, c'est quoi BMT et CMT ?
    Java : Cours et tutoriels - FAQ - Java SE 8 API - Programmation concurrente
    Ceylon : Installation - Concepts de base - Typage - Appels et arguments

    ECM = Exemple(reproduit le problème) Complet (code compilable) Minimal (ne postez pas votre application !)
    Une solution vous convient ? N'oubliez pas le tag
    Signature par pitipoisson

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 277
    Par défaut
    C'est ton session bean (ejb 3) qui est porteur de la transaction.
    Pour chaque méthode tu peux définir si celle-ci crée une nouvelle transaction, utilise la transaction courante, n'en utilise pas, etc ... grâce aux attributs :
    Required
    RequiresNew
    Mandatory
    NotSupported
    Supports
    Never

    Ta couche inférieure utilisera la transaction définie au niveau de ton EJB, tu n'auras pas à la gérer à ce niveau.

  6. #6
    Membre confirmé Avatar de Lordsephiroth
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 199
    Par défaut
    Citation Envoyé par Nemek Voir le message
    Pour info, c'est quoi BMT et CMT ?
    Bean Managed Transaction et Container Managed Transaction respectivement. Dans le premier cas, tu manipules tes transactions manuellement, faisant des begin(), des rollback() et des commit(). Dans le second cas, le container du serveur applicatif gère pour toi la transaction. Il sait quand l'ouvrir, quand effectuer le commit, quand effectuer le rollback. C'est pratique pour la majorité des applications. C'est complexe d'altérer le comportement exactement de la façon voulue quand on s'écarte d'un cas d'utilisation standard (je pense d'ailleurs que mon cas ne s'écarte pas du cas standard, je ne sais juste pas le faire, et c'est ce que je cherche à éclaircir).

    Citation Envoyé par fr1man Voir le message
    C'est ton session bean (ejb 3) qui est porteur de la transaction.
    Voilà une information intéressante. Prenons un cas concret : mon service applicatif est un Stateless Session Bean EJB3 et possède une fonction execute(). A la fin de cette fonction, j'appelle N fois la fonction save() de mon service d'intégration pour l'objet Person et M fois la fonction save() de mon service d'intégration pour l'objet Vehicule.

    En code, je placerais donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
    juste avant la fonction execute() et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @TransactionAttribute(value = TransactionAttributeType.REQUIRED)
    juste avant la fonction save() de chaque service d'intégration. De cette manière, je m'assure qu'une transaction est ouverte pour l'exécution de la fonction execute(). Elle devrait de plus être réutilisée lors de l'appel aux différents save().

    J'ai tout juste ? Je n'ai malheureusement pas le temps de tester ça maintenatn, je suis passé sur autre chose, mais ce sera fait en début de semaine. Merci de m'indiquer si la suggestion a été bien interprétée.

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 277
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 277
    Par défaut
    Ce que tu appelles tes services d'intégration, ce sont aussi des méthodes de ton EJB ?

    Au niveau des paramètres, tu peux laisser en required, qui permet d'en créer une s'il n'en existe pas, et d'utiliser la transaction courante, si elle existe.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 07/04/2010, 14h40
  2. Réponses: 10
    Dernier message: 08/02/2007, 13h18
  3. utiliser un menu unique pour plusieurs pages...
    Par brouette dans le forum ActionScript 1 & ActionScript 2
    Réponses: 8
    Dernier message: 17/12/2006, 01h29
  4. [VBA-E]une macro unique pour plusieurs fichiers excel
    Par fanchic29 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 21/04/2006, 16h20
  5. utiliser une transaction avec le composant DBExpress
    Par vbcasimir dans le forum Bases de données
    Réponses: 1
    Dernier message: 09/06/2005, 14h10

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