EJB 3.1 – Charakteristiken

Ich beschäftige mich gerade mit EJBs. Und damit ich das alles verstehe, blog ich halt immer wieder bissle was 🙂

Was ist eigentlich eine EJB? Ich mach es mir einfach und ĂĽbersetz einfach den passenden Teil aus der JSR 318 Abschnitt 2.3.1 Characteristics of Enterprise Beans

Die wesentlichen Teile einer Enterprise-Beans sind:

  • Eine Enterprise-Bean enthält normalerweise Geschäftslogik die auf den Daten des Geschäftes operiert
  • Die Instanzen einer EJB werden zur Laufzeit durch einen Container verwaltet.
  • Eine EJB kann zur Deployment-Zeit verändert werden, indem man ihre Umgebungsvariablen verändert.
  • Verschiedene Serviceinformationen, wie beispielsweise Transaktionen und Sicherheitsattribute, können zusammen mit der Geschäftslogik einer EJB-Klasse anhand von Annotations oder XML-Deployment-Deskriptoren spezifiziert werden. Diese Meta-Informationen können von anderen Werkzeugen während der Anwendungs-Zusammenstellung oder des Deployments genutzt werden.
  • Der Zugriff fĂĽr Clients wird ĂĽber den Container verwaltet in dem die EJBs deployed wurden.
  • Wenn die EJB nur Dienste anbietet die durch die EJB-Spezifikation vorgegeben sind, dann kann diese Bean in jeglichen EJB-kompatiblen Container deployed werden. Speziellere Container können zusätzliche Dienste, die ĂĽber die Spezifikation hinaus gehen, anbieten. Eine EJB die auf solche zusätzlichen Dienste zugreift, kann nur in solche Container deployed werden, die einen solchen Service anbieten.
  • Eine EJB kann in eine zusammengestellte Anwendung eingefĂĽgt werden, ohne das irgendwas am Quellcode geändert werden muss. Auch ein erneutes Kompilieren ist nicht notwendig.
  • Der Bean-Provider definiert die Client-Sicht einer EJB. Dies kann manuell geschehen, oder automatisch durch Anwendungs-Deployment-Werkzeuge. Die Client-Sicht wird weder durch den Container oder den Server beeinflusst in dem die Bean deployed wurde. Somit ist sichergestellt das sowohl die Bean als auch ihre Clients in verschiedene Umgebungen deployed werden können, ohne Ă„nderungen vorzunehmen oder neu zu kompilieren.

Dies ist eigentlich alles selbstverständlich und logisch, aber man muss ja mal klein anfangen 🙂

Java Collection Interface

Java hat ein paar nette Klassen. Und weil ich mir nie merken kann was jetzt der Unterschied zwischen ‚Set‘ und ‚List‘ ist, hier die Erklaerung. Deutsch/Englisch gemischt, zumindest was die Benennung angeht.

  • Collection — Die Wurzel der Collection-Hierarchie. Eine Collection repraesentiert eine Gruppe von Objekten, auch bekannt als seine Elemente. Das Collection Interface ist die gemeinsame Basis aller Unterklassen und wird benutzt um die Collections untereinander kompatibel zu machen. Ausserdem ermoeglich es einen allgemeinen Zugang zu allen Collections. Manche Untertypen erlauben Duplikate, andere nicht. Manche sind sortiert, andere nicht.
  • Set — Eine Collection die keine doppelten Elemente erhalten kann. Am Besten erklaert ist das an einem Pokerblatt, bei dem keine Karte doppelt vorkommt. Ausser jemand schwindelt und betruegt, aber das gehoert hier nicht hin.
  • List — eine sortierte Collection (manchmal Sequenz genannt). Listen koennen Duplikate enthalten. Im Prinzip also eine Menge von Football-Star-Sammelkarten, von denen man auch welche doppelt haben kann. Wer Vector kennt, dem kommt das bekannt vor.
  • Queue — eine Collection die mehrere Elemente beinhalten kann. Uebersetzt ist das eine Warteschlange, was auch die Funktion erklaert. Meistens wird FIFO benutzt (aber nicht zwingenderweise), d.h. das was als erstes reinkommt, kommt auch als erstes wieder raus. Warteschlange am Metzger halt.
  • Map — ein Objekt das eine Schluessel-Wert-Beziehung repraesentiert. Hier sind wieder keine doppelten Eintraege erlaubt. Vergleichbar mit Schluessel-Schloss, jeder Schluessel passt nur in ein Schloss. Gut, mein VW-Schluessel passt auch in den Polo eines bekannten, aber wir sprechen hier nicht von Autos 🙂

Quelle: http://java.sun.com/docs/books/tutorial/collections/interfaces/index.html

UPDATE: Noch eine Entscheidungshilfe als Bild:

Java Collections Entscheidungshilfe
Java Collections Entscheidungshilfe

