Як налаштувати вхід в режим Hibernate 4 для використання SLF4J


114

Зимовий режим 3.x використаний для проведення лісозаготівлі. Hibernate 4.x використовує. Я пишу окрему програму, яка використовує Hibernate 4 та SLF4J для ведення журналів.

Як я можу налаштувати Hibernate для входу в SLF4J?

Якщо це неможливо, як я можу взагалі налаштувати журнал Hibernate?

Розділ вручну в режимі Hibernate 4.1 щодо реєстрації даних починається з попередження, що це ...

Повністю застаріла. Hibernate використовує журнал JBoss, починаючи з 4.0. Це буде задокументовано під час переміщення цього вмісту до Посібника для розробників.

... продовжує говорити про SLF4J, і так марно. Ні посібник із початку роботи, ні керівництво розробника взагалі не говорять про ведення журналів. Також не посібник з міграції .

Я шукав документацію на jboss-журнал, але я не зміг їх знайти взагалі. Сторінка GitHub мовчить , а сторінка проектів спільноти JBoss навіть не перераховує журнал jboss. Мені було цікаво, чи можуть у трекера помилок проекту виникнути якісь проблеми, пов'язані із наданням документації, але це не так.

Хороша новина полягає в тому, що при використанні Hibernate 4 всередині сервера додатків, таких як JBoss AS7, ведення журналу значною мірою подбає про вас. Але як я можу налаштувати його в автономному додатку?


13
+1 для того, щоб підкреслити, що документи зі сплячого часу при реєстрації застаріли
mhnagaoka

Можна встановити властивість системи org.jboss.logging.provide = slf4j. Для отримання більш детальної інформації перейдіть за посиланням docs.jboss.org/hibernate/orm/4.3/topical/html/logging/… для сплячої версії понад 3.
Abhishek

Відповіді:


60

Перегляньте 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 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();
}

Таким чином , можливі значення org.jboss.logging.providerє: jboss, jdk, log4j, slf4j.

