SLF4J'yi kullanmak için Hibernate 4'te oturum açmayı nasıl yapılandırırsınız?


114

Hibernate 3.x kullanıldı günlüğü için. Hazırda bekletme 4.x kullanımları. Günlük kaydı için Hibernate 4 ve SLF4J kullanan bağımsız bir uygulama yazıyorum.

Hazırda Bekletmeyi SLF4J'de oturum açacak şekilde nasıl yapılandırabilirim?

Bu mümkün değilse, Hazırda Bekletme'nin günlük kaydını nasıl yapılandırabilirim?

Günlük kaydı ile ilgili Hibernate 4.1 kılavuz bölümü, şu uyarıyla başlar ...

Tamamen güncel değil. Hibernate, 4.0'dan itibaren JBoss Logging'i kullanır. Bu içeriği Geliştirici Kılavuzuna taşırken bu belgelenecektir.

... SLF4J hakkında konuşmaya devam ediyor ve bu yüzden faydasız. Ne başlangıç kılavuzu ne de geliştirici kılavuzu günlüğe kaydetme hakkında hiç konuşmuyor. Göç de rehberlik etmez .

Jboss-logging ile ilgili belgeleri aradım, ancak hiçbirini bulamadım. GitHub sayfa sessizdir ve JBoss en topluluk projeleri sayfası bile liste Jboss günlüğü buna gerek yoktur. Projenin hata izleyicisinin belgelerin sağlanmasıyla ilgili herhangi bir sorunu olup olmadığını merak ettim , ama yok.

İyi haber şu ki, Hibernate 4'ü JBoss AS7 gibi bir uygulama sunucusunda kullanırken, günlük kaydı sizin için büyük ölçüde halledilir. Ancak bunu bağımsız bir uygulamada nasıl yapılandırabilirim?


13
Oturum açma sırasında Hazırda Bekletme belgelerinin güncel olmadığını vurgulamak için +1
mhnagaoka

Sistem özelliği org.jboss.logging.provide = slf4j olarak ayarlanabilir. Daha fazla ayrıntı için lütfen 3'ten büyük hazırda bekletme sürümü için docs.jboss.org/hibernate/orm/4.3/topical/html/logging/… bağlantısını ziyaret edin .
Abhishek Ranjan,

Yanıtlar:


60

Https://github.com/jboss-logging/jboss-logging/blob/master/src/main/java/org/jboss/logging/LoggerProviders.java adresine bakın :

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();
}

Yani için olası değerler org.jboss.logging.providerşunlardır: jboss, jdk, log4j, slf4j.

Ayarlamazsanız org.jboss.logging.provider, jboss, ardından log4j, ardından slf4j (sadece logback kullanılmışsa) ve jdk'ye geri dönüş yapmayı dener.

Kullandığım slf4jile logback-classic:

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.13</version>
        <scope>${logging.scope}</scope>
    </dependency>

ve hepsi iyi çalışıyor!

GÜNCELLEME Bazı kullanıcılar çok ana App.java'da kullanır:

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

ancak konteyner tabanlı çözümler için bu işe yaramadı.

GÜNCELLEME 2 Log4j'yi SLF4J ile yönettiklerini düşünenler jboss-loggingtam olarak böyle değildir. jboss-loggingSLF4J olmadan doğrudan Log4j kullanır!


1
Nereye kurulmalı org.jboss.logging.provider?
Suzan Cioc

1
@SuzanCioc Size göre System.getProperty(LOGGING_PROVIDER_KEY);set sistem özelliği gerekir. Through java -D...=...veya konteyner için dokümanlar kontrol edin.
gavenkoa

1
Slf4j aracılığıyla log4j'yi kullanamama konusundaki ikinci güncellemeniz yardımcı oldu. Org.jboss.logging.provider'ı slf4j olarak ayarlamak, log4j desteğimin devreye gireceğini düşünmeme neden oldu. Yine de olmadı. Bunun çalışması için doğrudan log4j olarak ayarlamam gerekiyordu. Garip. O halde slf4j'nin bu yapılandırma için bir seçenek olarak anlamı nedir?
Travis Spencer

