# Simples eigenes Logfile



## Dagobert (10. Mrz 2010)

Guten Abend,
ich habe mir eine kleine simple Logfile Klasse geschrieben, die 3 Verschiedene Typen unterscheiden kann: Warnung, Error, Message. Desweitern soll sich die Datei um Mitternacht wechseln.
Ich wollte einfach mal nachfragen was ich daran noch verbessern kann, oder ob jemand noch Fehler entdeckt.
Ich habe 2 Klassen:
LogEntry:

```
package Logfile;

import java.util.Calendar;

public class LogEntry {
	
	public static int TYP_ERROR = 0;
	public static int TYP_WARNING = 1;
	public static int TYP_MESSAGE = 2;
	
	private Calendar date;
	private int typ;
	private String text;
	
	public LogEntry(int typ, Calendar datum, String text){
		this.setTyp(typ);
		this.setDatum(datum);
		this.setText(text);
	}
	
	public LogEntry(int typ, String text){
		this.setTyp(typ);
		this.setDatum(Calendar.getInstance());
		this.setText(text);
	}
	
	public void setDatum(Calendar datum){
		this.date = datum;
	}
	
	public Calendar getDatum(){
		return this.date;
	}
	
	public void setTyp(int typ){
		this.typ = typ;
	}
	
	public int getTyp(){
		return this.typ;
	}
	
	public String getTypToString(){
		switch(typ){
		case 0: return "TYP_ERROR";
		case 1: return "TYP_WARNING";
		case 2: return "TYP_MESSAGE";
		default: return null;
		}
	}
		
	public void setText(String text){
		this.text = text;
	}
	
	public String getText(){
		return this.text;
	}
}
```

LogFile:

