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 EE Discussion :

Problème accès concurrents/transaction


Sujet :

Java EE

  1. #1
    Candidat au Club
    Inscrit en
    Octobre 2006
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Problème accès concurrents/transaction
    Bonjour,

    pour Exemple: Mon application comporte deux EJB sessions stateless, et trois EJB entity CMP. Voici l'exemple de code
    EJBSession ejbsession1 {
    save(param1, param2, param3) {
    ejbEntity1.create(param1, param2);
    while (notFinished) {
    ejbSession2.save(param3);
    }
    }
    }

    EJBSession ejbsession2 {
    save() {
    ejbEntity3.findByPrimarykey(param3);
    ejbEntity2.create();
    }
    }

    Mon souci: Lorsque un premier traitement appelle la méthode save de ejbsession1, puis qu'un deuxième traitement appelle également cette méthode avant la fin du premier, je me retrouve avec un deadlockException lors du finder sur ejbEntity3 du traitement 2.

    D'après moi, une transaction est ouverte en mode mise à jour dès le début du save de ejbsession1. Dès lors, les créations, ainsi que les finders de la méthode save de ejbsession2 sont au sein de cette transaction, et du coup le finder vérouille la table, selon le principe "SELECT...FOR UPDATE".
    Quand mon deuxième traitement passe, et essaye d'effectuer le finder sur le même enregistrement, il se retrouve en concurrence et me lève une exception.

    essai 1- Paramétrage de la méthode findByPrimary de ejbEntyty3 en demandant de n'être dans aucune transaction ("NOT Supported" dans le descripteur de déploiement).
    résultat essai1- Gel du traitement lors du finder, rien ne se passe

    essai 2- Paramétrage des tentatives d'accès (access-intent) de l'ejbEntyty3 en "PessimisticRead" dans le descripteur de déploiement, avec espoir que du coup aucun vérouillage ne serait fait, même au sein d'une transaction de Mise à jour
    résultat essai2- Gel du traitement lors du finder, rien ne se passe.

    Je ne sais pas si cela est clair.

    Quelqu'un aurait-il une idée?

    Merci d'avance pour votre aide.

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Points : 495
    Points
    495
    Par défaut
    Salut,
    J'ai un peu de mal à comprendre ton code, et je me demande s'il ne faudrait pas revoir un peu la conception. D'abord, pourquoi deux Beans Session pour faire la même chose (méthodes save() différentes uniquement par les paramètres). Tu pourrais très bien mettre ces méthodes surchargées dans le même EJB Session1 et appeler l'une dans l'autre, ça éviterait ainsi de devoir définir une référence à Session2 dans Session1. En plus, je ne comprends pas trop cette boucle while :
    while (notFinished) {
    ejbSession2.save(param3);
    }
    Qu'est-ce qui est "notFinished" et à quel moment la condition d'arrêt devient-elle "false" ?
    essai 1- Paramétrage de la méthode findByPrimary de ejbEntyty3 en demandant de n'être dans aucune transaction ("NOT Supported" dans le descripteur de déploiement).
    résultat essai1- Gel du traitement lors du finder, rien ne se passe
    Les beans entity ne supportent comme attributs de transaction que : Mandatory, Required, ou RequiresNew. Certains serveurs peuvent permettre de spécifier un autre attribut (comme NotSupported) mais dans ce cas le comportement n'est pas spécifié dans la spécification et le Bean n'est pas portable.
    D'après moi, une transaction est ouverte en mode mise à jour dès le début du save de ejbsession1. Dès lors, les créations, ainsi que les finders de la méthode save de ejbsession2 sont au sein de cette transaction, et du coup le finder vérouille la table, selon le principe "SELECT...FOR UPDATE".
    Quand mon deuxième traitement passe, et essaye d'effectuer le finder sur le même enregistrement, il se retrouve en concurrence et me lève une exception.
    En principe, les méthodes Finder ne verrouillent pas la base de données, ou en tout cas pas FOR UPDATE, puisque les mises à jour pour un bean entity viennent plutot de "business methods", mais enfin, je ne sais plus trop, est-ce que cela dépendrait du SGBD que tu utilises ? En plus les beans entity sont transactionnels de nature, donc le container se charge de gérer les accès concurrents à une même instance de bean entity.
    Voilà, je n'ai pas tout compris de ton problème, si tu pourrais éclaircir un peu plus sur ce que tu veux faire réellement.
    En espérant t'avoir aidé ...
    SCJP 5 / SCBCD 1.3 Certified

  3. #3
    Candidat au Club
    Inscrit en
    Octobre 2006
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Salut,

    manblaizo, merci de ta réponse. Il est vrai que je n'ai pas été clair, je voulais rester concis au niveau du code pour me concentrer sur le problème de "principe".
    En fait, dans le cadre d'un service de passage de commande, je possède deux EJB Session. L'un, qui concerne l'entête de la commande, avec des informations générales, et un autre qui concerne une ligne de commande.
    j'ai fait deux EJB Session afin de séparer les contrôles et la logique pour ces deux types d'information. Si je reprends mon exemple:

    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
     
    public class SessionEnteteDeCommande implements javax.ejb.SessionBean{
    	private static SessionLigneDeCommandeLocalHome sessionLigneDeCommandeLocalHome;
    	private static EntityEnteteDeCommandeLocalHome entityEnteteDeCommandeLocalHome;
     
    	public void saveNew(param1Entete, param2Entete, vectorLigneDeCommandes) {
     
    		InitialContext ic = new InitialContext();
    		sessionLigneDeCommandeLocalHome = (SessionLigneDeCommandeLocalHome ) ic.lookup("java:comp/env/ejb/SessionLigneDeCommande");
    		entityEnteteDeCommandeLocalHome= (EntityEnteteDeCommandeLocalHome ) ic.lookup("java:comp/env/ejb/EntityEnteteDeCommande");
     
    		entityEnteteDeCommandeLocalHome.create(param1Entete, param2Entete);
    		for (int nbLigne = 0; nbLigne < vectorLigneDeCommandes.size();nbLigne++) {
    			sessionLigneDeCommandeLocalHome.create().saveLigneDeCommande((BeanSimpleLigneDeCommande)VectorLigneDeCommandes.get(nbLigne));
    		}
    	}
    }
     
    public class SessionLigneDeCommande implements javax.ejb.SessionBean{
    	private static EntityLigneDeCommandeLocalHome entityLigneDeCommandeLocalHome;
    	private static EntityTypeDeLivraisonLocalHome entityTypeDeLivraisonLocalHome;
     
    	public void saveLigneDeCommande(BeanSimpleLigneDeCommande beanSimpleLigneDeCommande) {
     
    		InitialContext ic = new InitialContext();
    		entityLigneDeCommandeLocalHome = (EntityLigneDeCommandeLocalHome ) ic.lookup("java:comp/env/ejb/EntityLigneDeCommande");
    		entityTypeDeLivraisonLocalHome= (EntityTypeDeLivraisonLocalHome) ic.lookup("java:comp/env/ejb/entityTypeDeLivraison");
     
     
    		EntityTypeDeLivraisonLocal entityTypeDeLivraisonLocal = entityTypeDeLivraisonLocalHome.findByPrimaryKey(beanSimpleLigneDeCommande.getTypeDeLivraison());
     
    		if (entityTypeDeLivraisonLocal.getIsActif()==1) {
    			entityLigneDeCommandeLocalHome.create(beanSimpleLigneDeCommande.getFieldA(), beanSimpleLigneDeCommande.getFieldB(), ...);
    		}
    	}
    }
    Donc, lorsque deux traitements concurrents (l'un depuis l'application web, l'autre depuis un scheduler sur le même serveur d'application) font appel à la méthode saveNew de SessionEnteteDeCommande, je me retrouve avec un deadLockException sur la demande findByPrimaryKey de entityTypeDeLivraisonLocalHome.
    J'espère avoir été plus clair, mais effectivement, je ne comprends pas pourquoi je plante sur un find. C'est pour ça que j'ai supposé que, comme j'étais au sein d'une transaction de mise à jour, le find ByPrimaryKey devait vérouiller l'enregistrement.
    La base de donnée est DB2 AS400, et le serveur est un serveur WAS.

    Merci

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Points : 495
    Points
    495
    Par défaut
    Bonjour,
    OK, si je comprend bien, l'objectif c'est d'insérer une nouvelle commande avec les détails (LigneCommandes) correspondants. Je continue à penser qu'il y a possibilité de n'utiliser qu'un seul bean session et exploiter la relation CMR entre les beans entity EnteteCommande et LigneCommande. Mais bon, le "problème de principe" n'est peut-être pas là. Effectivement, ce DeadlockException sur la méthode findByPrimaryKey du bean EntityTypeDeLivraison me surprend un peu aussi, car je n'avais jamais rencontré ça jusque-là. Le container est censé s'occuper de ces problèmes de transactions concurrentes.
    Une piste serait peut-être de paramétrer ce bean en "Optimistic Read" comme méthode d'accès, ce qui permettrait de libérer le verrou après lecture des données. Essaie aussi de paramétrer les attributs de transaction à "RequiresNew" pour les méthodes findByPrimaryKey() et getIsActif(), pour faire en sorte que ces méthodes s'exécutent dans une nouvelle transaction qui ne s'éterniserait pas et permettrait de libérer les verrous rapidement.
    Une autre solution serait d'essayer de déployer l'application sur un autre serveur d'application, et tenter un autre SGBD pour voir d'où peut bien venir le problème.
    Voilà juste quelques pistes, j'espère que ça aide.
    SCJP 5 / SCBCD 1.3 Certified

Discussions similaires

  1. Réponses: 7
    Dernier message: 17/09/2012, 06h13
  2. [PostgreSQL] Problèmes accès concurrents
    Par mnementh64 dans le forum JDBC
    Réponses: 3
    Dernier message: 28/06/2010, 16h48
  3. même problème acces concurrent aux fichiers sur le serveur
    Par al3alwa dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 11/06/2007, 16h51
  4. Appli Web, problème accès concurrent
    Par the java lover dans le forum Servlets/JSP
    Réponses: 5
    Dernier message: 12/06/2006, 10h11
  5. (débutant) Problème accès concurrents
    Par lolo... dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 09/12/2005, 08h49

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