27

Arka uç bir sistem özelliğinin kullanılmasını gerektirdiğinden, SLF4J'nin Logback olmadan JBoss Logging ile çalışmasını sağlamak için org.jboss.logging.provider=slf4j. log4j-over-slf4jBu durumda taktikler işe yaramıyor gibi görünmektedir çünkü ne Logback ne de log4j sınıf yolunda gerçekten mevcut değilse loglama JDK'ya geri dönecektir.

Bu biraz can sıkıcı bir durumdur ve otomatik algılamanın işe yaraması için, sınıf yükleyicinin en azından ch.qos.logback.classic.Loggerlogback-classic veya log4j'den org.apache.log4j.HierarchyJBoss Logging'i JDK günlüğüne geri dönmemesini kandırmak için içerdiğini gördünüz .

Sihir yorumlanır org.jboss.logging.LoggerProviders

GÜNCELLEME: Hizmet yükleyici desteği eklendi, böylece META-INF/services/org.jboss.logging.LoggerProvider( org.jboss.logging.Slf4jLoggerProviderbir değer olarak) bildirerek otomatik algılamayla ilgili sorunları önlemek mümkündür . Log4j2 desteği de eklenmiş gibi görünüyor.


1
Bu sistem özelliğini nerede ayarlayabilirim?
jhegedus

Kurulumunuza bağlıdır, ancak normalde bir komut satırı anahtarı -Dorg.jboss.logging.provider=slf4jyeterlidir. LoggingProviders.java , kabul edilen geçerli değerlerin ne olduğu ve sınıf yolunda nelerin bulunması bekleneceği konusunda size daha iyi içgörüler sağlar.
Tuomas Kiviaho

2
Servis yükleyici yaklaşımının işe yaradığını düşünmüyorum çünkü Slf4jLoggerProviderbir publicsınıf değil mi?
holmis83

Bir weblogic WAR'da org.jboss.logging.provider'ı kaynak koduna ayarlamam gerekiyor, ancak herhangi bir statik sınıf başlatıcısı LoggingProviders birinden sonra çağrılır!
Antonio Petricca

12

Leif'in Hypoport gönderisinden esinlenerek , Hibernate 4'ü slf4j'ye şöyle "eğdim":

Maven kullandığınızı varsayalım.

  • Ekle org.slf4j:log4j-over-slf4jiçin bir bağımlılık olarak sizinpom.xml
  • Komutu kullanarak, bağımlı kullandığınız yapılardan hiçbirinin olmadığındanmvn dependency:tree emin olun (kesin olmak gerekirse, hiçbir yapının derleme kapsamı bağımlılığı veya çalışma zamanı kapsam bağımlılığı olmayacaktır )slf4j:slf4jslf4j:slf4j

Arka plan: Hazırda bekletme 4.x, yapıya bağımlıdır org.jboss.logging:jboss-logging. Geçişli olarak, bu yapının yapıtta sağlanan bir kapsam bağımlılığı vardır slf4j:slf4j.

Artık yapıyı eklediğimiz için org.slf4j:log4j-over-slf4j, org.slf4j:log4j-over-slf4jyapıyı taklit ediyor slf4j:slf4j. Bu nedenle, JBoss Logginggünlükleri tutan her şey artık slf4j üzerinden gidecek.

Günlük arka ucu olarak Logback'i kullandığınızı varsayalım . İşte bir örnekpom.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>

Sınıfyolu günü, bir var logback.xmlböyle yer bunun gibi, 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 -->

Bazı bileşenler, logback.xmlörneğin Jetty Maven Eklentisi gibi, düzgün günlük kaydı için JVM başlatma zamanında erişime sahip olmak isteyebilir . Bu durumda, logback.configurationFile=./path/to/logback.xmlkomutunuza bir Java sistemi ekleyin (örn. mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run).

Hala "ham" konsol stdout Hazırda Bekletme çıkışı (gibi Hibernate: select ...) alıyorsanız, "Konsolda hazırda bekletme günlüğünü kapat " Yığın Taşması sorusu geçerli olabilir.