```
package Logfile;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;

import javax.swing.Timer;

import Datum.Datumsfunktion;
/**
 * * Speichert Logeinträge in einer Datei, die jeweils um Mitternacht wechselt
 * @author Dagobert
 * @since 20.02.2010
 * @version 1.0
 */
public class LogFile implements ActionListener {

	private String path;					// Pfad wo die Log-Dateien abgelegt werden

	private Calendar date;					// Datum für die Log-Datei
	private SimpleDateFormat timeFormater = new SimpleDateFormat("HH:mm:ss", Locale.GERMAN);
	private SimpleDateFormat dateFormater = new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN);

	private ArrayList<LogEntry> entries;	// Speicher für die Einträge
	private PropertyChangeSupport changes;	// abonnenten für änderungen

	private BufferedWriter bw;
	private Timer changeTimer;				// Timer zum wechseln der Datei um mitternacht

	public LogFile(String pfad) {			
		entries = new ArrayList<LogEntry>();
		changes = new PropertyChangeSupport(this);
		changeTimer = new Timer(1000, this);
		date = Calendar.getInstance();
		setPfad(pfad);
		createNewFile();
		restartLogfileChange();
	}
	
	/**
	 * Erstellt ein Erroreintrag in der Logdatei
	 * @param error Nachricht des Eintrages
	 */
	public void error(String error) {
		changes.firePropertyChange("logentry", getAnzahl(), getAnzahl() + 1);
		LogEntry e = new LogEntry(LogEntry.TYP_ERROR, error);
		entries.add(e);
		writeLastLogentry();
	}

	/**
	 * Erstellt eine Warnungseintrag in der Logdatei
	 * @param warning, Nachricht des eintrages
	 */
	public void warning(String warning) {
		changes.firePropertyChange("logentry", getAnzahl(), getAnzahl() + 1);
		LogEntry e = new LogEntry(LogEntry.TYP_WARNING, warning);
		entries.add(e);
		writeLastLogentry();
	}

	/**
	 * Erstellt eine Nachricht in der Logdatei
	 * @param message Nachricht der Logdatei
	 */
	public void message(String message) {
		changes.firePropertyChange("logentry", getAnzahl(), getAnzahl() + 1);
		LogEntry e = new LogEntry(LogEntry.TYP_MESSAGE, message);
		entries.add(e);
		writeLastLogentry();
	}

	/**
	 * Setzt den Pfad der Logdateien
	 * @param pfad pfad der Logdatei
	 */
	public void setPfad(String pfad) {
		this.path = pfad;
	}
	
	/**
	 * 
	 * @return Pfad der Logdatei
	 */
	public String getPfad() {
		return this.path;
	}

	/**
	 * 
	 * @return Anzahl der Logeinträge im Logfile
	 */
	public int getAnzahl() {
		return entries.size();
	}
	
	/**
	 * 
	 * @return Datum des Logfiles
	 */
	public Calendar getDate(){
		return this.date;
	}

	public void addPropertyChangeListener(PropertyChangeListener l) {
		changes.addPropertyChangeListener(l);
	}

	public void removePropertyChangeListener(PropertyChangeListener l) {
		changes.removePropertyChangeListener(l);
	}

	private void createNewFile() {
		File f = new File(path + "Log_" + Datumsfunktion.getCurrentDate() + ".log");
		boolean exists = f.exists();
		try {
			FileWriter fw = new FileWriter(f, true);
			bw = new BufferedWriter(fw);
			if (!exists) {
				bw.write(Datumsfunktion.getCurrentDate());
				bw.newLine();
				bw.flush();
			} else {
				loadFile(f);
			}
		} catch (IOException e) {
			e.printStackTrace();

		}
	}

	private void loadFile(File f) {
		try {
			FileReader fr = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			date = Datumsfunktion.stringToDate(br.readLine().split(" ")[1], "dd.MM.yyyy");
			String line = br.readLine();
			while (line != null) {
				entries.add(parseToEntry(line));
				line = br.readLine();
			}
			br.readLine();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private LogEntry parseToEntry(String stringEntry) {
		String[] dataString = stringEntry.split(";");
		Calendar date = Datumsfunktion.stringToDate(dataString[0], "dd.MM.yyyy HH:mm:ss");

		String typString = dataString[1].split(" ")[2];
		int typ;
		if (typString.equals("TYP_ERROR")) {
			typ = LogEntry.TYP_ERROR;
		} else if (typString.equals("TYP_WARNING")) {
			typ = LogEntry.TYP_WARNING;
		} else {
			typ = LogEntry.TYP_MESSAGE;
		}

		String message = dataString[2].substring(1);

		LogEntry e = new LogEntry(typ, date, message);
		return e;
	}

	private void writeLastLogentry() {
		if (bw != null) {
			try {
				LogEntry e = entries.get(entries.size() - 1);
				String s = dateFormater.format(e.getDatum().getTime()) + " " + timeFormater.format(e.getDatum().getTime()) + "; Typ: " + e.getTypToString() + " ->; " + e.getText();
				bw.write(s);
				bw.newLine();
				bw.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private void restartLogfileChange() {
		Calendar current, next;
		current = Calendar.getInstance();
		next = Calendar.getInstance();
		next.set(current.get(Calendar.YEAR), current.get(Calendar.MONTH), current.get(Calendar.DAY_OF_MONTH) + 1 ,0, 0, 0);
		changeTimer.setInitialDelay((int) (next.getTimeInMillis() - current.getTimeInMillis()));
		changeTimer.restart();
	}

	private void closeLogfile(){
		try {
			bw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent evt) {
		try {
			restartLogfileChange();
			message("! ! ! Logfile ende ! ! !");
			bw.close();
			createNewFile();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
```

Eine Beispielausgabe wäre dann z.B. die Log_10.03.2010.log:

```
10.03.2010
10.03.2010 18:49:34; Typ: TYP_ERROR ->; Es konnte keine Verbindung mit der Datenbank GELDTRANSPORTER hergestellt werden
```

Diese Datei soll später wieder in einer Liste aufbereitet werden mit Bild, Zeitpunkt, und Nachricht.
Was könnte ich noch verbessern?


mfg. Dagobert


----------



## SlaterB (10. Mrz 2010)

immer eine einfache Regel: keinen Code doppelt schreiben,
die Methoden error, warning und message könnten alle eine dritte interne Methode aufrufen, nur mit unterschiedlichen LogType (dafür bietet sich übrigens eine Enum an),
in der neuen Methode dann den Code nur EINMAL, die 3 Aufrufer-Methoden quasi leer

