De l’importance de bien comprendre les contextes Spring

Baptiste Autin, le 31 août 2013

Récemment, j’ai eu à intervenir sur une application web qui posait problème : toutes les annotations @Transactional, définies au niveau des classes métier, semblaient inopérantes, malgré la définition correcte d’un gestionnaire transactionnel dans le contexte Spring principal.

Je précise que les méthodes annotées étaient bien publiques (rappelons que c’est l’une des conditions du fonctionnement de l’annotation @Transactional avec les proxys JDK)

Que diable se passait-il ?

 

Dans le fichier applicationContext.xml (= contexte Web), j’ai bien trouvé la déclaration du manager JPA :

    
    
        
    

Ainsi que les beans de service de l’application, détectés par scan :

                               
       

Je m’attendais donc à ce que le fichier myapplication-servlet.xml (= contexte Spring MVC), quant à lui, définisse les contrôleurs de l’application.
Mais voici ce que je vis :

    

Au lieu de se contenter de scanner le paquetage où étaient rangés les controleurs MVC (dans foo.myapplication.controllers), on scannait tout le paquetage de l’application !
Du coup, on scannait aussi une deuxième fois les beans de la couche métier (notez au passage que cela ne pose pas de problème à Spring).

Or, comme beaucoup d’autres choses dans le framework Spring, le support déclaratif des transactions repose sur des proxys AOP, et les proxys AOP ne sont valides que dans le contexte Spring où ils sont définis, par conséquent la déclaration <tx:annotation-driven />, pourtant bien présente dans le contexte principal, devenait inopérante dans le contexte MVC.
Du coup, les annotations @Transactional restaient sans effet pour tous les beans de service qui étaient injectés dans des beans du contexte MVC (comme les beans @Controller).

La solution à mon problème a tout simplement consisté à limiter, dans le fichier myapplication-servlet.xml, le scan aux seules classes contrôleurs :

    

Les beans métiers et DAO sont maintenant uniquement définis dans le contexte principal, c’est à dire là où se trouve également défini le gestionnaire JPA.

 

Moralité
Le contexte Spring MVC ne devrait contenir que la définition des composants relatifs au framework MVC utilisé, et surtout pas de logique métier ou d’accès aux données.
Ne pas respecter ce principe, c’est non seulement problématique du point de vue architectural, mais c’est aussi s’exposer à des erreurs qui peuvent rester longtemps inaperçues.

Laisser une réponse

«     »