Come configurare la registrazione in Hibernate 4 per usare SLF4J

Hibernate 3.x ha usato slf4j per la registrazione. Hibernate 4.x utilizza jboss-logging . Sto scrivendo un’applicazione standalone che usa Hibernate 4 e SLF4J per la registrazione.

Come posso configurare Hibernate per accedere a SLF4J?

Se ciò non è ansible, come posso configurare la registrazione di Hibernate?

La sezione manuale di Hibernate 4.1 sulla registrazione inizia con l’avviso che è …

Completamente obsoleto. Hibernate utilizza JBoss Logging a partire dalla 4.0. Questo verrà documentato durante la migrazione di questo contenuto alla Guida per gli sviluppatori.

… continua a parlare di SLF4J, e quindi è inutile. Né la guida introduttiva né la guida per lo sviluppatore parlano del logging. Né la guida della migrazione .

Ho cercato la documentazione su jboss-logging stesso, ma non sono stato in grado di trovarne affatto. La pagina GitHub è silenziosa e la pagina dei progetti della comunità di JBoss non elenca nemmeno jboss-logging. Mi chiedevo se il bug tracker del progetto potesse avere problemi relativi alla documentazione, ma non lo è.

La buona notizia è che quando si utilizza Hibernate 4 all’interno di un server delle applicazioni, come JBoss AS7, la registrazione è ampiamente gestita per te. Ma come posso configurarlo in un’applicazione standalone?

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