und sollte
> changes.firePropertyChange
nicht erst NACH dem Einfügen des neuen Entries ausgeführt werden? 
sonst bekommt jemand das Event, schaut nach und der neue Entry ist noch gar nicht da


----------



## eRaaaa (10. Mrz 2010)

Dagobert hat gesagt.:


> Was könnte ich noch verbessern?



Mhm, hab eher so die ein oder andere Frage/Anmerkung 

- generell könnte oder sollte man die streams am Ende schließen ...  --> siehe next
- du hast ja closeLogfile() extra angelegt, rufst du nur nirgends auf 
- Bei TYP_ERROR usw. könnte man sich vllt überlegen enum zu benutzen? Oder aber es hat auch einen Grund dass die nicht final sind?!


----------



## Landei (10. Mrz 2010)

Java hat doch inzwischen java.util.logging, das ist zwar nicht so hübsch wie log4j, aber für den Hausgebrauch reichts allemal. Warum das Rad nochmal erfinden?


----------



## Gast2 (10. Mrz 2010)

Dagobert hat gesagt.:


> ich habe mir eine kleine simple Logfile Klasse geschrieben, die 3 Verschiedene Typen unterscheiden kann: Warnung, Error, Message. Desweitern soll sich die Datei um Mitternacht wechseln.


wenn es nur eine Übung ist , dann nachfolgendes überspringen ... schauen die mal log4j an ... da hast Du schon alles mit dabei



> ```
> 10.03.2010 18:49:34; Typ: TYP_ERROR ->; Es konnte keine Verbindung mit der Datenbank GELDTRANSPORTER hergestellt werden
> ```
> Diese Datei soll später wieder in einer Liste aufbereitet werden mit Bild, Zeitpunkt, und Nachricht.


dann kannst Du zwischen Datum/Uhrzeit/etc ein TAB packen ... dann lässt sich das leichter Splitten ... alternative kannst Du auch zwischen Zeit & Co sowie Meldung ein TAB packen ... dann kannst Du erst am TAB trennen und den Rest dann an den Leerzeichen ... jedenfalls brauchst dazu ein eindeutiges Format - damit Du es eben splitten kannst



> Was könnte ich noch verbessern?



Thread-ID und/oder Thread-Name wären noch super
Millisekunden hätten auch was - wenn Du schnell Meldungen raus gibst
Du hast nur 3 Meldungstypen ... die kannst Du in der Zeile das durch E/W/M ersetzen (alternativ ERR/WARN/MSG oder so)
eine Überladung der Error-Meldung für eine Exception wäre sehr brauchbar 
	
	
	
	





```
public void error(Exception ex) { error(ex.getMessage()); }
```

außerdem kannst Du die Meldung die Du ins File schreibst auch zusätzlich noch auf der Console (syso) ausgeben ... dann siehst Du auch wärend der Entwicklung was passiert und brauchst nicht immer die Log-Datei zu öffnen

das Wichtigste ... Du musst Synchronisieren!! ... bei Dir schreibt er willkürlich Daten wenn Du mit mehr als einem Thread arbeitest ... wenn Du den Vorschlag von SlaterB (eine Methode zum schreiben) umsetze, kannst Du die Synchronisation gleich dort machen




eRaaaa hat gesagt.:


> - generell könnte oder sollte man die streams am Ende schließen ...  --> siehe next


das kommt auf die entsprechende Menge der zu schreibenden Daten an ... wenn es eher viele sind (wie bei mir manchmal) ist es besser das die Datei permanent offen ist



Landei hat gesagt.:


> Warum das Rad nochmal erfinden?


weil sonst irgendwann keiner mehr weis wie Räder hergestellt werden ... dann muss es mühsam erneut erfunden werden


----------



## SlaterB (10. Mrz 2010)

mogel hat gesagt.:


> ... wenn Du den Vorschlag von eRaaa (eine Methode zum schreiben) umsetzt


buuh, Ideengeber-Verdreher


----------



## Gast2 (10. Mrz 2010)

SlaterB hat gesagt.:


> buuh, Ideengeber-Verdreher



verdammt - werde ich gleich korregieren


----------



## Gast2 (10. Mrz 2010)

*auch nochmal auf log4j und java.util.logging hinweis*

Ansonsten wäre auch noch der Klassenname interessant


----------



## eRaaaa (10. Mrz 2010)

mogel hat gesagt.:


> das kommt auf die entsprechende Menge der zu schreibenden Daten an ... wenn es eher viele sind (wie bei mir manchmal) ist es besser das die Datei permanent offen ist



Klar, aber dennoch würdest du doch sicherlich irgendwann mal close() aufrufen oder etwa nicht? Spätestens dann, wenn eh eine neue LogDatei erstellt wird....Ich hab allerdings in der actionPerformed den Aufruf übersehen, hatte nur nach seiner eigen, angelegten Methode gesucht und die wird halt nirgends aufgerufen (wo da halt auch die Frage entstand: wofür ist sie dann) und da die auch private ist, hätte auch der Benutzer der Klasse keine Möglichkeit gehabt per Hand selbst irgendwann zu schließen. Und das hätte ich dann für nicht so toll empfunden
--> korrigiere mich


----------



## Dagobert (10. Mrz 2010)

=) cool =)
danke für die vielen Anregungen. Ich habe schon angefangen ein par einzuarbeiten. Jedoch scheitert es bei mir gerade an den Enum's. Könnte mir wer nen guten Beispiellink posten?, denn Sun & die Insel hat mir nicht viel weiter gebracht.

Ich habe bis jetzt

```
public class LogEntry {
		
	public enum LogfileTyps{
		ERROR, WARNING, MESSAGE;
	}
. . . . . .  . . . . . . . . .
        private LogfileTyps typ;
. . . . . . . . . . . . . . . 
}
```

Wie würde denn jetzt die Passende set&get-Methode aus?
und um das ganze Threadsicher zu machen, würde es reichen die schreibmethoden syncronized zu machen?

mfg. Dagobert


----------



## SlaterB (10. Mrz 2010)

> Wie würde denn jetzt die Passende set&get-Methode aus?

wo set und get? in LogEntry nicht anders als zuvor mit int

public LogfileTyps getTyp()
statt
public int getTyp()
usw


----------



## tuxedo (11. Mrz 2010)

*Auf Simple Logging Facade 4 Java hinweis*

Das ist extrem einfach zu benutzen und man kann drunterschnallen was man will. log4j, java.utils.logging, eine eigene Log-Klasse, ... Und man kann das später sogar wieder austauschen ohne den Code nochmal zu ändern...

- Alex


----------



## Dagobert (11. Mrz 2010)

Guten Tag,
so ich hab mich mal hingesetzt und haben den größten Teil eurer Vorschläge mal eingearbeitet und nochmal 2-3 Methoden ergänzt.
Ich habe vorher schonmal was von den Logfile-Projekt gehört, aber ich wollte was eigenes machen 1. zur Übung 2. kp 
So herraus gekommen sind nun diese beiden Klassen:
LogEntry:

```
package Logfile;

import java.util.Calendar;

public class LogEntry {
		
	public enum LogfileTyps{
		ERROR, WARNING, MESSAGE;
	}
	
	private Calendar date;
	private LogfileTyps typ;
	private String text;
	
	public LogEntry(LogfileTyps typ, Calendar datum, String text){
		this.setTyp(typ);
		this.setDatum(datum);
		this.setText(text);
	}
	
	public LogEntry(LogfileTyps typ, String text){
		this.setTyp(typ);
		this.setDatum(Calendar.getInstance());
		this.setText(text);
	}
	
	public void setDatum(Calendar datum){
		this.date = datum;
	}
	
	public Calendar getDate(){
		return this.date;
	}
	
	public void setTyp(LogfileTyps typ){
		this.typ = typ;
	}
	
	public LogfileTyps getTyp(){
		return this.typ;
	}
	
	public String getTypToString(){
		return typ.name();
	}
		
	public void setText(String text){
		this.text = text;
	}
	
	public String getText(){
		return this.text;
	}
}
```

Logfile:

