2013-08-08 13 views
6

Un progetto di mine viene compresso come un file EAR che contiene API SLF4J (1.7.5) nonché le librerie di logback come implementazione (logback-core 1.0.13 e logback-classic 1.0.13).SLF4J - Le associazioni vengono sovrascritte da altre applicazioni sullo stesso server applicazioni

Quando I (usato per) distribuire il mio progetto, LoggerFactory di SLF4J trova il logback possibile come vincolante e viene utilizzato il logger corretto (cioè il logback).

Ora ho un connettore risorsa (activemq-rar-5.8.0.rar) che viene distribuito prima del mio file EAR (come i file EAR richiede l'RAR). Sfortunatamente questo RAR contiene la sua implementazione SLF4J (slf4j-api-1.6.6.jarslf4j-log4j12-1.6.6.jarlog4j-1.2.17.jar). I file RAR utilizzano l'implementazione log4j.

Quando distribuisco il file EAR, LoggerFactory all'interno del codice dell'applicazione utilizza improvvisamente l'implementazione log4j (org.slf4j.impl.Log4jLoggerAdapter), anche se mi aspettavo che il classpath fosse separato dal RAR.

Questo non sembra essere il caso - quindi cosa sto facendo male (il RAR dovrebbe usare log4j, il mio EAR dovrebbe usare il logback)?


Update 1: It doesn't look as if I am alone, ma purtroppo una risposta manca ..


Aggiornamento 2:

Secondo this tavolo, GlassFish carica il modulo connettore prima le librerie EAR/WAR (che sono le ultime librerie libere da caricare).


Update 3:

sono riuscito a risolvere il "vincolante": Se metto il slf4j-api-1.7.5.jar e l'implementazione logback (logback-core-1.0.13.jar e logback-classic-1.0.13.jar) all'interno della cartella domains/<myDomain>/lib in GlassFish, verrà utilizzato logback come implementazione di registrazione (vedi Aggiornamento 2 - "Common Classloader" viene prima di "Connector Classloader").

Purtroppo i miei file di configurazione non vengono più trovati poiché si trovano all'interno di WAR/EAR - che verranno caricati successivamente da un altro classloader ("Archive Classloader").

Quindi questa non è davvero una soluzione per me dato che mi piacerebbe mantenere i file di configurazione di logback all'interno di EAR/WAR (dato che ogni applicazione usa una configurazione diversa).


Genere riguarda

stupidSheep

+0

Perché il pacchetto log4j in una dipendenza? Il contenitore non può occuparsi della configurazione della registrazione e fornire l'impl? – roby

+0

Non impacchetta log4j come dipendenza da solo. È nel RAR (resource adapter) fornito da Apache ActiveMQ (http://activemq.apache.org/maven/5.8.0/activemq-rar/dependencies.html). Questi file JAR si trovano all'interno del RAR insieme ad alcuni file di configurazione del registro. – stupidSheep

risposta

1

ho finalmente capito una soluzione accettabile.

GlassFish carica il modulo connettore prima di EAR/WAR, vedere "Aggiornamento 2". Fornendo l'implementazione SLF4J PRIMA del caricamento del modulo connettore, viene utilizzata l'implementazione SLF4J fornita.

Per fare ciò ho copiato i seguenti JARS nella directory domains/<myDomain>/lib (vedere "Aggiornamento 3").

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

Purtroppo logback non ha trovato il proprio file di configurazione (logback.xml) più, che deve essere nel classpath (che è, come ho imballato dentro un JAR).

La soluzione è configurare manualmente il logback. Ho fatto questo utilizzando il seguente produttore 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()); 
    } 
} 

Questo configurerà logback. Tieni presente che ho utilizzato un codice di logback specifico per farlo, quindi se cambi l'implementazione di SLF4J devi modificare anche lo LoggerProducer.

Penso logback non trovare il suo file di configurazione come il "programma di caricamento classi Comune" non ha l'EAR/WAR sul suo percorso di classe. Ma in seguito, quando l'applicazione viene caricata, "Archive Classloader" ha il logback.xml sul suo classpath (come viene fornito dal file EAR/WAR), quindi è possibile configurare il logback una volta che tutto è a posto.

Riguarda stupidSheep

+0

Si scopre che questo non funziona. L'ultima applicazione da caricare sostituirà la configurazione del logger. – stupidSheep

+0

Lavoro perfettamente predisposto. – Sam