Comment configurer la journalisation dans Hibernate 4 pour utiliser SLF4J

Hibernate 3.x a utilisé slf4j pour la journalisation. Hibernate 4.x utilise jboss-logging . J’écris une application autonome qui utilise Hibernate 4 et SLF4J pour la journalisation.

Comment puis-je configurer Hibernate pour se connecter à SLF4J?

Si ce n’est pas possible, comment puis-je configurer la journalisation d’Hibernate?

La section du manuel Hibernate 4.1 sur la journalisation commence par l’avertissement que c’est …

Complètement obsolète. Hibernate utilise JBoss Logging à partir de la version 4.0. Cela sera documenté lors de la migration de ce contenu vers le Guide du développeur.

… continue à parler de SLF4J, et est donc inutile. Ni le guide de démarrage ni le guide du développeur ne parlent de la journalisation. Le guide de migration non plus.

J’ai cherché de la documentation sur jboss-logging lui-même, mais je n’ai pas pu en trouver du tout. La page GitHub est silencieuse et la page des projets de communauté de JBoss ne répertorie même pas jboss-logging. Je me suis demandé si l’ outil de suivi des bogues du projet pouvait avoir des problèmes liés à la fourniture de documentation, mais ce n’est pas le cas.

La bonne nouvelle est que lorsque vous utilisez Hibernate 4 dans un serveur d’applications, tel que JBoss AS7, la journalisation est largement prise en charge pour vous. Mais comment puis-je le configurer dans une application autonome?

Regardez à https://github.com/jboss-logging/jboss-logging/blob/master/src/main/java/org/jboss/logging/LoggerProviders.java :