```
package Logfile;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;

import javax.swing.Timer;

import Datum.Datumsfunktion;
import Logfile.LogEntry.LogfileTyps;
/**
 * Speichert Logeinträge in einer Datei, die jeweils um Mitternacht wechselt
 * @author Dagobert
 * @since 20.02.2010
 * @version 1.0
 */
public class Logfile implements ActionListener {
	
	static final long serialVersionUID = 391847145653624532L; //Wofür die ID gut ist weiß ich nur grob, (serializierung?), deswegen hab ich einfach mal selbst ne Zahlenkombi dahingemacht
	
	private String path;					// Pfad wo die Log-Dateien abgelegt werden

	private Calendar date;					// Datum für die Log-Datei
	private final SimpleDateFormat timeFormater = new SimpleDateFormat("HH:mm:ss", Locale.GERMAN);
	private final SimpleDateFormat dateFormater = new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN);

	private ArrayList<LogEntry> entries;	// Speicher für die Einträge
	private PropertyChangeSupport changes;	// abonnenten für änderungen

	private BufferedWriter bw;
	private Timer changeTimer;				// Timer zum wechseln der Datei um mitternacht

	public Logfile(String pfad) {			
		entries = new ArrayList<LogEntry>();
		changes = new PropertyChangeSupport(this);
		changeTimer = new Timer(1000, this);
		date = Calendar.getInstance();
		setPfad(pfad);
		createNewFile();
		restartLogfileChange();
	}
	
	/**
	 * Erstellt ein Eintrag in der Logdatei
	 * @param typ Typ der Nachricht
	 * @param text EIgentliche Nachricht des Eintrages
	 */
	public synchronized void insert(LogfileTyps typ, String text) {
		LogEntry e = new LogEntry(typ, text);
		entries.add(e);
		writeLastLogentry();
		changes.firePropertyChange("logentry", size()-1, size()); 
	}

	/**
	 * Speichert den Fehlertext einer Exception in der Logdatei
	 * @param ex Exception für den Text in der Logdatei
	 */
	public synchronized void error(Exception ex){
		insert(LogfileTyps.ERROR, ex.getMessage());
	}
	
	/**
	 * @return gibt den letzte (aktuellste) Logeintrag zurück 
	 */
	public LogEntry lastEntry(){
		return entries.get(entries.size());
	}
	
	public LogEntry getEntry(int pos){
		return entries.get(pos);
	}
	
	/**
	 * Setzt den Pfad der Logdateien
	 * @param pfad pfad der Logdatei
	 */
	public void setPfad(String pfad) {
		this.path = pfad;
	}
	
	/** 
	 * @return Pfad der Logdatei
	 */
	public String getPfad() {
		return this.path;
	}

	/**
	 * @return Anzahl der Logeinträge im Logfile
	 */
	public int size() {
		return entries.size();
	}
	
	/**
	 * @return Datum des Logfiles
	 */
	public Calendar getDate(){
		return this.date;
	}

	public void addPropertyChangeListener(PropertyChangeListener l) {
		changes.addPropertyChangeListener(l);
	}

	public void removePropertyChangeListener(PropertyChangeListener l) {
		changes.removePropertyChangeListener(l);
	}

	private void createNewFile() {
		File f = new File(path + "Log_" + Datumsfunktion.getCurrentDate() + ".log");
		boolean exists = f.exists();
		try {
			FileWriter fw = new FileWriter(f, true);
			bw = new BufferedWriter(fw);
			if (!exists) {
				bw.write(Datumsfunktion.getCurrentDate());
				bw.newLine();
				bw.flush();
			} else {
				loadFile(f);
			}
		} catch (IOException e) {
			e.printStackTrace();

		}
	}

	private void loadFile(File f) {
		try {
			FileReader fr = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			date = Datumsfunktion.stringToDate(br.readLine(), "dd.MM.yyyy");
			String line = br.readLine();
			while (line != null) {
				entries.add(parseToEntry(line));
				line = br.readLine();
			}
			br.readLine();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private LogEntry parseToEntry(String stringEntry) {
		String[] dataString = stringEntry.split("\t");
		Calendar date = Datumsfunktion.stringToDate(dataString[0], "dd.MM.yyyy HH:mm:ss");

		String typString = dataString[1].split(" ")[1];
		LogfileTyps typ = LogfileTyps.valueOf(typString);

		String message = dataString[3];
		
		LogEntry e = new LogEntry(typ, date, message);
		return e;
	}

	private void writeLastLogentry() {
		if (bw != null) {
			try {
				LogEntry e = entries.get(entries.size() - 1);
				String s = dateFormater.format(e.getDate().getTime()) + " " + timeFormater.format(e.getDate().getTime()) + "\tTyp: " + e.getTypToString() + "\t->\t" + e.getText();
				bw.write(s);
				bw.newLine();
				bw.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private void restartLogfileChange() {
		Calendar current, next;
		current = Calendar.getInstance();
		next = Calendar.getInstance();
		next.set(current.get(Calendar.YEAR), current.get(Calendar.MONTH), current.get(Calendar.DAY_OF_MONTH) + 1 ,0, 0, 0);
		changeTimer.setInitialDelay((int) (next.getTimeInMillis() - current.getTimeInMillis()));
		changeTimer.restart();
	}
	
	@Override
	public void actionPerformed(ActionEvent evt) {
		try {
			restartLogfileChange();
			insert(LogfileTyps.MESSAGE, "! ! ! Logfile ende ! ! !");
			bw.close();
			createNewFile();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
```

