6

logback-core 1.0.13私のプロジェクトは、SLF4J API (1.7.5) とその実装 (および)として logback ライブラリを含む EAR ファイルとしてパックされていますlogback-classic 1.0.13

私が(以前)プロジェクトをデプロイすると、SLF4J の LoggerFactory は logback をバインド可能なものとして検出し、正しいロガー (つまり logback) が使用されます。

activemq-rar-5.8.0.rarこれで、自分の EAR ファイルの前にデプロイされるリソース コネクタ ( ) ができました (EAR ファイルには RAR が必要なため)。残念ながら、この RAR には独自の SLF4J 実装が含まれています ( slf4j-api-1.6.6.jar slf4j-log4j12-1.6.6.jar log4j-1.2.17.jar)。RAR ファイルは log4j 実装を使用します。

EAR ファイルをデプロイすると、アプリケーションのコード内の LoggerFactory が突然 log4j 実装 ( org.slf4j.impl.Log4jLoggerAdapter) を使用します。クラスパスが RAR から分離されていると予想していたにもかかわらずです。

これは当てはまらないようです - では、何が間違っているのでしょうか (RAR は log4j を使用する必要があり、EAR は logback を使用する必要があります)。


更新 1: 1 人ではないように見えますが、残念ながら回答がありません..


更新 2:

この表によると、GlassFish は EAR/WAR ライブラリ (最後にロードされるライブラリ) の前にコネクタ モジュールをロードします。


更新 3:

私はなんとか「バインディング」を修正しました: GlassFish のフォルダー内に とslf4j-api-1.7.5.jarlogback 実装 (logback-core-1.0.13.jarおよびlogback-classic-1.0.13.jar)を配置するとdomains/<myDomain>/lib、logback がログ実装として使用されます (更新 2 を参照してください - 「共通クラスローダー」は「コネクター クラスローダー」の前に来ます)。

残念ながら、構成ファイルは WAR/EAR 内にあるため、もう見つかりません。これは、後で別のクラスローダー (「アーカイブ クラスローダー」) によってロードされます。

したがって、ログバック構成ファイルをEAR / WAR内に保持したいので(すべてのアプリケーションが異なる構成を使用するため)、これは実際には解決策ではありません。


敬具

愚かな羊

4

1 に答える 1

1

私はついに許容できる解決策を見つけました。

GlassFish は、EAR/WAR の前にコネクタ モジュールをロードします。「更新 2」を参照してください。コネクタ モジュールがロードされる前に SLF4J 実装を提供することで、提供された SLF4J 実装が使用されます。

これを行うために、次の JARS をディレクトリにコピーしましたdomains/<myDomain>/lib(「更新 3」を参照)。

  • logback-core-1.0.13.jar
  • logback-classic-1.0.13.jar
  • slf4j-api-1.7.5.jar

残念ながら、logback は独自の構成ファイル ( logback.xml) をもう見つけられませんでした。これは、クラスパス上にある必要があります (JAR 内にパックしたので、そうです)。

解決策は、logback を手動で構成することです。次の CDI プロデューサーを使用してこれを行いました。

package com.example;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;

@ApplicationScoped
public class LoggerProducer {
    @PostConstruct
    public void initialize() {
        // The following is logback specific. Unfortunately logback doesn't find its XML configuration
        // as the logback implementation gets loaded by a different ClassLoader than this code.
        // See http://docs.oracle.com/cd/E19226-01/820-7695/6niugesfp/index.html#indexterm-28
        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        JoranConfigurator joranConfigurator = new JoranConfigurator();
        joranConfigurator.setContext(lc);
        lc.reset();

        try {
            // The logback configuration is now being loaded from the classpath (by the "Archive Classloader")
            joranConfigurator.doConfigure(this.getClass().getClassLoader().getResource("logback.xml"));
        } catch (JoranException e) {
            e.printStackTrace();
        }
    }

    @Produces
    @ApplicationLogger
    Logger createLogger(InjectionPoint injectionPoint) {
        return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass());
    }
}

これにより、ログバックが構成されます。これを行うために logback 固有のコードを使用したことに注意してください。そのため、SLF4J の実装を変更する場合は、 も変更する必要がありLoggerProducerます。

「共通クラスローダー」のクラスパスにEAR/WARがないため、logbackは構成ファイルを見つけられないと思います。ただし、後でアプリケーションがロードされると、「アーカイブ クラスローダー」のlogback.xmlクラスパスが (EAR/WAR ファイルによって提供されるため) あるため、すべてが整ったらログバックを構成できます。

よろしく愚かな羊

于 2013-08-13T13:00:57.537 に答える