1
Başka hiçbir kitaplığın log4j içermediğinden emin olun, aksi takdirde bu çalışmayacaktır. Örnek: activemq-all.jar, log4j'yi içerir. İpucu: IDE'nizi açın ve log4j'yi kodunuzda kolayca bulun.
Dimitri Dewaele

Bu sorunu JBoss Hibernate4 ve (çok) eski bir sunucu ile yaşadım. Bu gönderi, application.properties'teki 1 satır dahil olmak üzere benim için hile yaptı. Öyleyse TNX !!! Ve mülklerimdeki bu son satır burada başka bir cevapta yazılmıştır:org.jboss.logging.provider=slf4j
Jeroen van Dijk-Haz

8

Öncelikle, SLF4J'nin bir günlük kaydı kitaplığı olmadığını, bir günlük sarmalayıcısı olduğunu anlıyorsunuz. Kendi başına hiçbir şey kaydetmez, sadece "arka uçlara" delege eder.

Jboss-logging'i "yapılandırmak" için, sınıf yolunuzda kullanmak istediğiniz günlük çerçevesini (jboss-logging ile birlikte) ekleyin ve geri kalanını jboss-logging belirler.

JBoss Logging yapılandırması için Hazırda bekletme odaklı bir kılavuz oluşturdum: http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html


2
SLF4J'nin bir cephe olduğunun farkındayım, evet. Hazırda bekletme günlüğünü SLF4J'ye göndermek, uygulamamın geri kalanı için seçtiğim arka uçta biteceği anlamına geliyor, istediğim de bu.
Tom Anderson

10
Öyleyse, konfigürasyon hakkında söylediğiniz şey, konfigürasyon olmadığı (ki bu güzel!), Ancak bu jboss-loglama bir şekilde bir arka uç algılayıp seçiyor? Ah, şimdi koda gerçekten bakmak için zaman ayırıyorum, tam olarak ne olduğunu görüyorum . Spesifik olarak, jboss-logging sırayla JBoss LogManager, log4j, SLF4J üzerinden Logback ve JDK günlük kaydını dener. Ama bu olabilir ile geçersiz kılınan olmak org.jboss.logging.providersistem özelliği.
Tom Anderson

2
Birçoğumuz, sizin için ortak oturum açma rakamları nedeniyle yanmış durumdayız, bu nedenle jboss-logging'in tam olarak nasıl çalıştığını bilmek, beklenmedik bir şey olduğunda gerçek dünyada onu destekleyebilmek için kritik öneme sahiptir.
ams

1
Aslında yukarıdaki bağlantı, gerçekten görmek istediğiniz şey buysa tam olarak ne olacağını gösteriyor, yani takip etmeyin ...
Steve Ebersole

3

Hibernate Core 4.1.7.Final plus Spring 3.1.2.RELEASE'i bağımsız bir uygulamada kullanıyorum. Bağımlılıklarıma Log4j 1.2.17'yi ekledim ve öyle görünüyor ki, JBoss Logging, varsa doğrudan log4j'ye günlükler kaydettiğinden ve Spring Commons Logging'i kullandığından, witch de mevcutsa Log4j'yi kullandığından, tüm Logging Log4J aracılığıyla yapılandırılabilir.

İşte ilgili bağımlılıklar listem:

<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>

3

yani, onu projemde çalıştırdım. hazırda bekletme 4, slf4j, logback. projem kademeli, ancak maven için aynı olmalı.

Temelde Abdull haklı. Onun haklı olmadığı yerde, slf4j'yi bağımlılıklardan kaldırmak zorunda kalmamanızdır.

  1. kapsamı derlemek için ekleyin:

    org.slf4j: slf4j-api

    org.slf4j: log4j-over-slf4j

    örneğin, logback için (ch.qos.logback: logback-classic, ch.qos.logback: logback-core: 1.0.12)

  2. log4j kitaplıklarını bağımlılıklardan tamamen hariç tut

sonuç: günlükleri slf4j aracılığıyla oturum açmak için hazırda bekletme. Tabii ki, logback'den farklı bir günlük uygulaması kullanabilmelisiniz