static final Ssortingng LOGGING_PROVIDER_KEY = "org.jboss.logging.provider"; private static LoggerProvider findProvider() { // Since the impl classes refer to the back-end frameworks directly, if this classloader can't find the target // log classes, then it doesn't really matter if they're possibly available from the TCCL because we won't be // able to find it anyway final ClassLoader cl = LoggerProviders.class.getClassLoader(); try { // Check the system property final Ssortingng loggerProvider = AccessController.doPrivileged(new PrivilegedAction() { public Ssortingng run() { return System.getProperty(LOGGING_PROVIDER_KEY); } }); if (loggerProvider != null) { if ("jboss".equalsIgnoreCase(loggerProvider)) { return tryJBossLogManager(cl); } else if ("jdk".equalsIgnoreCase(loggerProvider)) { return tryJDK(); } else if ("log4j".equalsIgnoreCase(loggerProvider)) { return tryLog4j(cl); } else if ("slf4j".equalsIgnoreCase(loggerProvider)) { return trySlf4j(); } } } catch (Throwable t) { } try { return tryJBossLogManager(cl); } catch (Throwable t) { // nope... } try { return tryLog4j(cl); } catch (Throwable t) { // nope... } try { // only use slf4j if Logback is in use Class.forName("ch.qos.logback.classic.Logger", false, cl); return trySlf4j(); } catch (Throwable t) { // nope... } return tryJDK(); } 

Les valeurs possibles pour org.jboss.logging.provider sont: jboss , jdk , log4j , slf4j .

Si vous ne définissez pas org.jboss.logging.provider il essaie jboss, puis log4j, puis slf4j (uniquement si logback utilisé) et repli sur jdk.

J’utilise slf4j avec logback-classic :

   ch.qos.logback logback-classic 1.0.13 ${logging.scope}  

et tout fonctionne bien!

UPDATE Certains utilisateurs utilisent très App.java principale:

 static { //runs when the main class is loaded. System.setProperty("org.jboss.logging.provider", "slf4j"); } 

mais pour les solutions basées sur des conteneurs, cela ne fonctionne pas.

MISE À JOUR 2 Ceux qui pensent qu’ils gèrent Log4j avec SLF4J pour jboss-logging ne le sont pas exactement. jboss-logging utilise directement Log4j sans SLF4J!

Pour que SLF4J fonctionne avec JBoss Logging sans vérification en tant que backend, vous devez utiliser une propriété système org.jboss.logging.provider=slf4j . log4j-over-slf4j tactiques log4j-over-slf4j ne semblent pas fonctionner dans ce cas, car la journalisation reviendra au JDK si ni Logback ni log4j ne sont réellement présents dans classpath.

C’est un peu gênant et pour que l’autodétection fonctionne, vous voyez que le classloader contient au moins ch.qos.logback.classic.Logger de logback-classic ou org.apache.log4j.Hierarchy de log4j pour tromper les JBoss Logging ne retombe pas dans la journalisation JDK.

La magie est interprétée à org.jboss.logging.LoggerProviders

UPDATE: le support du chargeur de service a été ajouté, il est donc possible d’éviter les problèmes de détection automatique en déclarant META-INF/services/org.jboss.logging.LoggerProvider (avec org.jboss.logging.Slf4jLoggerProvider comme valeur). Il semble y avoir également ajouté le support log4j2.

Inspiré du post Hypoport de Leif, voici comment je “plie” Hibernate 4 à slf4j:

Supposons que vous utilisez Maven.

  • Ajoutez org.slf4j:log4j-over-slf4j comme dépendance à votre pom.xml
  • En utilisant la commande mvn dependency:tree , assurez-vous qu’aucun des artefacts que vous utilisez ne dépend de slf4j:slf4j (pour être précis, aucun artefact ne doit avoir une dépendance de scope de compilation ou une dépendance de scope d’ exécution sur slf4j:slf4j )

Arrière-plan: Hibernate 4.x a une dépendance sur l’artefact org.jboss.logging:jboss-logging . De manière transitoire, cet artefact a une dépendance de scope fournie sur l’artefact slf4j:slf4j .

Comme nous avons maintenant ajouté l’ org.slf4j:log4j-over-slf4j , org.slf4j:log4j-over-slf4j imite l’artefact slf4j:slf4j . Par conséquent, tout ce que les journaux de JBoss Logging vont maintenant passer via slf4j.

Disons que vous utilisez Logback comme moteur de journalisation. Voici un exemple pom.xml

   4.0.0 ....  .... 1.7.2 1.7.2 1.7.2  1.0.7 1.0.7 4.1.7.Final      org.slf4j slf4j-api ${slf4j-api-version}   org.slf4j jcl-over-slf4j ${jcl-over-slf4j-version}   org.slf4j log4j-over-slf4j ${log4j-over-slf4j-version}   ch.qos.logback logback-core ${logback-core-version}   ch.qos.logback logback-classic ${logback-classic-version}     org.foo some-artifact-with-comstack-or-runtime-scope-dependency-on-log4j:log4j ${bla}   log4j log4j       org.hibernate hibernate-entitymanager ${hibernate-entitymanager-version}   ....  

Sur votre logback.xml , logback.xml un logback.xml , comme celui-ci situé dans src/main/java :

     %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n         

Certains composants peuvent vouloir accéder à logback.xml au démarrage de JVM pour une journalisation correcte, par exemple le plugin Jetty Maven. Dans ce cas, ajoutez un système Java logback.configurationFile=./path/to/logback.xml à votre commande (par exemple, mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run ).

Dans le cas où vous obtenez toujours une sortie Hibernate de sortie de console “brute” (comme Hibernate: select ... ), alors la question Stack Overflow ” Désactiver la journalisation d’hibernation sur la console ” peut s’appliquer.

Tout d’abord, vous réalisez que SLF4J n’est pas une bibliothèque de journalisation à droite, c’est un wrapper de journalisation. Il ne se connecte rien, il délègue simplement à “backends”.

Pour “configurer” jboss-logging, il vous suffit d’append le framework de journalisation que vous souhaitez utiliser sur votre chemin de classe (avec jboss-logging) et jboss-logging fait le rest.

J’ai créé un guide axé sur Hibernate pour la configuration de JBoss Logging: http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

J’utilise Hibernate Core 4.1.7.Final plus Spring 3.1.2.RELEASE dans une application autonome. J’ai ajouté Log4j 1.2.17 à mes dépendances et il semble que JBoss Logging se connectant directement à log4j si disponible et que Spring utilise Commons Commons, qui utilise également Log4j si disponible, tout Logging pourrait être configuré via Log4J.

Voici ma liste de dépendances pertinentes:

  log4j log4j 1.2.17   org.hibernate hibernate-core 4.1.7.Final   org.springframework spring-context 3.1.2.RELEASE   org.springframework spring-orm 3.1.2.RELEASE  

Hibernate 4.3 a de la documentation sur la façon de contrôler org.jboss.logging :

  • Il recherche le chemin de classe pour un fournisseur de journalisation . Il recherche slf4j après avoir recherché log4j. Donc, en théorie, assurez-vous que votre classpath (WAR) n’inclut pas log4j et n’inclut pas l’API slf4j et qu’un back-end devrait fonctionner.

  • En dernier recours, vous pouvez définir la propriété système org.jboss.logging.provider sur slf4j .


Malgré les affirmations de la documentation, org.jboss.logging insisté pour essayer d’utiliser log4j, malgré l’absence de log4j et la présence de SLF4J, entraînant le message suivant dans mon fichier journal Tomcat ( /var/log/tomcat/catalina.out ) :

  log4j:WARN No appenders could be found for logger (org.jboss.logging). log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. 

J’ai dû suivre la suggestion de la réponse de dasAnderl ausMinga et inclure le pont log4j-over-slf4j .

J’utilise maven et a ajouté la dépendance suivante:

  org.slf4j slf4j-log4j12 1.6.6  

Ensuite, j’ai créé un fichier log4j.properties dans /src/main/resources :

 # direct log messages to stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n # set log levels log4j.rootLogger=warn 

Cela le mettra à la racine de votre .jar . Il fonctionne comme un charme…

alors, je viens juste de le faire fonctionner dans mon projet. hibernate 4, slf4j, logback. mon projet est graduel, mais devrait être le même pour maven.

Essentiellement, Abdull a raison. Là où il n’est pas correct, c’est que vous ne devez PAS supprimer slf4j des dépendances.

  1. inclure à comstackr la scope:

    org.slf4j: slf4j-api

    org.slf4j: log4j-over-slf4j

    par exemple pour la récupération (ch.qos.logback: logback-classic, ch.qos.logback: logback-core: 1.0.12)

  2. exclure complètement les bibliothèques log4j des dépendances

résultat: hibernate logs via slf4j à logback. bien sûr, vous devriez pouvoir utiliser une implémentation de journal différente de celle du logback

pour être sûr qu’aucun log4j n’est présent, vérifiez vos libs sur classpath ou web-inf / lib pour les fichiers war.

bien sûr, vous avez défini les enregistreurs dans logback.xml, par exemple:

J’ai eu un problème avec le travail de journalisation hibernate 4 avec weblogic 12c et log4j. La solution consiste à mettre les éléments suivants dans votre weblogic-application.xml:

  org.apache.log4j.* org.jboss.logging.*  

À tous ceux qui pourraient faire face au même problème que moi. Si vous avez essayé toutes les autres solutions expliquées ici et que vous ne voyez toujours pas la journalisation hibernate avec votre slf4j, cela peut être dû au fait que vous utilisez un conteneur qui contient dans son dossier les bibliothèques jboss-logging.jar. Cela signifie qu’il est préchargé avant même de pouvoir définir une configuration pour l’influencer. Pour éviter ce problème dans weblogic, vous pouvez spécifier dans le fichier weblogic-application.xml dans votre fichier ear / META-INF pour préférer la bibliothèque chargée depuis l’application. Il devrait y avoir un mécanisme similaire pour les autres conteneurs de serveur. Dans mon cas, j’ai dû append:

     org.slf4j.* org.jboss.logging.*   org/slf4j/impl/StaticLoggerBinder.class   

as-tu essayé ceci:

– slf4j-log4j12.jar dans le cas de Log4J. Voir la documentation de SLF4J pour plus de détails. Pour utiliser Log4j, vous devrez également placer un fichier log4j.properties dans votre chemin de classe. Un exemple de fichier de propriétés est dissortingbué avec Hibernate dans le répertoire src /

il suffit d’append ces jars et propriétés ou log4j xml dans le classpath