Java Reference
In-Depth Information
private CounterProvider cp;
public String sayHello(String name)
{
Counter counter = cp.getCounter();
return "Hallo " + name + " (Aufruf Nr. " +
counter.increment() + ")";
}
@PostConstruct
public void init()
{
try
{
Context context = new InitialContext();
cp = (CounterProvider)context.lookup("CounterProvider");
}
catch(NamingException e)
{
}
}
}
Die erste Schwierigkeit mit dieser EJB-Komponente ist, dass der EJB-Container einen Fehler
bei der Installation meldet. Der Grund liegt darin, dass wir in dieser Komponente die
Schnittstelle CounterProvider und die Klasse Counter verwenden, die sich in einer anderen
EJB-Komponente befi nden. Damit die Hello-Komponente erfolgreich übersetzt werden
konnte, mussten natürlich die Counter- und CounterProvider-Klassen in den Klassenpfad
aufgenommen worden sein. Das ist aber eine andere Baustelle. Nun geht es um die Ausfüh-
rung und nicht um die Übersetzung. Und hier ist es wie auch bei anderen Komponentensys-
tem so, dass jede EJB-Komponente ihren eigenen Klassenlader hat, so dass die Klassen aus
einer anderen Komponente im Normalfall nicht verfügbar sind. Dass sich auch hier JBoss 6
wieder anders verhält, soll an dieser Stelle nicht weiter diskutiert werden.
Vielleicht zur Überraschung mancher Leserinnen und Leser hil es hier, wenn wir die
Class-Dateien für die Schnittstelle CounterProvider und die Klasse Counter mit in die EJB-
Jar-Datei der Hello-Komponente aufnehmen. Ähnliche Versuche für andere Komponenten-
systeme in den vorhergehenden Kapiteln führten zu der kuriosen ClassCast-Ausnahme der
Art „X kann man nicht zu X casten“ . Dies ist hier anders. Der Grund liegt in der Art der
Rückgabe des Counter-Objekts durch Call-By-Value: Auf dem Server gibt es ein Counter-
Objekt o1, wobei die Counter-Klasse mit einem Klassenlader K1 geladen wurde. Nicht mög-
lich ist es, dieses Objekt o1 auf eine Counter-Klasse zu casten, die mit einem anderen Klas-
senlader K2 geladen wurde. Aber das passiert hier nicht. Durch Call-By-Value wird ein ganz
neues Objekt o2 als Kopie von o1 erzeugt. Dieses neue Objekt ist ein Objekt der Klasse
Counter, die mit K2 geladen wurde. Das ist überhaupt kein Problem. Dies ist übrigens auch
der Grund, warum wir im vorigen Abschnitt kein Problem in unserem CounterProvider-
Client hatten; auch der Client hat natürlich seinen eigenen Klassenlader, aber das Counter-
Objekt, das der Client verwendet, wird auch auf dem Client erzeugt.
Somit funktioniert diese Anwendung. Sie tut natürlich nicht das, was sie soll. Denn es wird
bei jedem Aufruf „Aufruf Nr. 1“ zurückgegeben, da mit jedem Aufruf von getCounter eine
neue Kopie eines Counter-Objekts entsteht. Vielleicht denken nun einige von Ihnen, dass
man das Problem ganz leicht beheben kann, indem man den Aufruf von getCounter nicht