# Logging mit log4j



## seven-12 (4. Sep 2006)

Hallo, 

ich habe es im Internet ´gefunden:

```
import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.apache.log4j.*;
import org.apache.log4j.xml.DOMConfigurator;

public class MeinLogger
{
  private static final String LOG4J_CONFIG_FILE  = "log4j.xml";
  private static final String MEIN_LOGGER_NAME   = "MeinLogger";
  private static final String MESSAGES_RESBUNDLE = "messages.properties";
  private static ResourceBundle messagesResBundle;
  private static MeinLogger meinLogger;
  private static Logger log4jLogger;

  // private damit Singleton
  private MeinLogger()
  {
    init();
  }

  private synchronized void init()
  {
    try {
    	
      DOMConfigurator.configureAndWatch( LOG4J_CONFIG_FILE, 60*1000 );
      log4jLogger = Logger.getLogger( MEIN_LOGGER_NAME );
      messagesResBundle = ResourceBundle.getBundle( MESSAGES_RESBUNDLE );
      log4jLogger.setResourceBundle( messagesResBundle );
    } catch( MissingResourceException ex ) {
      System.err.println( "Fehler: '" + MESSAGES_RESBUNDLE + "'-.properties-Datei fehlt!" );
    } catch( Exception ex ) {
      System.err.println( "Fehler bei Logger-Initialisierung!" );
    } 
  }

  // Singleton-Instanz
  public static synchronized MeinLogger getInstance()
  {
    if( meinLogger == null ) meinLogger = new MeinLogger();
    return meinLogger;
  }

  public void log( Level level, Object caller, String id, String[] parms ) 
  {
    MDC.put( "clss", caller.getClass().getName() );
    MDC.put( "id", id );

    String message = id;
    if( null != messagesResBundle ) {
      try {
        message = messagesResBundle.getString( id );
      } catch( MissingResourceException ex ) {/**/}
    }
    if( null != parms )
      message = MessageFormat.format( message, parms );

    switch( level.toInt() ) {
      case Priority.ALL_INT:  
      case Priority.DEBUG_INT: log4jLogger.debug( message ); break;
      case Priority.INFO_INT:  log4jLogger.info(  message ); break;
      case Priority.WARN_INT:  log4jLogger.warn(  message ); break;
      case Priority.ERROR_INT: log4jLogger.error( message ); break;
      case Priority.FATAL_INT: log4jLogger.fatal( message ); break;                        
    }
  }

  public boolean isEnabledFor( Level level )
  {
     return log4jLogger.isEnabledFor( level );
  }
}
```

Es ist genau das, was ich brauche.
Was ich aber nicht verstehe, warum kann ich nicht logger.log nur im Konstruktor nutzen.



```
public class MeineKlasse1
{
  private static MeinLogger logger = MeinLogger.getInstance();

 
  {
    logger.log( Level.ERROR, this, "E002", new String[] { "abc", "xyz" } );
  }
}
```

Wie kann ich auf diese Methode log zugreifen?

Ich möchte einfacj innerhalb von if Schleifen logger.log aufrufen.

WAs mache ich falsch?

Danke Euch, 

seven-12


----------



## SlaterB (4. Sep 2006)

logger ist ein statisches Attribut deiner Klasse,
damit kannst es von ÜBERALL innerhalb deines Objektes aufrufen,
nur bei statischen Operationen siehts etwas schlecht aus

für andere Klassen müsstest du analog wiederum ein statisches Objek definieren,
potentiell ist logger und damit logger.log also von all deinen Objekten erreichbar,

was genau ist das Problem?,
funktioniert die Zeile 
logger.log( Level.ERROR, this, "E002", new String[] { "abc", "xyz" } ); 
an anderen Stellen nicht?


----------



## seven-12 (4. Sep 2006)

Vielen Dank für die Erklärung.

Jetzt funktioniert es, ich weiss nicht warum vorher es nicht funktioniert hat.