Java Applets und java.util.logging

So, heute habe ich mich mit der internen Logging-Bibliothek von Java rumgeaergert. Aber fangen wir mal von vorne an. In meinem Praxissemester programmiere ich gerade ein paar Perfomancemessungen in ein Applet ein. Prinzipiell ein simpler Arbeitsgang, aber ich wollte jetzt halt gleich alles ’schoen‘ machen. Nachdem mich ein Freund darauf hingewiesen hat das System.out.println() doch nicht das Wahre ist („fooo, lame, nutz nen Loggingframework. FTW!!!!11einself“), habe ich mich jetzt fuer java.util.logging entschieden. Kann genau das was ich will. Gut, also angefangen:

package foo;
import java.util.logging.*;
public class PerformanceDebug {
	private static Logger logger = Logger.getLogger("foo.PerformanceDebug");
	public PerformanceDebug() {
		Handler handler = new ConsoleHandler();
		handler.setLevel(Level.FINE);
		logger.addHandler(handler);
		logger.setLevel(Level.ALL);
		foobar();
	}
	public void foobar() {
		logger.info("Hello World");
	}
}

Gut. Oder auch nicht, hat naemlich nicht funktioniert. Hat irgendwelche PermissionExceptions geschmissen. Bissle Recherche: Applets laufen in einem beschraenktem Modus, d.h. sie duerfen z.B. nicht irgendwohin schreiben, z.B. mit dem ConsoleHandler. Aber gut, weitere Recherche ergab, dass ich den ConsoleHandler auch weglassen kann, dann schreibt er einfach nach STDOUT, d.h. in die Java Console. Gut.

package foo;
import java.util.logging.*;
public class PerformanceDebug {
	private static Logger logger = Logger.getLogger("foo.PerformanceDebug");
	public PerformanceDebug() {
		logger.setLevel(Level.ALL);
		foobar();
	}
	public void foobar() {
		logger.info("Hello World");
	}
}

Jop, hat erstmal nix gebracht, immer noch Fehlermeldungen (kompilieren tut das uebrigens alles prima). Der ConsoleHandler war gar nicht das einzige Problem, im Applet funktioniert auch Logger.getLogger(„package.class“) nicht. Aber dafuer gibts dann ja Logger.getAnonymousLogger().

package foo;
import java.util.logging.*;
public class PerformanceDebug {
	private static Logger logger = Logger.getAnonymousLogger();
	public PerformanceDebug() {
		logger.setLevel(Level.ALL);
		foobar();
	}
	public void foobar() {
		logger.info("Hello World");
	}
}

Wieder einen Schritt weiter und immer noch nicht am Ziel. Jetzt laeuft es zwar im Applet, aber die Ausgabe ist haesslich (im Sinne von: Ich mag sie nicht :)). Aber dafuer gibts ja java.util.logging.Formatter, damit kann man eigene Formate schreiben. Also flugs eine Subklasse verfasst:

package foo;
import java.util.logging.*;
public class PerformanceDebug {
	private static Logger logger = Logger.getAnonymousLogger();
	public PerformanceDebug() {
		logger.setLevel(Level.ALL);
		foobar();
	}
	public void foobar() {
		logger.info("Hello World");
	}

	public class FooFormatter extends Formatter {

		public String format(LogRecord record) {
			return "Foo:"
				+ record.getMessage()
				+ "\n";
		}
	}
}

Das klappt in jeder Standalone-Applikation und im Applet Viewer, aber im Applet selber gehts wieder nicht. Ein Spass mit den Sicherheitsbeschraenkungen von Applets, da wird das Laden des Formatters einfach unterbunden und eine Exception geschmissen. Also kann ich nicht das machen was ich will. Und Sun hat sich wohl gedacht das man in Applets keine eigenen Formatter braucht. Applets sind eh tot. Genau. Naja, so bringt man auch nen Tag rum, mit wilden Rumprobieren, googlen und fluchen. In diesem Sinne. Feierabend fuer heute.

__FUNCTION__ in Java

Unter PHP gibt es sogenannte Magische Konstanten. Die sind prima, wenn man z.B. eine Debugfunktion schreiben will, die an bestimmten Stellen sagt wo sie aufgerufen wurde. In Java sieht das dann so aus:

class Debug
{
  public static void print(String msg)
  {
    java.lang.Exception e = new java.lang.Exception();
    StackTraceElement ste[] = e.getStackTrace();
    System.out.println(
        new Date().getTime() + " " +
        ste[1].getClassName() + " " +
        ste[1].getMethodName() + " " +
        msg);
  }
}

Wird aufgerufen mit:

import mein.tolles.package.Debug;
Debug.print("lalala");

Was hiermit nicht geht ist: getFileName() und getLineNumber(), da diese Information nicht zur Verfuegung steht.