static final String LOGGING_PROVIDER_KEY = "org.jboss.logging.provider"; private static LoggerProvider findProvider() { // Since the impl classs refer to the back-end frameworks directly, if this classloader can't find the target // log classs, 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 String loggerProvider = AccessController.doPrivileged(new PrivilegedAction() { public String 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(); } 

Quindi i possibili valori per org.jboss.logging.provider sono: jboss , jdk , log4j , slf4j .

Se non si imposta org.jboss.logging.provider , prova jboss, quindi log4j, quindi slf4j (solo se il logback è utilizzato) e fallback su jdk.

Io uso slf4j con logback-classic :

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

e tutto funziona bene!

AGGIORNARE Alcuni utenti usano in App.java molto principale:

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

ma per le soluzioni basate su container questo non funziona.

AGGIORNAMENTO 2 Coloro che pensano di gestire Log4j con SLF4J per jboss-logging non è esattamente così. jboss-logging utilizza direttamente Log4j senza SLF4J!

Per fare in modo che SLF4J funzioni con JBoss Logging senza Logback come backend richiede l’uso di una proprietà di sistema org.jboss.logging.provider=slf4j . log4j-over-slf4j tattiche di log4j-over-slf4j non sembrano funzionare in questo caso perché la registrazione ricadrà su JDK se né Logback né log4j non sono effettivamente presenti in classpath.

Questo è un po ‘fastidioso e per far funzionare il rilevamento automatico hai visto che il classloader contiene almeno ch.qos.logback.classic.Logger da logback-classic o org.apache.log4j.Hierarchy da log4j per ingannare il JBoss Logging da non tornare alla registrazione JDK.

La magia è interpretata in org.jboss.logging.LoggerProviders

AGGIORNAMENTO: è stato aggiunto il supporto del caricatore di servizio, pertanto è ansible evitare problemi con il rilevamento automatico dichiarando META-INF/services/org.jboss.logging.LoggerProvider (con org.jboss.logging.Slf4jLoggerProvider come valore). Sembra esserci anche il supporto log4j2.

Ispirato al post di Leif su Hypoport , ecco come ho “piegato” Hibernate 4 a slf4j:

Supponiamo che tu stia usando Maven.

  • Aggiungi org.slf4j:log4j-over-slf4j come dipendenza dal tuo pom.xml
  • Usando il comando mvn dependency:tree , assicurati che nessuna delle slf4j:slf4j che stai usando slf4j:slf4j su slf4j:slf4j (per essere precisi, nessun artefatto deve avere una dipendenza dall’ambito di compilazione o una dipendenza dall’ambito di runtime su slf4j:slf4j )

Sfondo: Hibernate 4.x ha una dipendenza org.jboss.logging:jboss-logging . In modo transnazionale, questo artefatto ha una dipendenza dallo scope fornita dalla slf4j:slf4j .

Come ora abbiamo aggiunto org.slf4j:log4j-over-slf4j artefatto, org.slf4j:log4j-over-slf4j slf4j:slf4j artefatto slf4j:slf4j . Quindi tutto quello che JBoss Logging ora passerà effettivamente tramite slf4j.

Supponiamo che tu stia utilizzando Logback come back-end di registrazione. Ecco un esempio pom.xml

 < ?xml version="1.0" encoding="UTF-8"?>  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-compile-or-runtime-scope-dependency-on-log4j:log4j ${bla}   log4j log4j       org.hibernate hibernate-entitymanager ${hibernate-entitymanager-version}   ....  

Sul tuo classpath, hai un logback.xml , come questo che si trova in src/main/java :

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

Alcuni componenti potrebbero voler accedere a logback.xml all’ora di avvio JVM per la corretta registrazione, ad esempio il plug-in Jetty Maven. In tal caso, aggiungi al tuo comando un sistema Java logback.configurationFile=./path/to/logback.xml (es. mvn -Dlogback.configurationFile=./target/classs/logback.xml jetty:run ).

Nel caso in cui si stia ottenendo ancora l’output di ibernazione “stdout” della console (come Hibernate: select ... ), potrebbe essere applicata la domanda Overflow dello stack ” Distriggers la registrazione dell’ibernazione sulla console “.

Per prima cosa ti rendi conto che SLF4J non è una libreria di registrazione, è un wrapper di registrazione. Di per sé non registra nulla, semplicemente delega a “backend”.

Per “configurare” jboss-logging basta aggiungere qualsiasi framework di log che si desidera utilizzare sul classpath (insieme a jboss-logging) e jboss-logging calcola il resto.

Ho creato una guida focalizzata su Hibernate per la configurazione di JBoss Logging: http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

Uso Hibernate Core 4.1.7.Final plus Spring 3.1.2.RELEASE in un’app standalone. Ho aggiunto Log4j 1.2.17 alle mie dipendenze e sembra che, come JBoss Logging accede direttamente a log4j se disponibile e Spring usi Commons Logging, witch utilizza anche Log4j se disponibile, tutto il logging può essere configurato tramite Log4J.

Ecco la mia lista di dipendenze rilevanti:

  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 ha una documentazione su come controllare org.jboss.logging :

  • Cerca il percorso di class per un provider di registrazione . Cerca slf4j dopo aver cercato log4j. Quindi, in teoria, assicurando che il classpath (WAR) non includa log4j e includa l’API slf4j e un back-end dovrebbe funzionare.

  • Come ultima risorsa è ansible impostare la proprietà di sistema slf4j su slf4j .


Nonostante le affermazioni della documentazione, org.jboss.logging insistito sul tentativo di utilizzare log4j, nonostante l’assenza di log4j e la presenza di SLF4J, determinando il seguente messaggio nel mio file di log di 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. 

Ho dovuto seguire il suggerimento della risposta di dasAnderl ausMinga e includere il ponte log4j-over-slf4j .

Io uso Maven e ho aggiunto la seguente dipendenza:

  org.slf4j slf4j-log4j12 1.6.6  

Quindi, ho creato un file log4j.properties in /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 

Questo lo metterà alla radice del tuo .jar . Esso funziona magicamente…

quindi, ho appena lavorato nel mio progetto. hibernate 4, slf4j, logback. il mio progetto è gradle, ma dovrebbe essere lo stesso per Maven.

Fondamentalmente Abdull ha ragione. Dove NON ha ragione, è che NON DEVI rimuovere slf4j dalle dipendenze.

  1. includi per compilare scope:

    org.slf4j: slf4j-api

    org.slf4j: log4j-over-slf4j

    ad esempio per il logback (ch.qos.logback: logback-classic, ch.qos.logback: logback-core: 1.0.12)

  2. escludere completamente le librerie log4j dalle dipendenze

risultato: registri di ibernazione tramite slf4j per il logback. ovviamente dovresti essere in grado di utilizzare un’implementazione di log diversa da quella di logback

per essere sicuri che non sia presente log4j, controlla le tue lib su classpath o web-inf / lib per i file war.

ovviamente hai impostato i logger in logback.xml ad esempio:

Ho avuto un problema nel far funzionare la registrazione in ibernazione 4 con weblogic 12c e log4j. La soluzione è quella di mettere quanto segue nel tuo weblogic-application.xml:

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

A chiunque possa affrontare lo stesso problema che ho avuto. Nel caso in cui tu abbia provato tutte le altre soluzioni spiegate qui e ancora non vedi la registrazione in ibernazione che funziona con il tuo slf4j, potrebbe essere perché stai usando un contenitore che ha nella sua cartella le librerie jboss-logging.jar. Ciò significa che viene precaricato prima di poter impostare qualsiasi configurazione per influenzarlo. Per evitare questo problema in weblogic puoi specificare nel file weblogic-application.xml in te ear / META-INF di preferire la libreria caricata dall’applicazione. dovrebbe esserci un meccanismo simile per altri contenitori di server. Nel mio caso ho dovuto aggiungere:

 < ?xml version="1.0" encoding="UTF-8"?>    org.slf4j.* org.jboss.logging.*   org/slf4j/impl/StaticLoggerBinder.class   

hai provato questo:

– slf4j-log4j12.jar nel caso di Log4J. Vedi la documentazione di SLF4J per maggiori dettagli. Per utilizzare Log4j è necessario inoltre inserire un file log4j.properties nel classpath. Un file di proprietà di esempio viene distribuito con Hibernate nella directory src /

basta aggiungere questi jar e proprietà o log4j xml nel classpath