----------



## Gast (5. Sep 2006)

ich habe noch eine kleine Frage .
wo muss die Datei message.properties liegen,
 damit ich keine Meldung bekomme:Fehler: 'messages.properties'-.properties-Datei fehlt!

private static final String MESSAGES_RESBUNDLE = "messages.properties"; 

Danke und gruß,
seven-12


----------



## seven-12 (5. Sep 2006)

hallo, 

ich habe auch mit: 
private static final String MESSAGES = "resources/messages";
Probleme  Ich habe im Verzeichniss: resources/messages" eine Datei erstellt messages.properties und ich bekomme immer die Meldung:
Fehler: 'messages.properties'-.properties-Datei fehlt! 


Kann jemand helfen?

Gruß,
seven-12


----------



## SlaterB (5. Sep 2006)

die Fehlermeldung sollte dich doch recht deutlich darauf hinweisen,
dass es 
private static final String MESSAGES_RESBUNDLE = "messages";
heißen muss,
dass .properties wird automatisch hinzugefügt


----------



## seven-12 (6. Sep 2006)

klar, 

ich habe : 
private static final String MESSAGES = "messages";

und es kommt die gleiche Fehlermeldung...


----------



## SlaterB (6. Sep 2006)

tja, dann weiß ich auch nicht,
allgemeine Tipps: m stat messages um Rechtschreibfehler zu vermeiden,
auf genaue Schreibweise der Endung achten:
m.properties

----

Im Programm an gleicher Stelle eine Datei TestData.txt erstellen und schauen, wo im Dateisystem diese Datei erstellt wird.

-----
Datei m.properties in alle. Verzeichnisse des Projektes sowie in Oberverzeichnissen bis zum Root-Verzeichnis, im user.home-Verzeichnis, in bin- oder sonstigen verdächtigen Verzeichnissen von Java/ Eclipse/ anderen Programmierumgebungen oder Servern, sonstigen Verzeichnissen im Classpath erstellen.
Überall wo Log4 potentiell nachschaut


----------



## seven-12 (7. Sep 2006)

Hallo, 

vielen Dank,.. wie erstelle ich es im Classpath?

Datei m.properties in alle. Verzeichnisse des Projektes sowie in Oberverzeichnissen bis zum Root-Verzeichnis, im user.home-Verzeichnis, in bin- oder sonstigen verdächtigen Verzeichnissen von Java/ Eclipse/ anderen Programmierumgebungen oder Servern, sonstigen Verzeichnissen im Classpath erstellen. 
Überall wo Log4 potentiell nachschaut 

Danke Dir,

seven-12


----------



## SlaterB (7. Sep 2006)

probier doch erstmal 
> Im Programm an gleicher Stelle eine Datei TestData.txt erstellen und schauen, wo im Dateisystem diese Datei erstellt wird. 

was kommt da raus?
--------
und ich meinte nicht, die Datei in den Classpath einzufügen,
sondern nachzuschauen, welche Verzeichnisse im Classpath sind,
und dort (edit: dort in diese Verzeichnisse auf der Festplatte!!) per Hand die Datei einzufügen (edit: zu kopieren),
eher eine verzweifelter Versuch als dass man da noch genauer drüber reden sollte


----------



## seven-12 (7. Sep 2006)

ok, ich habe im classpath eingetragen:
<classpathentry kind="lib" path="lib/messages"/>
 es kommt auch die gleiche Fehlermeldung, wenn ich eine txt datei erstelle... TestData.txt nicht gefunden...


----------



## SlaterB (7. Sep 2006)

zum zweiten mal: ich spreche NICHT davon, die Datei in den Classpath einzufügen...

----------

Wenn du auf deinem Rechner keine Dateinen erzeugen kannst,
nun, dann freue dich, dann musst du dir zumindest um das Logging keine Sorgen mehr machen,
dann hast du ein viel größeres Problem. 


