Comment récupérer les propriétés d’une annotation avec Spring AOP

Pour les besoins d’une application offrant la possibilité de spécifier des formules pour le calcul de rubrique de paye, je souhaitais enrichir l’entité JPA représentant les formules choisies par l’utilisateur de l’application avec une référence sur l’algorithme « Programme » à exécuter. Vous l’aurez noté l’algorithme est une classe qui implémente un calcul, il varie d’une formule à l’autre et par conséquent il ne peut pas être représenté sous la forme d’une entité JPA. Par contre la formule possède une référence (un identifiant) sur un programme (algorithme). Il fallait donc trouver un moyen pour associer la formule et son algorithme après le chargement de l’entité. Bien entendu je me suis penché immédiatement sur la spécification JPA qui offre la possibilité de déclarer un listener sur les entités et ainsi gérer des événements liés au cycle de vie de ces objets.

Très rapidement j’ai mis de côté cette possibilité qui me conduisait à lier la couche métier avec des services utilisés pour charger certains types de programme. Je me suis donc orienté vers une solution basée sur l’AOP (Aspect Oriented Programming) afin de mettre en oeuvre ce chargement de données sans compromettre le principe d’isolation des couches.
L’idée était de créer une annotation et d’utiliser un aspect pour intercepter tous les appels de méthodes annotées avec cette annotation spécifique. De plus je souhaitais pour plus de souplesse que le traitement réalisé sur les méthodes annotées puisse être modifié si ce mécanisme était utilisé dans d’autres situations ou sur d’autres entités. Spring était utilisé dans ce projet et, tout naturellement, je souhaitais que l’on puisse spécifier dans l’annotation le nom du bean implémentant la logique de l’intercepteur à exécuter.

J’ai commencé par créer l’annotation qui porte nom du bean Spring devant être exécuté sur la méthode annotée.


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PostLoadInterceptor {
    String interceptor();
}

Puis le code de l’aspect

@Aspect
@Component
public class PostLoadInterceptorAspect {
    private static Logger logger = LoggerFactory.getLogger(PostLoadInterceptorAspect.class);
    @AfterReturning(pointcut = "@annotation(PostLoadInterceptor)", returning = "result")
    public Object intercept(JoinPoint jp, Object result) {
        Optional interceptor = getHandlerClassFrom(jp);
        if (interceptor.isPresent()) {
            Object handler = beanUtils.getBean(interceptor.get().interceptor());
            if (LifeCycleInterceptor.class.isAssignableFrom(handler.getClass())) {
                result = ((LifeCycleInterceptor) handler).handle(result);
            }
        }
        return result;
     }
    private Optional getHandlerClassFrom(JoinPoint jp) {
        PostLoadInterceptor interceptor = null;
        final MethodSignature methodSignature = (MethodSignature) jp.getSignature();
methodSignature.getMethod();
        try {
            Method method = jp.getTarget().getClass().getMethod(methodSignature.getMethod().getName(), methodSignature.getMethod().getParameterTypes());
            interceptor = method.getAnnotation(PostLoadInterceptor.class);
        } catch (SecurityException | NoSuchMethodException e) {
            logger.warn("Erreur lors de la recherche de l'annotation PostLoadInterceptor dans la classe {}  message {}", jp.getTarget().getClass().getName(), e.getMessage());
        }
        return Optional.ofNullable(interceptor);
    }
}

Et enfin l’illustration de l’utilisation de l’annotation sur une méthode d’un service.


public class FormuleServiceImpl implements FormuleService {

    @Autowired
    private FormuleDao formuleDao;