Якщо ви не встановите, org.jboss.logging.providerвін намагається перетворити jboss, тоді log4j, потім slf4j (тільки якщо використовується зворотний зв'язок) та backback до jdk.

Я використовую slf4jз logback-classic:

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

і все добре працює!

ОНОВЛЕННЯ Деякі користувачі використовують у головній App.java:

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

але для контейнерних рішень це не працює.

ОНОВЛЕННЯ 2 Тим, хто думає, що вони управляють Log4j за допомогою SLF4J, jboss-loggingце не зовсім так. jboss-loggingбезпосередньо використовує Log4j без SLF4J!


1
Де встановити org.jboss.logging.provider?
Suzan Cioc

1
@SuzanCioc Відповідно System.getProperty(LOGGING_PROVIDER_KEY);вам потрібно встановити властивість системи. Через java -D...=...або перевірте документи для вашого контейнера.
gavenkoa

1
Ваше друге оновлення про неможливість використання log4j через slf4j було корисним. Встановлення org.jboss.logging.provider на slf4j змусило мене думати, що моя підтримка log4j запуститься. Однак це не сталося. Мені довелося встановити це безпосередньо на log4j, щоб це працювало. Незвичайно. Який сенс slf4j як варіант для цього конфігурації?
Тревіс Спенсер

27

Щоб SLF4J працював з JBoss Logging без Logback, оскільки бекенд вимагає використання властивості системи org.jboss.logging.provider=slf4j. log4j-over-slf4jтактика, схоже, не працює в цьому випадку, тому що реєстрація повернеться до JDK, якщо ні Logback, ні log4j насправді не присутній у classpath.

Це трохи неприємно, і для того, щоб автоматичне виявлення працювало, ви побачили, що завантажувач класів містить принаймні ch.qos.logback.classic.Loggerз клавіш logback або classic або org.apache.log4j.Hierarchylog4j, щоб обдурити Журнал JBoss не повертатися до журналу JDK.

Магія тлумачиться на org.jboss.logging.LoggerProviders

ОНОВЛЕННЯ: Додана підтримка завантажувача сервісу, щоб можна було уникнути проблем із автоматичним виявленням, оголосивши META-INF/services/org.jboss.logging.LoggerProvider( org.jboss.logging.Slf4jLoggerProviderяк значення). Здається, також додано підтримку log4j2.


1
Де встановити цю властивість системи?
jhegedus

Залежить від вашої установки, але зазвичай -Dorg.jboss.logging.provider=slf4jдостатньо комутатора командного рядка . LoggingProviders.java дає кращу інформацію про те, що є поточними прийнятими значеннями та що слід очікувати, щоб вони були присутніми на класі.
Туомас Ківіахо

2
Я не думаю, що підхід до завантажувача послуг працює, оскільки Slf4jLoggerProviderце не publicклас?
holmis83

Мені потрібно встановити org.jboss.logging.provider у weblogic WAR у вихідний код, але будь-який ініціалізатор статичного класу викликається після одного LoggingProviders!
Антоніо Петріка

12

Натхненний гіпопортним повідомленням Лейфа , ось як я "зігнув" сплячку 4 назад до slf4j:

Припустимо, ви використовуєте Maven.

  • Додайте org.slf4j:log4j-over-slf4jяк залежність до свогоpom.xml
  • Використовуючи команду mvn dependency:tree, переконайтесь, що жоден артефакт, який ви використовуєте, не залежає slf4j:slf4j(якщо бути точним, жоден артефакт не повинен мати залежність від компіляції або залежність від обсягу виконанняslf4j:slf4j )

Передумови: Зимова сплячка 4.x залежить від артефакту org.jboss.logging:jboss-logging. Транзитивно цей артефакт має передбачену залежність від артефакту slf4j:slf4j.

Як ми зараз додали org.slf4j:log4j-over-slf4jартефакт, org.slf4j:log4j-over-slf4jімітує slf4j:slf4jартефакт. Тому все, що JBoss Loggingжурнали, тепер фактично піде через slf4j.

Скажімо, ви використовуєте Зворотний зв'язок у якості резервного журналу. Ось зразок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>

На своєму уроці майте такий logback.xml, як цей, розташований у 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 -->

Деякі компоненти можуть мати доступ до часу logback.xmlзапуску JVM для правильного ведення журналу, наприклад, плагін Jetty Maven. У цьому випадку додайте logback.configurationFile=./path/to/logback.xmlдо своєї команди систему Java (наприклад mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run).

Якщо ви все ще отримуєте «сирий» вихід консольного режиму зі сну (наприклад Hibernate: select ...), тоді може бути застосовано питання про переповнення стека « Вимкнути сплячий режим журналу до консолі ».


1
Переконайтеся, що жодна інша бібліотечна іклада log4j, інакше це не працюватиме. Приклад: activemq-all.jar містить log4j. Підказка: Відкрийте свій IDE і легко знайдіть log4j у своєму коді.
Димитрій Дюаеле

У мене була ця проблема з JBoss Hibernate4 і (занадто) старим сервером. Ця публікація, включаючи 1 рядок у application.properties, зробила для мене трюк. Тож TNX !!! І цей останній рядок у моїх властивостях був написаний в іншій відповіді тут:org.jboss.logging.provider=slf4j
Jeroen van Dijk-Jun

8

Спочатку ви розумієте, що SLF4J - це не права бібліотеки журналів, а її обгортка. Він сам нічого не реєструє, він просто делегує "бакендс".

Щоб "налаштувати" jboss-журнал, ви просто додасте будь-які рамки журналу, які ви хочете використовувати на своєму classpath (разом з jboss-logging) та jboss-logging, виведіть решту.

Я створив посібник, орієнтований на зимування, для конфігурації журналу JBoss: http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html


2
Я розумію, що SLF4J - це фасад, так. Надсилання журналу сплячого режиму до SLF4J означає, що він закінчується в будь-який бэкенд, який я обрав для решти моєї програми, чого я хочу.
Том Андерсон,

10
Отже, що ви говорите про конфігурацію, це те, що немає конфігурації (що приємно!), Але що jboss-журнал якось виявляє та вибирає бекенд? Ага, зараз я забираю час, щоб насправді подивитися на код, я бачу, що саме так і відбувається . Зокрема, jboss-журнал намагається виконувати порядок, JBoss LogManager, log4j, Logback через SLF4J та JDK. Але це може бути замінено org.jboss.logging.providerвластивістю системи.
Том Андерсон,

2
Багатьох із нас спалили загальнодоступні фігури, які розбирають для вас речі, тому точно знати, як працює jboss-журнал, є критичним для того, щоб мати змогу підтримати його в реальному світі, коли станеться несподіване.
Ams

1
Наведене вище посилання насправді показує, що саме відбувається, якщо це те, що ви насправді хочете бачити, так що не
слідкуйте

3

Я використовую Hibernate Core 4.1.7.Final плюс Spring 3.1.2. RELEASE в автономному додатку. Я додав Log4j 1.2.17 до моїх залежностей, і, схоже, як JBoss Logging веде журнал безпосередньо до log4j, якщо такий доступний, а Spring використовує журнал Commons Logging, відьма також використовує Log4j, якщо такий доступний, усі журнали можуть бути налаштовані через Log4J.

Ось мій список відповідних залежностей:

<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

так що я просто працював у моєму проекті. сплячий режим 4, slf4j, зворотний зв'язок. мій проект є студе, але повинен бути таким же для Maven.

В основному Абдулл має рацію. Там, де він НЕ правий, це те, що ви НЕ повинні видаляти slf4j із залежностей.

  1. включити для компіляції області:

    org.slf4j: slf4j-api

    org.slf4j: log4j-over-slf4j

    наприклад, для зворотного зв'язку (ch.qos.logback: logback-classic, ch.qos.logback: logback-core: 1.0.12)

  2. повністю виключати li4 log4j від залежностей

результат: сплячі журнали через slf4j до входу. звичайно, ви повинні мати можливість використовувати іншу реалізацію журналу, ніж logback

щоб переконатися, що немає журналу log4j, перевірте свої файли на classpath чи web-inf / lib на файли війни.

звичайно, ви встановили реєстратори в logback.xml, наприклад:

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


була ця точна проблема. log4j надходив як перехідна залежність від іншої бібліотеки. Виключено це, і сплячий лісозаготівлі почав працювати, як очікувалося, використовуючи logback та міст slf4j log4j
Пол Цеперник

3

Hibernate 4.3 має деяку документацію щодо контролю org.jboss.logging:

  • Він шукає шлях до класу для постачальника журналів . Він шукає slf4j після пошуку log4j. Отже, теоретично, гарантуючи, що ваш класний шлях (WAR) не включає log4j і включає API slf4j, і бек-енд повинен працювати.

  • В крайньому випадку ви можете встановити org.jboss.logging.providerвластивість системи slf4j.


Незважаючи на твердження документації, org.jboss.loggingнаполягали на спробі використовувати log4j, незважаючи на відсутність log4j та наявність SLF4J, в результаті чого у моєму файлі журналу 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.

Мені довелося дотримуватися пропозиції відповіді dasAnderl ausMinga і включити log4j-over-slf4jміст.


2

Я використовую maven і додав таку залежність:

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

Потім я створив log4j.propertiesфайли в /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

Це поставить це в корені вашого .jar. Це працює як шарм ...


3
Це налаштовує використання log4j. ОП не хоче використовувати log4j; вони хочуть використовувати slf4j.
Raedwald

1

У мене виникла проблема з тим, щоб зробити сплячий режим 4 роботи з weblogic 12c та log4j. Рішення полягає в тому, щоб помістити наступне у свій weblogic-application.xml:

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

0

Для кожного, хто міг зіткнутися з тією ж проблемою, що і я. Якщо ви спробували всі інші рішення, пояснені тут, і все ще не бачите сплячого журналу, що працює з вашим slf4j, це може бути тому, що ви використовуєте контейнер, який має в бібліотеках його папок jboss-logging.jar. Це означає, що він попередньо завантажується, перш ніж ви навіть зможете встановити будь-яку конфігурацію, щоб впливати на нього. Щоб уникнути цієї проблеми в weblogic, ви можете вказати у файлі weblogic-application.xml у вашому вусі / META-INF, щоб віддати перевагу завантаженій із програми бібліотеці. має бути подібний механізм для інших контейнерів сервера. У моєму випадку мені довелося додати:

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

ти спробував це:

- slf4j-log4j12.jar у випадку Log4J. Докладніше див. Документацію SLF4J. Для використання Log4j вам також потрібно буде розмістити файл log4j.properties у своєму класі. Приклад файлу властивостей поширюється за допомогою Hibernate у src / директорії

просто додайте ці банки та властивості або log4j xml у classpath


4
Це цитата з документації зі сплячого режиму 3.x. Як ви вважаєте, що все одно буде працювати з Hibernate 4.x, який не використовує SLF4J?
Том Андерсон

наскільки я пам'ятаю log4j достатньо
Avihai Marchiano
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.