```
import java.io.File;
import java.io.IOException;

public class Test {

	public static void main(String args[]) throws IOException {
		createTestFile();
	}
	
	public static void createTestFile() throws IOException {
		File f = new File("TestDatei.txt");
		System.out.println("f: " + f.getAbsolutePath()); 
          // dieser Pfad sagt dir, wo du deine messages.properties hinlegen musst!!
		if (f.exists()) {
			System.out.println("f existiert");
		} else {
			boolean create = f.createNewFile();
			System.out.println("hat Erzeugung funktioniert?: " + create);
		}
	}
}
```


----------



## seven-12 (7. Sep 2006)

HI Slater, 

es hat doch noch nicht geholfen: 
Fehler: 'TestDatei.txt'-.properties-Datei fehlt!
Ich habe  
private static final String MESSAGES_RESBUNDLE = "TestDatei.txt"; 
Ich bin verzweifelt....

Gruß,
seven-12


----------



## SlaterB (7. Sep 2006)

tja, du verstehst mich eben nicht,
du sollst nicht TestDatei.txt in den String MESSAGES_RESBUNDLE schreiben, was sollte das bringen?

du sollst in deinem Programm eine Datei ERZEUGEN/ erstellen/ anlegen, wie auch immer,
in der Hoffung, dass du diese Datei dann auf deiner Festplatte wiederfindest, 
und damit erkennst, welches Verzeichnis von deinem Programm überhaupt verwendet wird,
DANN kannst du dort in dieses Verzeichnis die messages.resources-Datei einfügen...


----------



## seven-12 (7. Sep 2006)

danke, ich habe es verstanden, ich habe in diesem Verzeichniss die Datei messages_de.properties erstellt und 
private static final String MESSAGES_RESBUNDLE = "Meinpackage\messages"; 
es funktioniert trotzdem nicht,


----------



## SlaterB (7. Sep 2006)

nun mal immer Schritt für Schritt, 
vor allem: jede Art von packages zunächt weglassen,
sondern nur im default-package (zum testen) arbeiten

Also: in welchem Verzeichnis wird denn die Testdatei erstellt?

Doch wohl hoffentlich im gleichen Verzeichnis, direkt im Projekt-Grundverzeichnis wo auch die .java und .class-Datei von MeinLogger und einer evtl. zweiten Klasse zum Aufruf liegen?

Falls dein Programm zu kompliziert ist benutze so ein einfaches wie folgt:

```
import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.apache.log4j.*;
import org.apache.log4j.xml.DOMConfigurator;

public class MeinLogger {
	private static final String LOG4J_CONFIG_FILE = "log4j.xml";
	private static final String MEIN_LOGGER_NAME = "MeinLogger";
	private static final String MESSAGES_RESBUNDLE = "messages";
	private static ResourceBundle messagesResBundle;
	private static MeinLogger meinLogger;
	private static Logger log4jLogger;

	// private damit Singleton
	private MeinLogger() {
		init();
	}

	private synchronized void init() {
		try {

			DOMConfigurator.configureAndWatch(LOG4J_CONFIG_FILE, 60 * 1000);
			log4jLogger = Logger.getLogger(MEIN_LOGGER_NAME);
			messagesResBundle = ResourceBundle.getBundle(MESSAGES_RESBUNDLE);
			log4jLogger.setResourceBundle(messagesResBundle);
		} catch (MissingResourceException ex) {
			ex.printStackTrace();
			System.err.println(
				"Fehler: '"
					+ MESSAGES_RESBUNDLE
					+ "'-.properties-Datei fehlt!");
		} catch (Exception ex) {
						ex.printStackTrace();
			System.err.println("Fehler bei Logger-Initialisierung!");
		}
	}

	// Singleton-Instanz
	public static synchronized MeinLogger getInstance() {
		if (meinLogger == null)
			meinLogger = new MeinLogger();
		return meinLogger;
	}

	public void log(Level level, Object caller, String id, String[] parms) {
		MDC.put("clss", caller.getClass().getName());
		MDC.put("id", id);

		String message = id;
		if (null != messagesResBundle) {
			try {
				message = messagesResBundle.getString(id);
			} catch (MissingResourceException ex) { /**/
			}
		}
		if (null != parms)
			message = MessageFormat.format(message, parms);

		switch (level.toInt()) {
			case Priority.ALL_INT :
			case Priority.DEBUG_INT :
				log4jLogger.debug(message);
				break;
			case Priority.INFO_INT :
				log4jLogger.info(message);
				break;
			case Priority.WARN_INT :
				log4jLogger.warn(message);
				break;
			case Priority.ERROR_INT :
				log4jLogger.error(message);
				break;
			case Priority.FATAL_INT :
				log4jLogger.fatal(message);
				break;
		}
	}

	public boolean isEnabledFor(Level level) {
		return log4jLogger.isEnabledFor(level);
	}

	public static void main(String[] args) {
		MeinLogger logger = MeinLogger.getInstance();
		Object o = new Object();

		logger.log(Level.ERROR, o, "E002", new String[] { "abc", "xyz" });
	}
}
```

