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

Autres Java Discussion :

[AspectJ] Puis-je espérer localiser (internationaliser) des objets métiers de la manière suivante ?


Sujet :

Autres Java

  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    605
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 605
    Points : 670
    Points
    670
    Par défaut [AspectJ] Puis-je espérer localiser (internationaliser) des objets métiers de la manière suivante ?
    Bonjour,

    J'ai un site web sur lequel les internautes peuvent venir de plusieurs lieux étrangers avec des langues distinctes, bien sûr.

    Pas de problème pour le site web : ça gère, comme on dit.

    Je me suis aussi dépatouillé pour que les services EJB invoqués reçoivent aussi les locales choisies par l'internaute (une liste ordonnée de ses préférences comme : [en_US, de, fr_CA, fr]), afin que s'ils ont des messages à lui retourner, ils les fassent dans l'une des langues qu'il attend, en fonction du mieux qu'ils sont capables.

    Le problème vient des objets métiers.
    Car, classiquement, ils n'ont qu'un constructeur sans argument et se doivent de le garder, sauf à en passer – au long cours – par une grande variétés de problèmes annexes, connexes, et contrariants.

    Cependant, parmi mes objets métiers, certains émettent des messages. Un objet Email, par exemple, est capable d'auto-contrôler la justesse de construction de son adresse et de renvoyer le message qui explique pourquoi elle est mal formée.
    Et j'ai aussi quelques enum "à ressources", c'est à dire qu'ils sont associés à des clefs de propriétés liées à des bundles pour renvoyer, le cas échéant, une description de ce qu'ils représentent.
    Et le problème, bien entendu, c'est qu'un POJO construit avec son constructeur sans argument, eh bien, il ne peut se mettre qu'en Locale.Default, et donc fera l'importun qui continuera à parler en français à un internaute toltèque venu inopinément dans le Ratanakiri septentrional, et espérant de nous qu'on lui parle dans une variante en sonnets.

    Il ne m'est pas possible de déléguer la création des messages finaux à la seule interface web, parce que :
    - il y en a beaucoup.
    - la construction des messages peut réclamer des éléments dont le contenu n'est connu qu'à un instant précis et ne l'est plus dans l'interface web. Les messages paramétrés sont souvent dans ce cas et ne peuvent être faits qu'au bon moment, dans une couche logicielle donnée, lorsque que l'interprétation d'une situation est claire, l'environnement bien connu, et permet de décrire parfaitement ce qui se passe.
    - un certain nombre de messages ne sont pas émis par moi, mais des API tierces parties, localisables, mais dont je ne peux pas prévoir à l'avance tous les messages qu'elles sont capables de produire.


    Il m'a semblé possible de résoudre le problème ainsi :

    Un certain nombre d'objets métiers vont devenir éligibles à la localisation en implémentant une interface Localisable, qui contiendra :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    public Locales getLocales(); // où Locales extends ArrayList<Locale>, et représente les choix de l'internaute dans l'ordre de ses préférences.
    public void setLocales(Locales locales);
    Et je voudrais par une ou plusieurs règles AspectJ (ou un autre moteur de POA, s'il y en a un de meilleur ?!) définir un comportement qui serait celui-ci :
    à l'issue de la construction d'un objet qui implémente l'interface Localisable, si la classe qui a provoqué sa construction implémente aussi cette interface, alors il est exécuté un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    objetCréé.setLocales(objetDemandantLaCréation.getLocales());
    Est-ce possible ?

    En vous remerciant,

    Grunt.

  2. #2
    Membre éclairé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    605
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 605
    Points : 670
    Points
    670
    Par défaut
    J'ai avancé jusqu'à un point où je me trouve bloqué, sans savoir si je peux ou non passer l'obstacle.

    J'ai écrit cet aspect, qui se fonde sur les interfaces Localisable dont j'ai parlé :
    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
    /**
     * Aspect provoquant la circulation de locales entre objets lors de leur création.
     */
    @Aspect public class CirculationDeLocales
    {
       /**
        * Déclaration du pointcut de circulation de locales d'un objet à un autre, pour alimenter un objet créé avec les locales de celui qui l'a créé.
        * @param cible Objet localisable à créer.
        * @param appelant Objet localisable créateur de l'objet.
        */
       @Pointcut("target(cible) && this(appelant) && (execution((LocalisableIF+).new(..)))") 
       public void declarationCirculation(@SuppressWarnings("unused") LocalisableIF appelant, @SuppressWarnings("unused") LocalisableIF cible)
       {
       }
     
       /**
        * Provoquer la circulation de locales d'un objet à un autre, pour alimenter un objet créé avec les locales de celui qui l'a créé.
        * @param cible Objet localisable à créer.
        * @param appelant Objet localisable créateur de l'objet.
        */
       @After("declarationCirculation(appelant, cible)") 
       public void circulation(LocalisableIF appelant, LocalisableIF cible)
       {
          Validate.notNull(cible, "La cible du passage de locales ne peut pas valoir null."); //$NON-NLS-1$
          Validate.notNull(appelant, "La source du passage de locales ne peut pas valoir null."); //$NON-NLS-1$
     
          Ressources rsc = new Ressources(CirculationDeLocales.class);
     
          if (rsc.isDebugEnabled())
             rsc.debug("log.circulation_locale", cible.getClass().getName(), appelant.getClass().getName()); //$NON-NLS-1$
     
          cible.setLocales(appelant.getLocales());
       }
    }
    Mais le test que j'ai prévu pour valider mon aspect et qui utilise un objet ObjetNonMetierLocalisable implements LocalisableIF – un objet qui s'initialise par défaut avec la Locale par défaut du système (fr_FR, pour moi) – n'a pas fonctionné comme souhaité.

    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
    37
    38
    39
    40
    41
    /**
     * Test de l'aspect "Circulation des locales".
     */
    public class TestAspectCirculationLocales
    {
       @SuppressWarnings("javadoc") 
       public class A extends ObjetNonMetierLocalise
       {
          public B creerB()
          {
             B b = new B();
             return(b);
          }
       }
     
       @SuppressWarnings("javadoc") 
       public class B extends ObjetNonMetierLocalise
       {
       }
     
       /**
        * Une circulation de locales d'un objet A à un objet B.
        */
       @Test public void circulationSimple()
       {
          // Nous attribuons à un objet A des locales.
          Locales localesAppelant = new Locales(Locale.FRENCH, Locale.ITALY);
     
          A a = new A();
          a.setLocales(localesAppelant);
          assertEquals("A n'a pas convenablement fixé ses locales de départ.", localesAppelant, a.getLocales()); //$NON-NLS-1$
     
          // Et nous créons un objet B par le biais de A. L'aspect est supposé se déclencher après le new.
          B b = a.creerB();
     
          // Dans les locales de l'objet créé, nous devons retrouver celles de l'appelant.
          Locales localesCible = b.getLocales();
          assertNotNull("L'objet créé n''a reçu aucune locale de l'appelant.", localesCible); //$NON-NLS-1$
          assertEquals("Les locales de l'objet créé ne sont pas celles de l'appelant.", localesAppelant, localesCible); //$NON-NLS-1$
       }
    }
    Il échoue sur la dernière assertion, par un message :
    "Failed tests: circulationSimple(test.utils.localisation.TestAspectCirculationLocales): Les locales de l'objet créé ne sont pas celles de l'appelant. expected:<[fr, it_IT]> but was:<[fr_FR]>".

    Si je le passe en debug, j'arrive bien dans l'aspect qui s'exécute normalement. À ceci près que les paramètres appelant et cible désignent les mêmes pointeurs. De sorte que quand je fais le :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cible.setLocales(appelant.getLocales());
    je donne un coup d'épée dans l'eau : je me réaffecte à moi-même ce que j'ai déjà.

    D'après ce que j'ai lu d'AspectJ,
    il est normal pour un pointcut en initialize de renvoyer pour valeurs de target et this le même pointeur parce que AspectJ se considère à l'intérieur du constructeur sans rien savoir d'autour.

    Mais, en revanche, avec un pointcut en execution, j'espérais qu'il me mettrait pour :
    - this(appelant) : l'objet qui a entrepris d'en créer un autre, c'est à dire : A a;
    - target(cible) : l'objet qui vient d'être créé, B b;
    Or donc, mes paramètres appelant et cible désignent tous deux B b.

    J'ai essayé de replacer l'execution par un call,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @Pointcut("target(cible) && this(appelant) && (call((LocalisableIF+).new(..)))")
    mais mon aspect n'a même pas été tissé, sans que je comprenne bien pourquoi (je suis très jeune sur les aspects).

    Il y a t-il une solution pour obtenir le résultat que je désire, ou bien suis-je devant une impossibilité d'AspectJ ?

    Merci !
    Grunt.

Discussions similaires

  1. Mapper des objets métier sur une base existante (mais pas un simple mapping)
    Par NaBuCO dans le forum Persistance des données
    Réponses: 2
    Dernier message: 13/04/2012, 16h24
  2. Réponses: 12
    Dernier message: 03/07/2009, 14h37
  3. [ZF 1.8] [débutant] Quelle est la place des objets métier dans zf ?
    Par Trycias dans le forum Zend Framework
    Réponses: 3
    Dernier message: 21/05/2009, 20h14
  4. Question sur la gestion des objets métier
    Par viddak dans le forum Développement Web en Java
    Réponses: 1
    Dernier message: 24/11/2008, 08h06
  5. Utiliser des objets métiers d'un autre package
    Par mickilous dans le forum GWT et Vaadin
    Réponses: 7
    Dernier message: 05/08/2008, 18h48

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