hiçbir log4j'nin bulunmadığından emin olmak için, savaş dosyaları için sınıf yolunda veya web-inf / lib'deki kitaplıklarınızı kontrol edin.

tabii ki logback.xml'deki logger'ları ayarladınız, örneğin:

<logger name="org.hibernate.SQL" level="TRACE"/>


tam olarak bu sorunu yaşadım. log4j, başka bir kitaplıktan geçişli bağımlılık olarak getiriliyordu. Hariç tutuldu ve hazırda bekletme günlüğü, beklendiği gibi logback ve slf4j log4j köprüsü kullanılarak çalışmaya başladı
Paul Zepernick

3

Hibernate 4.3'ün nasıl kontrol edileceğiyle ilgili bazı belgeleri vardır org.jboss.logging:

  • Bir günlük kaydı sağlayıcısı için sınıf yolunu arar . Log4j'yi aradıktan sonra slf4j'yi arar. Bu nedenle, teoride, sınıf yolunuzun (WAR) log4j içermediğinden ve slf4j API'sini içerdiğinden ve arka ucun çalıştığından emin olun.

  • Son çare olarak org.jboss.logging.providersistem özelliğini olarak ayarlayabilirsiniz slf4j.


Dokümantasyon iddialarına rağmen, org.jboss.logginglog4j kullanılmamasına ve SLF4J mevcut olmasına rağmen log4j'yi kullanmaya çalışmak konusunda ısrar etti ve Tomcat günlük dosyamda ( /var/log/tomcat/catalina.out) aşağıdaki mesajla sonuçlandı :

 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.

DasAnderl ausMinga'nın cevabının önerisini takip etmek ve log4j-over-slf4jköprüyü dahil etmek zorunda kaldım .


2

Maven kullanıyorum ve şu bağımlılığı ekledim:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.6</version>
</dependency>

Sonra şurada bir log4j.propertiesdosya oluşturdum /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

Bu, onu senin köküne koyacak .jar. Mucizevi şekilde çalışır...


3
Bu, log4j kullanımını yapılandırır. OP, log4j'yi kullanmak istemiyor; slf4j kullanmak istiyorlar.
Raedwald

1

Hazırda bekletme 4 günlüğünü weblogic 12c ve log4j ile çalıştırma konusunda sorun yaşadım. Çözüm, aşağıdakileri weblogic-application.xml dosyanıza koymaktır:

<prefer-application-packages>
    <package-name>org.apache.log4j.*</package-name>
    <package-name>org.jboss.logging.*</package-name>
</prefer-application-packages>

0

Benim sahip olduğum aynı problemle yüzleşebilecek herkese. Burada açıklanan diğer tüm çözümleri denediyseniz ve hala slf4j'nizle çalışırken hazırda bekletme günlüğünü göremiyorsanız, bunun nedeni klasör kitaplıklarında jboss-logging.jar olan bir kapsayıcı kullanıyor olmanız olabilir. Bu, siz onu etkileyecek herhangi bir yapılandırmayı bile ayarlamadan önce önceden yüklenmiş olduğu anlamına gelir. Weblogic'te bu sorunu önlemek için, uygulamadan yüklenen kitaplığı tercih etmek için ear / META-INF dosyasındaki weblogic-application.xml dosyasında belirtebilirsiniz. diğer sunucu kapsayıcıları için benzer bir mekanizma olmalıdır. Benim durumumda eklemek zorunda kaldım:

<?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>

-2

bunu denedin mi

- Log4J durumunda slf4j-log4j12.jar. Daha fazla ayrıntı için SLF4J belgelerine bakın. Log4j'yi kullanmak için sınıf yolunuza bir log4j.properties dosyası da yerleştirmeniz gerekir. Örnek bir özellikler dosyası, src / dizininde Hibernate ile dağıtılır

sadece bu kavanozları ve özellikleri veya log4j xml'yi sınıf yoluna ekleyin


4
Hibernate 3.x belgelerinden bir alıntıdır. Bunun SLF4J kullanmayan Hibernate 4.x ile çalışacağını düşünüyor musunuz?
Tom Anderson

hatırladığım kadarıyla log4j yeterli
Avihai Marchiano
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.