Wenn dann noch messages.properties da ist, kann ja wohl nix mehr schiefgehen.

Notfalls die Library auch in das Verzeichnis kopieren und per Konsole starten mit
java -cp.;logXY.jar MeinLogger


----------



## seven-12 (7. Sep 2006)

Danke, ich habe es geschafft OHne Deine HIlfe würde es nicht klappen, EIne kleine Frage dazu: 

ich habe im message_de.properties:
TEST=Hello

Mit diesem Aufruf :meinlogger.log(Level.ERROR,this,"TEST") dachte ich , bekomme ich Hello in meine Log Datei, ich habe aber nur TEST

Was kann hier falsch sein, ich habe log Methode so geändert:
 public void log( Level level, Object caller, String id ) 
  {
	MDC.put( "clss", caller.getClass().getName() );
    MDC.put( "id", id );
    String message = id;


    if( null != messagesResBundle ) {
    	try {
        message = messagesResBundle.getString(id);
        System.out.println("message"+message);
      } catch( MissingResourceException ex ) {/**/}
    }


    switch( level.toInt() ) {
      case Priority.ALL_INT:  
      case Priority.DEBUG_INT: log4jLogger.debug( message ); break;
      case Priority.INFO_INT:  log4jLogger.info(  message ); break;
      case Priority.WARN_INT:  log4jLogger.warn(  message ); break;
      case Priority.ERROR_INT: log4jLogger.error( message ); break;
      case Priority.FATAL_INT: log4jLogger.fatal( message ); break;                        
    }
  }

Danke Dir 
Gruß,
seven-12


----------



## SlaterB (7. Sep 2006)

tja, was ist denn nun wieder message_de.properties?
hoffentlich nur umbenannt die normale Datei?
mehrere verschiedene Dateien, das wär ja was nach den ersten Problemen..

ich wüßte nun nicht wirklich was man falsch machen könnte,
hast du den String in die falsche von mehreren Dateien geschrieben?
vielleicht mit einem seltsamen Editor der eine Datei in ungünstigen Format erzeugt?
versuche mal irgendwo anders eine fertige property-Datei zu klauen und kopiere sie nur/ benenne sie um, aber nicht den Inhalt verändern,
klappts mit deren Keys?

------

gib im Programm doch mal alle enthaltenen Keys aus mit 


```
try {
				Enumeration en = messagesResBundle.getKeys();
				while (en.hasMoreElements()) {
					String key = (String) en.nextElement();
					System.out.println("key: "+key+" -> "+messagesResBundle.getString(key));
				}
				message = messagesResBundle.getString(id);
				System.out.println("message: " + message);
			} catch (MissingResourceException ex) {
				ex.printStackTrace();
			}
```


----------

