Comment configurer la journalisation dans Hibernate 4 pour utiliser SLF4J
hibernation 3.x utilisé slf4j pour l'exploitation forestière. Hibernation 4.x utilise jboss-enregistrement . J'écris une application autonome qui utilise Hibernate 4, et SLF4J pour la journalisation.
comment configurer Hibernate pour se connecter à SLF4J?
si ce n'est pas possible, Comment puis-je configurer la journalisation D'Hibernate?
Hibernate 4.1 manuel "1519110920 la section" enregistrement commence avec l'avertissement qu'il est ...
complètement périmé. Hibernate utilise la journalisation JBoss à partir de 4.0. Cela sera documenté au fur et à mesure que nous migrerons 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 parler de l'exploitation forestière à tous. La migration non plus guide .
j'ai cherché de la documentation sur jboss-logging lui-même, mais je n'en ai pas trouvé du tout. La page de GitHub est muette , et la page de JBoss community projects ne mentionne même pas jboss-logging. Je me suis demandé si le bug tracker du projet th pourrait avoir des problèmes concernant la fourniture de documentation, mais ce n'est pas le cas.
la bonne nouvelle est que lors de l'utilisation Hibernate 4 à l'intérieur d'un serveur d'application, tel que JBoss AS7, la journalisation est en grande partie prise en charge pour vous. Mais comment puis-je configurer dans une application autonome?
11 réponses
static final String 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 String loggerProvider = AccessController.doPrivileged(new PrivilegedAction<String>() {
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();
}
ainsi 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 (seulement si logback utilisé) et fallback vers jdk.
j'utilise slf4j
avec logback-classic
:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
<scope>${logging.scope}</scope>
</dependency>
et tout fonctionne bien!
UPDATE certains utilisateurs utilisent dans L'application très principale.java:
static { //runs when the main class is loaded.
System.setProperty("org.jboss.logging.provider", "slf4j");
}
mais pour les solutions à base de conteneur cela ne fonctionne pas.
UPDATE 2 ceux qui pensent gérer Log4j avec SLF4J pour jboss-logging
ce n'est pas exactement ainsi. jboss-logging
utilise directement Log4j sans SLF4J!
pour que SLF4J fonctionne avec la journalisation de JBoss sans Logback car le backend nécessite l'utilisation d'une propriété de système org.jboss.logging.provider=slf4j
. La tactique log4j-over-slf4j
ne semble pas fonctionner dans ce cas car la journalisation retombera sur JDK si ni Logback ni log4j n'est pas réellement présent dans classpath.
c'est un peu gênant et pour faire fonctionner autodetection vous avez vu que classloader contient au moins ch.qos.logback.classic.Logger
de logback-classic ou org.apache.log4j.Hierarchy
de log4j pour le truc de l'JBoss Journalisation de ne pas retomber à la journalisation JDK.
la magie est interprétée à org.jboss.logging.LoggerProviders
mise à jour: la prise en charge du chargeur de Service a été ajoutée afin qu'il soit possible d'éviter les problèmes d'autodétection en déclarant META-INF/services/org.jboss.logging.LoggerProvider
(avec org.jboss.logging.Slf4jLoggerProvider
comme valeur). Il semble qu'il y ait aussi un support log4j2 ajouté.
Inspiré par Leif Hypoport post , c'est la façon dont je "plié" Hibernate 4 retour à la slf4j:
supposons que vous utilisez Maven.
- ajouter
org.slf4j:log4j-over-slf4j
comme une dépendance à votrepom.xml
- utilisez la commande
mvn dependency:tree
, assurez-vous que aucun des artefacts que vous utilisez depende surslf4j:slf4j
(pour être précis, aucun artefact ne doit avoir compiler portée de dépendance ou de runtime la portée de la dépendanceslf4j:slf4j
)
Background: Hibernate 4.x dépend de l'artefact org.jboss.logging:jboss-logging
. De façon transitoire, cet artéfact a une fournie dépendance de portée sur l'artéfact slf4j:slf4j
.
comme nous avons maintenant ajouté le org.slf4j:log4j-over-slf4j
artefact, org.slf4j:log4j-over-slf4j
imite le slf4j:slf4j
artefact. Par conséquent tout ce que JBoss Logging
logs va maintenant passer par slf4j.
disons que vous utilisez Logback comme support de votre journalisation. Voici un échantillon pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
....
<properties>
....
<slf4j-api-version>1.7.2</slf4j-api-version>
<log4j-over-slf4j-version>1.7.2</log4j-over-slf4j-version>
<jcl-over-slf4j-version>1.7.2</jcl-over-slf4j-version> <!-- no problem to have yet another slf4j bridge -->
<logback-core-version>1.0.7</logback-core-version>
<logback-classic-version>1.0.7</logback-classic-version>
<hibernate-entitymanager-version>4.1.7.Final</hibernate-entitymanager-version> <!-- our logging problem child -->
</properties>
<dependencies>
<!-- begin: logging-related artifacts .... -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${jcl-over-slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${log4j-over-slf4j-version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback-core-version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback-classic-version}</version>
</dependency>
<!-- end: logging-related artifacts .... -->
<!-- begin: some artifact with direct dependency on log4j:log4j .... -->
<dependency>
<groupId>org.foo</groupId>
<artifactId>some-artifact-with-compile-or-runtime-scope-dependency-on-log4j:log4j</artifactId>
<version>${bla}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- begin: some artifact with direct dependency on log4j:log4j .... -->
<!-- begin: a hibernate 4.x problem child........... -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate-entitymanager-version}</version>
</dependencies>
<!-- end: a hibernate 4.x problem child........... -->
....
</project>
sur votre chemin de classe, avoir un logback.xml
, comme celui-ci situé dans src/main/java
:
<!-- begin: logback.xml -->
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.hibernate" level="debug"/>
<root level="info">
<appender-ref ref="console"/>
</root>
</configuration>
<!-- end: logback.xml -->
certains composants peuvent vouloir avoir accès à logback.xml
à L'Heure de 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 encore la sortie" raw "stdout Hibernate de la console (comme Hibernate: select ...
), puis la question de débordement de la pile " désactiver la journalisation de l'hibernation vers la console " peut s'appliquer.
tout d'abord, vous réalisez que SLF4J n'est pas un droit de bibliothèque de journalisation, c'est un enveloppeur de journalisation. Il lui-même ne Note rien, il délègue simplement pour "soutenir".
pour" configurer " JBoss-logging il vous suffit d'ajouter n'importe quel cadre de journalisation que vous voulez utiliser sur votre classepath (avec JBoss-logging) et JBoss-logging comprend le reste.
j'ai créé un guide axé sur L'hibernation pour la configuration de journalisation de JBoss: http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html
J'utilise le noyau D'hibernation 4.1.7.Finale + printemps 3.1.2.La mise en application autonome. J'ai ajouté Log4j 1.2.17 à mes dépendances et il semble que, comme JBoss Logging logs directement sur log4j si disponible et Spring utilise la journalisation Commons, witch utilise aussi Log4j si disponible, toute la journalisation peut être configurée via Log4J.
voici ma liste de dépendances pertinentes:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.1.7.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
Hibernate 4.3 a documentation sur le contrôle de la org.jboss.logging
:
-
il recherche le chemin de classe pour un logging provider . Il recherche slf4j après avoir cherché log4j. Donc, en théorie, s'assurer que votre chemin de classe (WAR) n'inclut pas log4j et inclut l'API slf4j et un back-end devrait fonctionner.
-
comme dernier resort vous pouvez définir la propriété du système
org.jboss.logging.provider
àslf4j
.
malgré les affirmations de la documentation, org.jboss.logging
a insisté pour essayer d'utiliser log4j, malgré l'absence de log4j et la présence de SLF4J, ce qui a donné le message suivant dans mon fichier Tomcat log ( /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 par dasAnderl ausMinga et comprend le pont log4j-over-slf4j
.
j'utilise maven et j'ai ajouté la dépendance suivante:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>
puis, j'ai créé un log4j.properties
fichiers 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 placera à la racine de votre .jar
. Il fonctionne comme un charme...
donc, je l'ai eu dans mon projet. hibernate 4, slf4j, logback. mon projet est gradle, mais devrait être le même pour maven.
Abdull a raison. Là où il N'a pas raison, c'est que vous N'avez pas à supprimer slf4j des dépendances.
-
inclure les compiler portée:
org.slf4j: slf4j-api
org.slf4j:log4j-sur-slf4j
p.ex. pour le retour (ch.la qualité de service.logback:logback-classique, ch.la qualité de service.logback: logback-core: 1.0.12)
-
exclure complètement les libs log4j des dépendances
résultat: mise en veille prolongée journaux via slf4j à logback. bien sûr, vous devriez être en mesure d'utiliser l'implémentation de log différent de logback
pour être sûr qu'aucun log4j n'est présent, vérifiez vos lib sur classpath ou web-inf/lib pour les fichiers de guerre.
bien sûr, vous avez mis les loggers dans logback.xml par exemple:
<logger name="org.hibernate.SQL" level="TRACE"/>
j'ai eu un problème pour faire fonctionner hibernate 4 logging avec weblogic 12c et log4j. La solution est de mettre ce qui suit dans votre application weblogic.xml:
<prefer-application-packages>
<package-name>org.apache.log4j.*</package-name>
<package-name>org.jboss.logging.*</package-name>
</prefer-application-packages>
à tous ceux qui pourraient faire face au même problème que moi. Dans le cas où vous avez essayé toutes les autres solutions expliquées ici et ne voyez toujours pas hibernate logging travailler avec votre slf4j, cela pourrait être parce que vous utilisez un conteneur qui a dans ses bibliothèques de dossiers le JBoss-logging.pot. Cela signifie qu'il est préchargé avant même que vous puissiez configurer n'importe quelle configuration pour l'influencer. Pour éviter ce problème dans weblogic vous pouvez spécifier dans le fichier de weblogic application.xml dans ton oreille/META-INF à préférer la bibliothèque chargée de l'application. il devrait y avoir un mécanisme similaire pour d'autres serveurs conteneurs. Dans mon cas, je devais ajouter:
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-application xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-application" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/javaee_5.xsd http://xmlns.oracle.com/weblogic/weblogic-application http://xmlns.oracle.com/weblogic/weblogic-application/1.5/weblogic-application.xsd">
<wls:prefer-application-packages>
<!-- logging -->
<wls:package-name>org.slf4j.*</wls:package-name>
<wls:package-name>org.jboss.logging.*</wls:package-name>
</wls:prefer-application-packages>
<wls:prefer-application-resources>
<wls:resource-name>org/slf4j/impl/StaticLoggerBinder.class</wls:resource-name>
</wls:prefer-application-resources>
</wls:weblogic-application>
avez-vous essayer ceci:
- slf4j-log4j12.jar dans le cas de Log4J. Voir la documentation SLF4J pour plus de détails. Pour utiliser Log4j vous aurez également besoin de placer un log4j.fichier de propriétés dans votre classpath. Un exemple de fichier de propriétés est distribué avec Hibernate dans le répertoire src/
il suffit d'ajouter ces bocaux et propriétés ou log4j xml dans le chemin de classe