    @Override
    @PostLoadInterceptor(interceptor = "formulePostLoadInterceptor")
    public Formule findOne(Integer id) {
        return formuleDao.findOne(id);
    }
    ...

Dans cet exemple de code, l’objet beanUtils est un composant dont la responsabilité est de s’interfacer avec le contexte de Spring pour charger un bean Spring.
J’ai fait le choix que les beans implémentant les intercepteurs, devaient respecter une interface particulière (LifeCycleInterceptor) qui définit une méthode handle(Object value). celle ci prend en paramètre l’objet renvoyé par la méthode sur laquelle l’annotation a été positionnée. L’aspect est également exécuté uniquement si la méthode annotée s’est correctement exécutée (@AfterReturning).
Mais la plus grande difficulté a été de récupérer la propriété de l’annotation (ici le nom du bean devant être exécuté) car si l’annotation est positionnée sur une classe concrète (versus une interface) JoinPoint.getSignature() renvoie la signature de la méthode définie dans l’interface implémentée par le bean et cette dernière ne porte pas l’annotation. L’idée est donc de récupérer via l’objet JointPoint la classe et la méthode portant l’annotation (ici un bean Spring).
J’espère que cet article un peu technique permettra à certains lecteurs de mettre en place ce type de fonctionnalité sans difficulté… Pour moi ce sera un mémo 😉

http:///www.jperf.com

 

Publicités
Publié dans tech notes | Tagué | Laisser un commentaire

Quelles métriques pour mesurer l’expérience utilisateur?

L’expérience utilisateur est défini comme un concept apparu dans les années 2000 pour tenter de qualifier le résultat (bénéfice) et le ressenti de l’utilisateur (expérience) lors d’une manipulation (utilisation provisoire ou récurrente) d’un objet fonctionnel ou d’une interface homme-machine (source wikipedia).

C’est cette expérience utilisateur qui est au cœur de la stratégie de développement des grands noms du commerce sur internet. Lorsqu’on sait qu’un internaute s’impatiente à partir de 2 secondes d’attente, ou que le taux d’abandon augmente de 40% lorsque le chargement d’une page passe de une à cinq secondes on comprend pourquoi ces sociétés investissent beaucoup de moyens dans l’optimisation de leurs sites web.

Dans ce contexte, le temps de chargement d’une page web revêt une attention toute particulière que les experts essayent de mesurer efficacement. Deux aspects sont primordiaux dans l’analyse de l’expérience utilisateur: Le contenu de la page doit commencer à s’afficher très rapidement pour permettre à l’utilisateur d’interagir avec l’application, et le chargement de la partie visible de la page doit être privilégié. La partie en dessous de la ligne de flottaison est moins importante du fait qu’elle n’est pas immédiatement visible par l’utilisateur. C’est ce sentiment d’interactivité avec l’application qui va satisfaire ou non l’internaute.

« Page load time »

La mesure la plus ancienne permettant d’analyser la vitesse de chargement d’une page est fournit par la méthode window.onload(). Cette métrique identifie le temps nécessaire au chargement, par le navigateur, de toutes les ressources de la page. Cette méthode, largement utilisée par le passé, n’est plus adaptée car un grand nombre de sites sont devenus entièrement dynamique et les ressources des pages sont chargées de façon asynchrone. De fait il est possible que cette métrique soit inférieure (ou supérieure) au temps nécessaire pour afficher le contenu de la page.

Steve Souders, un des experts mondiaux de la performance, rapportait en 2013 que certains sites internet pouvaient s’afficher très rapidement mais cet indicateur windows.onload révélait que le temps de chargement des pages étaient lent. Pourquoi? Parce que tout simplement le contenu au dessus de la ligne de flottaison de la page s’affichait rapidement et que le reste du contenu de la page prenait un peu plus de temps à se charger.

« Start render »

Certains sites tel que webpagetest fournissent un indicateur « start render » qui mesure le moment ou le contenu de la page commence à apparaître dans le navigateur. C’est un indicateur intéressant car il indique le moment à partir duquel l’internaute commence à voir le résultat de son action. Mais il reste insuffisant car il n’indique pas quand l’internaute peut interagir avec le site. Ce n’est donc pas non plus la métrique idéale pour mesurer cette expérience utilisateur.

« Speed index »

Le « speed index » prend en compte la progression du chargement de la partie visible de la page et calcule un score global mesurant la rapidité avec laquelle le contenu est affiché. Pour calculer cette métrique WebPagetest utilisait un algorithme qui analysait une capture vidéo du chargement de la page à raison de 10 frames par seconde, plus récemment WebPagetest a implémenté un procédé d’analyse basé sur des événements émis par le navigateur lors du rendu de la page. Le détail du calcul du « speed index » est décrit sur le site WebPageTest  (https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index).
Ce score mesure donc la vitesse à laquelle la partie de la page se situant au dessus de la ligne de flottaison est affichée : plus le score est bas, plus la page s’est affichée rapidement.
Cette métrique illustre plutôt bien la qualité de l’expérience utilisateur mais elle n’est disponible qu’au travers de WebPageTest.

« Time to First Contentful Paint (TTFCP) »

Plus récemment les métriques TTFCP « Time to First Contentful Paint » et TTFP « Time to First Paint » exposent des informations qui peuvent permettre aux développeurs de mieux comprendre la performance du chargement des sites internet, et mesurer l’expérience utilisateur. Ces nouveaux indicateurs sont disponibles au travers de l’API « Paint timing API » du navigateur Chrome.

Solutions spécifiques

D’autres initiatives commencent à voir le jour telles que Hero Rendering Times disponible dans la solution SpeedCurve. Cette solution part de l’idée qu’il faut pouvoir spécifier ce qui doit être mesuré dans une page, et que tous les éléments d’une page n’ont pas la même importance du point de vue de l’internaute. Par exemple l’affichage d’un encart publicitaire au dessus de la ligne de flottaison a t-il la même importance que les autres informations présentées sur la page?

https://www.jperf.com

Publié dans Uncategorized | Laisser un commentaire

Comment planter un chantier d’amélioration des performances

Il existe de nombreuses façons de faire échouer un chantier d’amélioration des performances, mais il en existe une qui relève du sponsoring.

L’amélioration des performance relève des exigences non fonctionnelles et ces dernières sont souvent sont reléguées au second plan dans les phases de qualification d’un logiciel.

De fait les problématiques de performance sont étudiées très tardivement dans le cycle de développement. Malheureusement à ce stade, la solution à ces problèmes de performance peuvent conduire à remettre en cause l’architecture du logiciel.

Pour reprioriser l’analyse des performances il est nécessaire que cette activité soit portée par un sponsor. Une personne qui peut prendre des décisions et impulser des actions, mobiliser des équipes, organiser des « war rooms »… Une personne qui travaille en collaboration intelligente avec ses propres équipes d’experts. Ce sponsor  doit avoir confiance dans les compétences de ces équipes, il doit se reposer sur celles ci pour appuyer les prises de décisions, les choix, les orientations. Lorsque cela s’avère nécessaire, il doit également pouvoir exercer une pression sur les prestataires afin qu’ils prennent en compte dans le plan de développement, les actions d’amélioration des performances qui ont été identifiées par ses équipes techniques.

Imaginez un manager décisionnaire qui ne consulte pas ses équipes et qui négocie, avec un acteur du projet, des actions techniques qui n’ont pas reçues l’aval des experts de l’entreprise. Est ce un sponsor?

Sans sponsor décisionnaire proche de ses consultants, il est très difficile de faire appliquer rapidement des préconisations d’amélioration des performances qui n’ont pas de valeurs ajoutées d’un point de vue fonctionnel et qui peuvent avoir un impact significatif sur le développement du produit final.

Le risque est donc de faire durer cette activité dans le temps, d’entrer dans des opérations de suivi d’avancement très chronophages.

http://www.jperf.com

Publié dans performance | Laisser un commentaire

Performance – TOP 5 – Granularité des services

Parmi les problèmes de performance auxquels j’ai été confronté, il y a ceux qui relèvent de la granularité des services dans une architecture SOA.

Cette catégorie regroupe beaucoup de mauvaises pratiques dont ont les impacts ne sont pas toujours faciles à évaluer mais qui ont nécessairement une influence sur la capacité à monter en charge d’une application.
On peut citer par exemple les problèmes relatifs à des invocations excessives de la couche de service généralement liés à une granularité trop faible des services. L’application cliente doit dans ce cas gérer une multitude d’invocations de service pour réaliser l’action requise.
Parfois c’est tout simplement une mauvaise connaissance de l’application cliente ou une mauvaise gestion du contexte d’exécution qui conduit les développeurs à multiplier les invocations aux mêmes services. Ce dernier cas de figure peut être rencontré sur des applications ou l’équipe de développement est plus ou moins livrée à elle même, sans réel leader qui assurerait une cohérence d’ensemble du développement. Ces problèmes peuvent également être liés à une mauvaise connaissance ou une documentation inadaptée du fonctionnement des services.

Parmi les solutions permettant d’éradiquer les problèmes de performance liés à la granularité des services nous pouvons évoquer les pistes suivantes:

  • S’assurer du bon niveau de granularité des services. Une granularité trop faible conduit à un nombre excessif d’appel de service tandis qu’une granularité trop forte conduit à la multiplication des services ayant des comportements similaires;
  • Profiler l’application pour s’assurer que l’application n’exécute pas un nombre excessif d’appel de service.
  • Rationaliser les appels de service pour ne pas invoquer plusieurs fois les mêmes services.

http://www.jperf.com

Publié dans performance | Laisser un commentaire

Améliorer les performances d’une application web (1er volet)

Savez vous que 47% des internautes s’attendent à ce qu’une page web s’affiche en moins de deux secondes et que 40% des gens vont fermer une page si elle met plus de trois secondes à se charger?  Sur un site de eCommerce le temps d’affichage d’une page a un impact direct sur le taux d’abandon d’un panier.

Dans ce contexte, on comprend pourquoi la performance d’un site web puisse requérir une attention toute particulière. Nous pouvons également avoir la même réflexion pour un site web interne ou un extranet ouvert aux partenaires.

Dans le processus d’amélioration des performances d’une application web on s’intéresse à la fois à ce qui se passe sur le serveur mais également dans la couche cliente (le navigateur). Dans ce premier volet, nous allons nous intéresser plus particulièrement à cette couche cliente : le navigateur.

Il y a de nombreuses technologies qui peuvent être utilisées dans cette couche qui peuvent donner lieu à une attention particulière (applet, flex…), mais nous limiterons notre sujet aux simples requêtes HTTP.

Comment réduire le temps de chargement d’une page web?

1er conseil : Réduire le nombre de requêtes

Cette technique vise à réduire le nombre de requêtes exécutées pour afficher une page. Il s’agit de l’approche la plus importante pour améliorer les performances d’affichage des pages pour les visiteurs qui accèdent au site pour la première fois.

Elle part du constat qu’une grande partie du temps consacré à l’affichage d’une page, ressenti par l’utilisateur d’un site, est passée sur le navigateur et que la majeure partie de ce temps est lié au téléchargement de tous les composants de la page: images, feuilles de style, scripts…

Cette approche met en jeu des techniques permettant de réduire le nombre de ressources à charger. Elle s’appuie notamment sur des solutions de fusion des scripts et des feuilles de style, et de combinaison des images dans un seule image (sprite).
Dans le cas du sprite, c’est à dire du regroupement des images dans une seule image, l’affichage d’une image en particulier est réalisée au travers de la définition de classes CSS qui déclarent notamment une propriété background-position qui précise la position du coin supérieur gauche de l’image que l’on veut afficher. Il faut également définir le fichier image via la propriété background-image ainsi que la taille de l’image à afficher avec les propriétés width et height.

2 ème conseil : Utiliser un CDN Content Delivery Network ou domain Sharding

Les navigateurs limitent volontairement le nombre de requêtes simultanées sur un domaine internet dans le but de ne pas surcharger les serveurs. Les anciens navigateurs autorisaient 2 connexions simultanées (IE7) tandis que les versions plus récentes permettent de réaliser entre 6 et 8 connexions simultanées. Ce dispositif n’empêche pas qu’un site internet chargeant un grand nombre de ressources statiques telles que des images, des scripts, des feuilles de style soit pénalisé par ces limites.

Il existe 2 techniques distinctes permettant d’améliorer le temps de chargement de ces ressources.

Le domain sharding est une technique qui consiste à charger les ressources statiques à partir de sous domaine. Cette technique permet donc de multiplier le nombre de requêtes simultanées par le nombre de sous domaine. L’approche consiste donc à distribuer les ressources entre différents domaines de façon à dépasser les limitations imposées par les navigateurs.
L’inconvénient est que chaque sous domaine nécessite de mettre en oeuvre une résolution de domaine qui peut ajouter un temps de latence supplémentaire. Sur les mobiles, la résolution DNS est également plus longue que pour les connexions dites conventionnelles.

La résolution DNS est le procédé de conversion d’un nom de domaine (par exemple google.com) en une adresse IP.

Il faut toutefois garder à l’esprit que cette technique peut être contre productive dans le cas ou le site web réalise peu de requêtes vers des ressources statiques. Notez également que le protocole HTTP/2.0 rend cette pratique est obsolète.

Le CDN (Content Delivery Network) est un réseau de serveurs distribués sur la planète qui délivre du contenu aux utilisateurs en fonction de la situation géographique des visiteurs. Cette approche consiste donc à distribuer les ressources sur un réseau de serveurs distribués dans le monde, et peut être intéressante pour des sites qui ont une audience internationale. Plusieurs sociétés se répartissent les parts de marché dans ce domaine citons par exemple Akamai, Amazon CloudFront….

3ème conseil : Utiliser le cache des navigateurs

L’utilisation d’un cache pour les ressources statiques a un impact majeur sur les performances et l’expérience utilisateur.  En effet bien que cette technique n’ait aucune incidence lors de la première visite d’un internaute sur la page de votre site, elle permet de réduire l’utilisation de la bande passante et le niveau de sollicitation des serveurs mais également améliore sensiblement le temps de chargement des pages lors des visites successives.
Bien entendu, l’utilisation du cache doit être réservée aux ressources statiques telles que les images, les feuilles de style, les scripts et ne doit surtout pas être utilisée pour gérer du contenu dynamique.
L’idée est de paramétrer l’entête HTTP « expires » de façon à ce que la ressource soit mise en cache sur le navigateur pendant la période déclarée. Lorsque la ressource est expirée (ou si l’utilisateur demande un rafraîchissement de la page « soft-refresh »), si les entêtes HTTP Etag ou Last-Modified sont présents sur la ressource, le navigateur lance une requête conditionnelle avec les entêtes If-None-Match ou If-Modified-Since.
Si le serveur répond avec un status HTTP 304 (Not modified) avec les entêtes relatives à la mise en cache de la ressource, le navigateur gardera la ressource dans le cache et modifiera la date d’expiration conformément aux informations renvoyées par le serveur.
La ressource est, bien entendu servie, par le cache du navigateur.

Pour les ressources statiques mises en cache qui peuvent être modifiées périodiquement, il existe des techniques de gestion de version qui permettent de prendre en compte la modification en forçant le navigateur à charger la nouvelle ressource.

4ème conseil : Compresser les contenus

Le temps de chargement d’une ressource dépend en particulier de la taille du contenu. Un navigateur prendra plus de temps pour charger une ressource de 100 Ko qu’une ressource de 10 Ko 😉 . Cette technique répond à cette exigence de réduction de la taille des ressources en utilisant une technique de compression.
Les ressources textuelles sont principalement visées par cette approche : les documents HTML, les feuilles de style, les scripts…

5ème conseil : Déplacer les scripts à la fin de la page

Cette technique consiste à déclarer les scripts juste avant la fermeture du tag BODY de la page. En effet, l’une des caractéristiques des scripts est qu’ils s’exécutent à l’emplacement exact où ils sont insérés dans le document et de fait, ils bloquent la construction du DOM (Document Object Modèle) et retarde l’affichage initial de la page. Autrement dit, un script déclaré au milieu du contenu d’une page bloque l’affichage du reste de la page tant que le script n’est pas exécuté. Cela peut provoquer des situations de page blanche, ou des effets visuels disgracieux ou l’utilisateur voit le chargement partiel de la page puis attend le rendu complet.

Plus techniquement, lorsque l’analyseur HTML rencontre une balise de script, il suspend le processus de construction du DOM, puis cède le contrôle au moteur JavaScript. Lorsque celui-ci a fini de s’exécuter, le navigateur reprend sa tâche au point où il l’a laissée, puis reprend la construction du DOM. Pourquoi la construction du DOM est-elle interrompue? Tout simplement car le script peut modifier le DOM et le CSSOM (représentation objet d’une feuille de style) qui sont tout deux nécessaires à la construction du rendu de la page.

Par ailleurs, si le navigateur n’a pas fini de construire le CSSOM au moment ou un script peut être exécuté, il retardera l’exécution du script jusqu’à ce que le CSSOM soit construit.

Il est donc nécessaire de charger les feuilles de style le plus tôt possible dans le processus de construction de la page. En fait, cette étape fait appel à une autre notion « le chemin critique du rendu » que nous aborderons dans un autre volet.

Le chemin critique du rendu fait appel à l’optimisation du schéma de dépendance entre HTML, CSS et JavaScript et, plus particulièrement, il s’agit d’améliorer les performances de sorte que le navigateur charge très rapidement tous les éléments graphiques qui sont visibles immédiatement afin que l’utilisateur ait une sensation d’instantanéité. Les éléments non visibles sont chargés d’une façon imperceptible pour l’utilisateur.

Notons simplement à ce stade qu’il existe des attributs de la balise script qui permettent de rendre un script non bloquant.