Anregungen und Kritik sind wieder erwünscht 

mfg. Dagobert


----------



## SlaterB (11. Mrz 2010)

Methoden wie
> public void warning(String warning) 
gibts jetzt nicht mehr?

könntest du ruhig wieder ergänzen, wenn jeder Aufrufer den LogType importieren und angeben muss ist das doch recht aufwendig,
da schadet dann eine Abkürzungs-Methode wie 
> public void warning(String warning) 
nicht, 
nur sollte diese Methode dann eben insert() aufrufen, das meinte ich in meinem Post


----------



## Dagobert (11. Mrz 2010)

okay das wird dann nachher wieder nachgeholt


----------



## Dagobert (11. Mrz 2010)

So auch wenns jetzt nicht ganz zum Thema passt, ich hab nen Problem wo ich seit 2 std. einfach nicht weiter komme 
Ich möchte ein Image in einer Tabelle darstellen. Wie stelle ich das an?

ich habe ein eigenes TableModel.
So jetzt habe ich in diesem Model:

```
@Override
	public Object getValueAt(int col, int row) {
		LogEntry entry = logfile.getEntry(col);
		switch(row){
			case 0: return im.getScaledIcon(entry.getTyp().name(), 25, 25);
			case 1: return Datumsfunktion.dateToString(entry.getDate(), "dd.MM HH:mm:ss");
			case 2: return entry.getText();
			default: return null;
		}
	}
```
weobei getScaledIcon ein ImageIcon zurückgibt.
dann habe ich noch:

```
public Class getColumnClass(int columnIndex) {
		switch (columnIndex) {
		case 0:
			return ImageIcon.class;
		case 1:
			return String.class;
		default:
			return String.class;
		}
	}
```

Warum bekomme ich eine NullPointerException? 

mfg. Dagobert


----------



## tuxedo (12. Mrz 2010)

Weil ein Objekt das du nuttzen willst null ist?! Schau doch in den Stracktrace der Exception. Das verrät alles. Zur Not nen Debugger benutzen und durchsteppen. Spätestens dann müsste dir ein Licht aufgehen ;-)

Nebenbei: Das ist ne ziemlich krasse Themenabweichung. Normalerweise behandelt man unterschiedliche Probleme in unterschiedlichen Threads...


----------



## tuxedo (12. Mrz 2010)

*doppelpost, sorry*


----------



## Dagobert (12. Mrz 2010)

ahhh ein dreher in nem String  shit happens ^^
ich weiß das das ne Krasse abweichung war, aber war gerade echt ein Problem ohne deren Lösung ich nicht weiterkam 
den passenden viewer gibs dann im laufe des Wochenendes denke ich mal 

mfg. Dagobert


----------

