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 :

Business methods Transaction Asynchronous


Sujet :

Java EE

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Septembre 2002
    Messages
    74
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 74
    Par défaut Business methods Transaction Asynchronous
    Bonjour, je me pose beaucoup de questions autour du terme business methods.
    En effet lors de mes dernières expériences, je constate plusieurs choses qui me laissent perplexe :

    Soit le code suivant simplifié...
    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
    @Stateless
    @LocalBean
    public AClass {
       @EJB
       BClass bclass;
     
       @TransactionAttribute(NOT_SUPPORTED)
       public void aMethod() {
           bMethod();
           cMethod();
           bClass.dMethod();
           bClass.eMethod();
       }
       @TransactionAttribute(REQUIRED_NEW)
       public void bMethod() {
       }
       @Asynchronous
       public void cMethod() {
       }
    }
     
    public BClass {
       @TransactionAttribute(REQUIRED_NEW)
       public void dMethod() {
       }
       @Asynchronous
       public void eMethod() {
       }
    }
    Je constate la chose suivante :
    aMethod comme prévu n'est pas dans une transaction : NOT_SUPPORTED.
    bMethod N'est PAS dans une transaction malgré REQUIRED_NEW
    cMethod N'est PAS Asynchronous malgré Asynchronous
    dMethod est dans une nouvelle transaction quoi qu'il arrive
    eMethod est asynchronous

    Donc si je comprends bien mes lectures et mes constatations : bMethod et cMethod ne sont pas des business method dans ce cas, mais pourrait l’être dans le cas d'un autre appel, les autres oui car elle sont appelées par extérieure de l'EJB.
    Je constate aussi la même chose quand à l'application des Interceptors.

    soit un interceptor :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public AInterceptor {
      @AroundInvoke
      public Object process(InvocationContext ic)  throws Exception {
         return ic.proccess();
      }
    }
    puis sur la class :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    @Interceptors(AInterceptor.class)  
        public class AClass {  ...}
    Seule la methode aMethod (appelé de l'exterieur) sera "décoré" par l'interceptor.

    Déjà à ce stade, je trouve cela bien dommage et surtout pas très clair.

    Maintenant un cas pratique :

    Soit un ejb gérant la persistance d'une Entity
    celui ci permet de persister une entité ou plusieurs entités à la fois comme suit, mais je veux que quoi qui l'arrive chaque persistance soit individuelle. Mais les transactions gérer par le container toujours.

    Naïvement :

    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
    ...
    @TransactionAttribute(REQUIRED_NEW)
    public void persistOk(MonEntity o) throws NokException(){
    // code de persistence metant en oeuvre plusieurs persitence d'objets
    ... throw new NokException(); // ou pas
    }
     
    @TransactionAttribute(REQUIRED_NEW)
    public void persistNok(MonEntity o) {}
     
    @TransactionAttribute(REQUIRED_NEW)
    public void persistList(Collection<MonEntity> list {
       for(MonEntity  o : list) {
          try {
            persistOk(o); 
          } catch(NokException ne) {
            persistNok(o);
          }
    }
    ...
    on pourrait imaginer que si j'appelle persistList, chaque persistOk et persistNok soit dans leur propre transaction. Il n'en ai rien. seule persistList crée une nouvelle transaction.
    Le code précédent ne marche donc pas.
    En revanche si vous déplacer dans un autre EJB les methodes persistOk et persistNok. tout rentre dans l'ordre.

    Quelque chose m’échappe ? Je réalise une grosse appli, et mes EJBs se compte par dizaines. et certains ont parfois plusieurs dizaines de méthode. Si mes constatation sont justes, il va falloir revoir pas mal de truc.
    Mes EJBs on plutôt tendances à gérer un coté fonctionnel. un EJB pour s'occuper des Users, un, EJB pour les Groups etc... N'est ce pas comme cela qu'il faut faire ???
    J'avoue être très perplexe. J'ai plutôt tendance à essayer de laisser le container gérer le plus de chose. Je sais bien que l'on peut gérer les Transaction en mode BEAN, mais je pense que normalement cela devrait être à utiliser qu'en cas d'impasse avec le container.
    Je lis tout ce qui me tombe sur la main, mais les exemples sont souvent très simplistes.
    Quelqu'un à t'il quelques tuyaux, ouvrages, tutos qui explique les transactions et tout ce qui va autour vraiment en détails ?

    Cordialement

  2. #2
    Membre actif
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Septembre 2002
    Messages
    74
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 74
    Par défaut Personne ne constate cela ?
    Je remonte le post, je suis étonné que personne n'est son avis la dessus. c'est pourtant primordiale.

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

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Par défaut
    Citation Envoyé par hhfr Voir le message
    Je remonte le post, je suis étonné que personne n'est son avis la dessus. c'est pourtant primordiale.
    Plein de gens sont, ou reviennent encore de vacances.

    Sinon pour tes questions:
    Citation Envoyé par hhfr Voir le message
    Je constate la chose suivante :
    aMethod comme prévu n'est pas dans une transaction : NOT_SUPPORTED.
    bMethod N'est PAS dans une transaction malgré REQUIRED_NEW
    cMethod N'est PAS Asynchronous malgré Asynchronous
    dMethod est dans une nouvelle transaction quoi qu'il arrive
    eMethod est asynchronous

    Donc si je comprends bien mes lectures et mes constatations : bMethod et cMethod ne sont pas des business method dans ce cas, mais pourrait l’être dans le cas d'un autre appel, les autres oui car elle sont appelées par extérieure de l'EJB.
    Je constate aussi la même chose quand à l'application des Interceptors.

    ...

    Quelque chose m’échappe ?
    La seule chose à savoir pour bien comprendre ce comportement, c'est que le container crée un wrapper (proxy) autour de l'instance de ta classe EJB qui n'est donc pas accessible directement depuis l'extérieur.
    Tous les appels (externes) vers ton ejb sont faits sur cet objet wrapper qui ensuite délègue vers ton instance ejb.
    C'est ce qui permet au container d'intercepter ces appels et d'appliquer les services "cross-cutting" (transactions, interceptors, asynchrone ou autres services AOP) configurés pour l'ejb avant délégation. Tous les containers (ejb, spring...) fonctionnent comme cela.

    Quand tu fais un appel interne (aMethod --> bMethod), le container ne peut pas "voir" ça pour l'intercepter, c'est comme si la méthode bMethod() était déclarée private dans ta classe. L'exécution de bMethod() dans ce cas va se faire dans le contexte de aMethod() et utiliser les attributs de transactions et autres interceptors déclarés pour aMethod().

    En principe c'est rare de faire ce genre d'appels internes, mais si tu veux vraiment faire cet appel de aMethod vers bMethod tout en conservant la sémantique configurée pour bMethod, le mieux à faire c'est d'obtenir une référence vers l'objet wrapper (getBusinessObjet ou getEJBLocalObjet) du bean courant et de faire ensuite l'appel:

    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
    @Stateless
    @LocalBean
    public AClass {
       @EJB
       BClass bclass;
    
       private @Resource SessionContext ctx;
     
       @TransactionAttribute(NOT_SUPPORTED)
       public void aMethod() {
           ctx.getBusinessObject(AClass .class).bMethod();
           ....
       }
    
       @TransactionAttribute(REQUIRED_NEW)
       public void bMethod() {
       }
    
       @Asynchronous
       public void cMethod() {
       }
    }
     
    public BClass {
       @TransactionAttribute(REQUIRED_NEW)
       public void dMethod() {
       }
       @Asynchronous
       public void eMethod() {
       }
    }
    C'est à tester, mais je crois que ça devrait faire l'affaire.

    Bon courage.

  4. #4
    Membre actif
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Septembre 2002
    Messages
    74
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 74
    Par défaut Interessant
    Intéressant, je vais tester ça. Malgré mes constatations et mes modifications en conséquences, je ne trouvais pas cela très clair ou logique.

    Par contre, tu dis que c'est plutôt rare comme appel, mais, on n’arrête pas de faire des appels de méthodes au sein d'un même EJB. J'ai rien compris d'après toi ?
    L'exemple de la persistance de X entities via une boucle est pourtant pas si rare. Si ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @TransactionAttribute(REQUIRED_NEW)
    public void persistSingle(MonEntity o) throws NokException(){
    ... throw new NokException(); // ou pas
    }
     
    public void persistList(Collection<MonEntity> list {
       for(MonEntity  o : list) {
          try {
            persistSingle(o); 
          } catch(NokException ne) {
            log.error(...);
          }
    }
    Ceci n'est pas un mauvais pattern avec JPA ? Si ?

    En tous cas, ton explication du proxy est intéressante. Ceci dit, la modification à chaud du code aurait été aussi une solution non ? Cela aurait aussi été envisageable et avec une couverture plus large.

    Sinon, au niveau perf, cela n'aura pas d'incidence de faire appel à la business méthode ? Comme tu le suggère ?

  5. #5
    Membre actif
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Septembre 2002
    Messages
    74
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 74
    Par défaut ca marche
    Effectivement cela marche.

    J'ai pensé aussi à un autre exemple ou cette histoire de proxy n'est pas top, quand tu utilises un interceptor pour logger/bencher par exemple, seule les méthodes business sont "décorées".

    Mais bon, ta solution est quand même plus élégante que de systématiquement découper les ejbs en x morceaux pour profiter des fonctions du container.

    Merci en tous cas.

  6. #6
    Membre actif
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Septembre 2002
    Messages
    74
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 74
    Par défaut Petite deception
    Après avoir testé cela chez moi et constaté le fonctionnement, teste grandeur réelle sur le projet sur lequel je travaille. Et là surprise, cela ne marche plus.
    la récupération du businessObject via :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ctx.getBusinessObject(AClass.class);
    retourne tout simplement null.

    Différence entre chez moi et au taf, la différence de version de glassfish. 3.01 au boulot, 3.1 at home.

    La migration vers la 3.1 n'étant pas tout a fait à l'ordre du jours (mais prévu), quelqu'un sait il si cela peut venir de la ?

    Merci

Discussions similaires

  1. Business Method sous Net 6
    Par abdoinfo dans le forum NetBeans
    Réponses: 0
    Dernier message: 14/02/2011, 09h15
  2. methodes en asynchrones
    Par micka132 dans le forum Silverlight
    Réponses: 4
    Dernier message: 29/06/2010, 11h36
  3. Réponses: 24
    Dernier message: 13/11/2006, 09h00
  4. Réponses: 1
    Dernier message: 12/06/2006, 19h02
  5. [JSP][EJB]usebean --> utilisation d'une business method
    Par Eric Berger dans le forum Servlets/JSP
    Réponses: 4
    Dernier message: 23/05/2006, 09h04

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