  • defer : différer l’exécution à la fin du chargement du document.
  • async : charger/exécuter les scripts de façon asynchrone (par un autre thread).

Nous reviendrons plus précisément, dans un prochain volet, sur les mécanismes mis en oeuvre lors du chargement des scripts.

6ème conseil : Externaliser les ressources

Les ressources de type feuille de style et script devraient être externalisées dans des fichiers de façon à bénéficier de l’utilisation du cache du navigateur.

7ème conseil : Réduire l’impact de la résolution DNS

Pour réduire l’impact de la résolution DNS, il est nécessaire d’utiliser la directive HTTP keep-alive et rationaliser l’utilisation des domaines différents.

La directive Keep-alive est un dispositif permettant d’utiliser une simple connexion TCP pour envoyer et recevoir de multiples requêtes et réponses.
Elle s’oppose à un fonctionnement ou chaque requête nécessite l’ouverture et la fermeture d’une connexion TCP. Avec le protocole HTTP/1.1 toutes les connexions sont considérées persistantes par défaut.

8ème conseil : Minifier les scripts

Cette opération consiste à réduire la taille des scripts en supprimant tous les caractères non indispensables (commentaires, espaces inutiles…). Elle peut venir en complément de la technique de compression pour réduire la taille de la ressource.

En synthèse

L’application de ces premières mesures devraient vous permettre d’améliorer le ressenti de l’utilisateur. Dans un prochain volet, nous nous intéresserons à la notion de chemin critique du rendu et nous entrerons plus en détails sur l’impact des scripts sur la performance de l’affichage des pages.

http://www.jperf.com

Publié dans performance | Laisser un commentaire

Qu’est ce que le PACING?

Dans le domaine des tests de performance, il s’agit du temps minimum entre chaque itération d’un scénario de test.

Qu’est ce qu’une itération?

Imaginez que vous recherchiez un objet sur un site d’annonces en ligne. Votre scénario de test pourrait consister en un accès à la page d’accueil du site, le choix de critères de sélection, le parcourt de la liste des objets correspondants à vos critères, et la consultation des annonces les plus intéressantes. Malheureusement vous n’avez rien trouvé et vous quittez le site en fermant simplement votre navigateur. L’exécution de ce scénario une seule fois représente une itération.

Le pacing correspond donc au temps séparant deux exécutions d’un scénario par un même utilisateur virtuel. Il peut être égal ou supérieur au temps d’exécution du scénario. Dans le cas ou il est supérieur, un délai est ajouté à la fin de l’exécution de l’itération avant de commencer l’itération suivante. Si le pacing est inférieur ou égal au temps d’exécution du scénario, l’itération suivante débute immédiatement après la fin de la précédente.

A quoi cela sert il?

Ce mécanisme permet de réaliser des tests de performance avec un taux constant de transactions/requêtes. De fait, lorsque le pacing est calculé correctement, à chaque itération tous les utilisateurs virtuels commencent un nouveau scénario en même temps. Personnellement j’utilise assez peu cette méthode de simulation de charge qui peut produire des graphes d’utilisation des ressources en dents de scie puisque à la fin des itérations tous les utilisateurs virtuels attendent quelques secondes avant de démarrer une nouvelle itération.

http://www.jperf.com

 

Publié dans performance, Uncategorized | Tagué , | Laisser un commentaire

Hibernate: Comment tracer les requêtes SQL et les paramètres des requêtes

Cet article est davantage un pense bête personnel.

Ces deux articles expliquent parfaitement les bonnes pratiques en matière de debugage des requêtes SQL et la manière de les mettre en oeuvre.

Mieux vaut éviter d’utiliser la propriété show_sql et préférer une configuration des logs (org.hibernate.SQL, org.hibernate.type.descriptor.sql …).

http://www.thoughts-on-java.org/hibernate-logging-guide/

http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

Cependant vous pouvez rencontrer des problèmes de mise en oeuvre si vous utilisez une librairie de log telle que SLF4J. Pourquoi ? Parce que Hibernate (depuis la version 4) utilise un « bridge » pour ne pas être dépendant d’une librairie de log particulière. Ce bridge teste les API disponibles dans le classpath selon un ordre précis. Donc assurez vous bien que les librairies tierces que vous avez intégrées dans votre projet n’ont pas de dépendance avec une API de log.

Dans un projet maven, il suffit d’exécuter la tâche dependency-tree qui liste l’ensemble des dépendance de votre projet. Si vous trouvez une dépendance avec une autre librairie de log, il faudra exclure cette dépendance en intègrant une section exclusion dans le noeud dependency.

Par exemple pour exclure une dépendance avec la librairie log4j.

<dependency>
...
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>

 

Publié dans tech notes | Tagué | Laisser un commentaire