Apache Avalon

Die Nebel von Avalon

Carsten Ziegeler

Die aktuelle Softwareentwicklung ist sehr stark durch Komponenten geprägt und es existieren auch viele Open Source-Bausteine, die direkt als Bausteine verwendet werden können. Hierfür werden einheitliche Bedingungen benötigt, damit allgemeine Komponenten entwickelt und eingesetzt werden können. Das Apache Open Source-Projekt Avalon bietet Ihnen ein Java-Framework zur einheitlichen Entwicklung und Nutzung von Komponenten. Dieser Artikel stellt das Framework vor und zeigt, wie Sie es bei der eigenen Softwareentwicklung erfolgreich einsetzen können.

Versunken in der Entwicklung Ihrer neuesten Software, tauchen plötzlich Fragmente aus der Vergangenheit auf. Doch: Bei dem alten Projekt hatten Sie eine XML-Konfigurationsdatei für einen bestimmten Softwarebaustein – nun haben Sie eine SQL-Datenbank. Wie können Sie diese Komponenten in Ihrem neuen Projekt einsetzen? Sie haben zwei Möglichkeiten: Entweder die Komponente entsprechend anpassen oder sie ganz neu schreiben. Unabhängig davon, für welche Methode Sie sich entscheiden, erhalten Sie zwei verschiedene Versionen der gleichen Komponente, die sich lediglich durch ihre Konfigurationsart unterscheiden. Mit Avalon als integralem Bestandteil Ihrer Anwendung kann dieses Problem nicht mehr auftreten.

Avalon kommt natürlich ebenfalls in Betracht, wenn Sie einen Rahmen für Ihre Komponentenverwaltung benötigen. Komponenten sind mittlerweile ein etabliertes Softwareentwicklungsmodell, sie haben eine hohe Akzeptanz, da mit Hilfe von Komponenten verschiedene allgemeine Probleme bei der Softwareentwicklung gelöst werden können: Durch Komponenten wird die Struktur einer Anwendung leichter und schneller verständlich. Es ist möglich, einzelne Teile der Anwendung zu aktualisieren, ohne Seiteneffekte zu erzeugen. Anwendungen lassen sich schneller entwickeln, da bestehende Komponenten aus anderen Projekten wiederverwendet und unverändert eingesetzt werden können.

Das Apache Avalon-Projekt [1] besteht aus mehreren Unterprojekten. In diesem Artikel werden wir drei davon betrachten: das Avalon LogKit, das eigentliche Avalon Framework und Avalon Excalibur. Das Avalon LogKit ist ein schnelles und flexibles Logging-API. Avalon verwendet durchgehend das LogKit zum Loggen. Das Avalon Framework pictureet die eigentliche Basis. Es definiert verschiedene Konzepte und Schnittstellen zur Komponentenentwicklung. Darauf aufbauend implementiert das Avalon Excalibur-Unterprojekt die verschiedenen Konzepte und bietet somit einen Rahmen für eigene Anwendungen. Darüber hinaus bietet Excalibur nützliche Komponenten, die in eigenen Anwendungen verwendet werden können.

Avalon und auch das LogKit liegen in ihrer jetzigen Form seit über einem Jahr vor: Die aktuellen Versionen sind Avalon LogKit 1.1, Avalon Framework 4.1.3 und Avalon Excalibur 4.1. Mittlerweile hat sich der Komponentengedanke auch bei wichtigen Open Source-Projekten durchgesetzt. So basieren beispielsweise Apache Cocoon oder Apache James auf Avalon. Weitere große Projekte wie beispielsweise FOP oder Turbine folgen ebenfalls diesem Vorpicture. Sobald man sich mit Open Source-Projekten beschäftigt, stößt man früher oder später auch auf Avalon. Im Folgenden werden wir die Grundkonzepte von Avalon betrachten, und im Anschluss daran entwickeln wir zur Verdeutlichung eine Anwendung auf Basis von Avalon.

Vom Container zur Komponente

Bevor wir uns in die Nebel von Avalon wagen, sollten wir einige allgemeine Dinge beleuchten (Eine Ausführliche Darstellung der Prinzipien Komponenten-basierter Architekturen finden Sie auf Seite XX). Jedes komponentenbasierte System benötigt die Konzepte des Clients, eines Containers, eines Suchmechanismus‘ und natürlich einer Komponente. Der Client ist im Normalfall die Anwendung, aber er könnte ebenso eine kleinere Einheit innerhalb der Anwendung sein, wie beispielsweise eine andere Komponente. Wenn ein Client Komponenten verwendet, benötigt er einen Mechanismus, um eine bestimmte Komponente suchen zu können. Diese Aufgabe übernimmt der sogenannte (Komponenten-)Container. Er verwaltet alle im System verfügbaren Komponenten. Wenn der Client beispielsweise einen Parser benötigt, fragt er den Container nach einer Komponente, die diese Funktion ausführen könnte. Der Container überprüft seine vorhandenen Komponenten und gibt im Erfolgsfall einen Parser an die Anwendung zurück.

Eine Komponente besteht aus zwei Bestandteilen: Ihrem Interface und der zugehörigen Implementierung. Das Interface beschreibt den Typ der Komponente und wie sie verwendet werden kann; die Implementierung setzt dieses Interface um. Wenn eine Komponente eingesetzt wird, ist es unerheblich, wie die Implementierung aussieht. Allein das Interface legt die Schnittstelle fest, auf die eine Anwendung zugreifen darf. Diese Schnittstelle wird in Avalon als Rolle der Komponente definiert, sie ist in der Regel der komplette Klassenname des Interfaces. Um beispielsweise den XML-Parser von Excalibur zu erhalten, wird der Container nach einer Komponente für die Rolle org.apache.avalon.excalibur.xml.Parser gefragt. Nur der Container kennt die Implementierung, die hinter dieser Rolle bzw. diesem Interface steht. Hierdurch ist die Anwendung unabhängig von der tatsächlich verwendeten Implementierung. Wird eine andere (bessere) Implementierung benötigt, kann zwischen der alten und der neuen Variante gewählt werden, ohne die Anwendung umzuschreiben. Durch dieses Late-Binding der Komponenten wird erst zur Laufzeit festgelegt, welche Implementierung verwendet werden soll – es ist sogar möglich, die Anwendung derart zu entwickeln, dass ein Umkonfigurieren zur Laufzeit möglich ist.

In Avalon wird der Container durch ein Java Interface, dem ComponentManager beschrieben:

package org.apache.avalon.framework.component;

public interface ComponentManager {
Component lookup(String role) throws ComponentException;
void release(Component component);
boolean hasComponent(String role);
}

Über die Methode lookup kann eine Komponente für eine entsprechende Rolle abgeholt werden. Wichtig ist, diese Komponente auf jeden Fall wieder freizugeben (Methode release), wenn sie nicht mehr benötigt wird. Aus Sicherheitsgründen lässt sich bei Avalon über den ComponentManager nicht abfragen, welche Rollen innerhalb der Anwendung verfügbar sind. Diese Information kann aus der entsprechenden Konfiguration für den ComponentManager herausgelesen werden, hierzu später mehr.

Über den ComponentManager erhält man zunächst eine Komponente bzw. ein Objekt vom Typ Component. Somit muss jede Komponente org.apache.avalon.framework.component.Component annehmen. Dieses Interface ist ein reines Marker-Interface, d.h. es definiert keine Methoden, sondern kennzeichnet ein Objekt lediglich als Avalon-Komponente. Nachdem der ComponentManager die Komponente geliefert hat, muss sie noch entsprechend gecastet werden, damit der Client diese Komponente auch richtig verwenden kann:

import org.apache.avalon.excalibur.xml.Parser;

public void useParser(ComponentManager manager) {
Parser parser = null;
try {
parser = (Parser)manager.lookup( Parser.ROLE );

// Use Parser here

} finally {
manager.release( parser );
}
}

In dem obigen Beispiel wird eine Parser-Komponente vom ComponentManager abgeholt und entsprechend verwendet. Da der Rollenname einer Komponente gleich dem kompletten Klassennamen des Interfaces ist, ist es bei Avalon Standard, dass jede Rolle eine Konstante role definiert, die den Rollennamen beinhaltet. Dadurch werden Tippfehler bei der Verwendung der langen Rollennamen vermieden.

Das Verwenden einer Komponente besteht somit immer aus den folgenden Schritten: Zuerst wird die Komponente über einen ComponentManager bezogen, hiernach gecastet und verwendet und auf jeden Fall abschließend wieder über den ComponentManager freigegeben. Danach darf die Komponente nicht mehr verwendet werden. Mit Avalon ist das Entwickeln des Clients immer so einfach wie gerade beschrieben. Steigen wir nun tiefer in die Komponentenentwicklung mit Avalon ein.

Inversion of Control und Separation of Concerns

Avalon verwendet zwei zentrale Konzepte: Inversion of Control (IoC) und Separation of Concerns (SoC). Im Gegensatz zu anderen Containern wie beispielsweise Enterprise Java Beans (EJB) werden bei Avalon die Komponenten durch den Container gesteuert: Der Container ist für die Erstellung einer Komponente, für deren Initialisierung und Konfiguration und letztendlich auch für das Entfernen einer Komponente zuständig. Dabei erfolgt der Fluss der verschiedenen Informationen vom Container zur Komponente. Der Container ruft unter Umständen verschiedene Methoden einer Komponente auf, um ihr beispielsweise eine Konfiguration zu übergeben. Dieser umgekehrte Aufruf wird Inversion of Control genannt. Das Objekt, das die Komponente erstellt hat, ist auch für die anderen Aspekte wie z. B. Konfiguration zuständig.

Bei der Verwaltung von Komponenten gibt es verschiedene Bereiche, unter anderem gibt es Komponenten, die gerne ihre Tätigkeiten protokollieren möchten (Logging), die eine Konfiguration benötigen oder die nach durchgeführter Arbeit aufräumen müssen. Durch das zweite wichtige Konzept, Separation of Concerns, bietet Avalon die Möglichkeit, dass sich Komponenten nur dann mit einem dieser Bereiche befassen müssen, wenn es für diese Komponente relevant ist. Benötigt eine Komponente etwa keine Konfiguration, muss sie sich nicht mit diesem Aspekt beschäftigen.

Avalon realisiert diese Trennung durch verschiedene sogenannte Marker-Interfaces. Interessiert sich eine Komponente für einen Bereich, so implementiert sie das zugehörige Interface. Beispielsweise bietet Avalon das Configurable Interface. Eine Komponente, die dieses Interface annimmt, ist konfigurierbar und erhält folglich vom Container die Konfigurationsinformationen. Genaueres zu der Funktionsweise werden wir später im Artikel behandeln. Insbesondere durch diese Trennung zeigt sich ein erheblicher Vorteil von Avalon zu anderen Komponenten-Frameworks: Benötigt man keine Konfiguration, wird das Interface nicht angenommen und es muss auch keine Methode implementiert werden. Bei anderen Frameworks ist eine solche Methode häufig Bestandteil des Komponenteninterfaces, das von jeder Komponente implementiert werden muss. Abhilfe wird hier oft mit abstrakten Basisklassen geschaffen, die leere Implementierungen für alle Methoden bereithalten. Mit Avalon findet eine klarere Trennung statt, und dieser Aufwand ist nicht notwendig.

Generell lassen sich drei verschiedene Phasen bei der Verwendung von Komponenten unterscheiden: Das Erstellen einer Komponente, die Benutzungsphase und das Entfernen der Komponente. Betrachten wir nun die verschiedenen Möglichkeiten von Avalon in diesen einzelnen Phasen.

Die Erstellungsphase

Wenn eine Komponente das erste Mal vom Container geliefert werden soll, muss diese Komponente erstellt und initialisiert werden. Zuerst ruft Avalon den Konstruktor (ohne Argumente) der zugehörigen Java-Klasse auf. Danach testet Avalon, welche Bereiche (Concerns) für die Komponente relevant sind.

Nach der Erstellung des Objektes prüft der ComponentManager als erstes, ob die Komponente über das Avalon LogKit loggen möchte. Eine Komponete erklärt dieses durch Annehmen des Interfaces LogEnabled:

package org.apache.avalon.framework.logger;


public interface LogEnabled {

void enabledLogging( Logger logger );
}

Wenn eine Komponente dieses Interface implementiert, bekommt sie in der Erstellungsphase ein Objekt vom Typ Logger. Über dieses Objekt können Meldungen in verschiedene Level (von Debug bis fataler Fehler) ausgegeben werden. Das Logger Objekt verwendet das Avalon LogKit, das sich flexibel konfigurieren lässt. Beispielsweise können für eine Komponente unterschiedliche Ziele angeben werden: Datei, Datenbank oder Email. Diese Ziele lassen sich bei Bedarf erweitern. Über eine zentrale Konfigurationsdatei werden die verschiedenen Ziele definiert. Darüber hinaus bietet Avalon die Möglichkeit, dass Komponenten in unterschiedliche Ziele (oder besser: Kategorien) loggen. Mehr zum Thema LogKit finden Sie in der Dokumentation. Natürlich muss nicht das Avalon LogKit zum Loggen verwendet werden – auch Log4j oder das Logging-API des JDK 1.4 können problemlos eingesetzt werden. Der Vorteil beim LogKit liegt darin, dass der ComponentManager dieses schon direkt unterstützt.

Für die Komponentenentwicklung ist es wichtig, dass die Komponente zuerst eine Möglichkeit zum Loggen bekommt. Falls im weiteren Verlauf der Erstellungsphase ein Fehler auftritt, kann dies gleich entsprechend vermerkt werden.

Nach LogEnabled wird die Komponente auf Contextualizable überprüft:

package org.apache.avalon.framework.context;


public interface Contextualizable {

void contextualize( Context context ) throws ContextException;
}


public interface Context {

Object get( Object key ) throws ContextException;
}

Wenn eine Komponente dieses Interface implementiert, bekommt sie einmalig ein Objekt vom Typ Context übergeben. Dieses Objekt kann von der jeweiligen Anwendung erstellt werden. Somit kann die Anwendung beliebige (Context-)Informationen an jede Komponente weiterreichen.

Benötigt eine Komponente wiederum Zugriff auf andere Komponenten, benötigt sie einen ComponentManager. Über das Composable Interface kann die Komponente diesen erhalten:

proxyhost
...

...

Diese Konfiguration kann über entsprechende Methoden (analog zu DOM) abgefragt werden. Woher diese Informationen kommen – aus einer Datei oder aus einer Datenbank – spielt für die Komponente keine Rolle. Es ist Aufgabe des ComponentManagers, die richtige Konfiguration für eine Komponente zu verwenden.

Die Alternative zu Configurable ist Parameterizable mit der Methode parameterize:

Über ein Objekt vom Typ Parameters können die verschiedenen Werte in unterschiedlichen Formaten (Boolean, Long, String etc.) abgefragt werden. Wichtig ist, dass eine Komponente entweder Configurable oder Parameterizable implementiert, aber auf keinen Fall beide gleichzeitig. Benötigt eine Komponente keine Konfiguration, muss und sollte dieses Interface nicht implementiert werden.

Als letztes Interface in der Erstellungsphase wird auf Initializable getestet:

package org.apache.avalon.framework.activity;


public interface Initializable{

void initialize() throws Exception;
}

Implementiert eine Komponente dieses Interface, kann sich die Komponente in den Arbeitszustand versetzen und alle wichtigen Arbeiten erledigen, beispielsweise andere Komponenten suchen oder Datenbankverbindungen aufbauen.

import org.apache.avalon.excalibur.xml.Parser;

public void useParser(ComponentManager manager) {
Parser parser = null;
try {
parser = (Parser)manager.lookup( Parser.ROLE );

// Use Parser here

} finally {
manager.release( parser );
}
}

Zwischen der Erstellungs- und der Aufräumphase kann eine Komponente verwendet werden. Es gibt verschiedene Arten von Komponenten: Komponenten, die parallel von verschiedenen Threads gleichzeitig benutzt werden können oder die für jede Benutzung neu instantiiert und danach dem Garbage Collector übergeben werden müssen. Dazwischen liegen Komponenten, die zwar wieder verwendet, die aber nicht gleichzeitig von mehreren Threads verwendet werden können. Dem Entwickler einer Komponente ist das Verhalten seiner Komponente natürlich bekannt, und er sollte dieses Verhalten durch ein entsprechendes Marker-Interface von Avalon kennzeichnen, damit dem ComponentManager mitgeteilt wird, wie er diese Komponente behandeln soll.

Das Marker-Interface ThreadSafe kennzeichnet eine Komponente als parallel von mehreren Threads gleichzeitig benutzbar. Somit gibt es, unabhängig von der Anzahl der Anforderungen, nur ein einziges Objekt dieser entsprechenden Rolle. Das Gegenteil davon wird durch das Interface SingleThreaded gekennzeichnet. Jedesmal, wenn eine solche Komponente angefragt wird, wird ein neues Objekt erstellt.

import org.apache.avalon.excalibur.xml.Parser;

public void useParser(ComponentManager manager) {
Parser parser = null;
try {
parser = (Parser)manager.lookup( Parser.ROLE );

// Use Parser here

} finally {
manager.release( parser );
}
}

Die Erstellungs- und die Aufräumphasen werden für eine Komponente nur genau einmal durchlaufen, d.h. sowohl bei Komponenten, die als Poolable gekennzeichnet sind, als auch bei ThreadSafe Komponenten spart man sich nicht nur das Erstellen von neuen Objekten, sondern auch das Durchlaufen dieser beiden Phasen. Wenn Ihre Anwendung oft Komponenten über den ComponentManager anfordert, kann sich dieses schon auf die Performance auswirken. Daher ist es wichtig, bei der Entwicklung der Komponente dieses mit zu berücksichtigen und zu versuchen, wenn möglich ThreadSafe einzuhalten und ansonsten auf Poolable bzw. Recyclable zurückzugreifen.

In Avalon gibt es für jede einzelne Phase Marker-Interfaces für unterschiedliche Bereiche. Abhängig von den Anforderungen einer Komponente, muss das zugehörige Interface implementiert werden. Benötigt eine Komponente eine Information nicht (beispielsweise den Anwendungskontext), sollten Sie auf keinen Fall dieses Interface implementieren. Sie ersparen sich damit leere Methoden zu implementieren welche vom ComponentManager nicht aufgerufen werden müssen. Sämtliche dieser Marker-Interfaces gehören zur Implementierung, d. h. die Anwendung sollte und darf keine Annahmen darüber machen, welche davon eine Komponente implementiert. Insbesondere ist es kein guter Stil, diese Methoden direkt an einer Komponente aufzurufen.

Ein praktisches Beispiel

Auf den ersten Blick sieht Avalon sehr komplex und kompliziert aus: Es gibt eine Menge an (neuen) Interfaces, die es zu beherrschen gilt. In der Praxis stellt sich allerdings sehr schnell heraus, dass Avalon im Grunde sehr einfach aber trotzdem mächtig ist. Für den Anwendungsentwickler, der lediglich Komponenten verwendet, reicht es aus, einen ComponentManager im Zugriff zu haben und zu wissen, wie er diesen benutzt. Für den Komponentenentwickler gestaltet es sich ähnlich einfach: Zuerst definiert er ein Interface für seine Komponente (dieses müsste er mit jedem anderen Komponenten-Framework auch tun), danach implementiert er die Komponente. Dank Separation of Concern muss er sich nur die Marker-Interfaces (Concerns) herauspicken, die er für seine Komponente benötigt.

Als Beispiel werden wir eine Anwendung entwickeln, die eine Komponente verwendet. Diese Komponente ist ein einfacher Speicher (Store), der eine maximale Anzahl an Elementen enthalten kann. Das Interface hierfür sieht folgendermaßen aus:

import org.apache.avalon.excalibur.xml.Parser;

public void useParser(ComponentManager manager) {
Parser parser = null;
try {
parser = (Parser)manager.lookup( Parser.ROLE );

// Use Parser here

} finally {
manager.release( parser );
}
}

Die Komponente bietet zwei Methoden: put und get. Put wird verwandt, um neue Informationen unter einem Schlüssel einzufügen. Sie gibt true zurück, wenn der Speicher noch nicht voll ist. Über get können die entsprechenden Informationen wieder herausgeholt werden. Die Implementierung ist ebenfalls nicht spektakulär: Die Werte werden in eine Java Map gespeichert – es ließe sich beispielsweise genauso eine Implementierung für diese Komponente entwickeln, die die Informationen persistent in einer Datenbank ablegt. Da die Komponente konfigurierbar ist (maximale Anzahl an Objekten), implementiert sie das Interface Parameterizable. Darüber hinaus ist die Komponente ThreadSafe. Zur Demonstration verwendet die Komponente zusätzlich das Initializable Interface, um die Map einmalig anzulegen (Listing 1).

Listing 1

import org.apache.avalon.excalibur.xml.Parser;

public void useParser(ComponentManager manager) {
Parser parser = null;
try {
parser = (Parser)manager.lookup( Parser.ROLE );

// Use Parser here

} finally {
manager.release( parser );
}
}

Damit eine Anwendung Komponenten verwenden kann, ist ein ComponentManager zwingend erforderlich, der mit der Liste aller Komponenten initialisiert wird. Bei Avalon wird zwischen der Liste der verfügbaren Komponente und deren Konfiguration unterschieden. D.h. der Anwendungsadministrator stellt den Entwicklern eine Liste der Komponenten zur Verfügung, und ein Entwickler verwendet lediglich die Komponenten bzw. konfiguriert sie entsprechend. Diese Unterscheidung wird durch zwei verschiedene Konfigurationsinformationen für den ComponentManager erreicht: Die Rollendefinition und die Komponenten-Konfiguration.

Betrachten wir zuerst die Rollendefinition. Für dieses Beispiel haben wir die Möglichkeit gewählt, eine XML-Datei zu verwenden – diese Konfiguration könnte aber auch anders abgelegt sein:

import org.apache.avalon.excalibur.xml.Parser;

public void useParser(ComponentManager manager) {
Parser parser = null;
try {
parser = (Parser)manager.lookup( Parser.ROLE );

// Use Parser here

} finally {
manager.release( parser );
}
}

Bisher haben wir den einfachen Fall behandelt: Für eine Rolle gibt es genau eine Implementierung. Aber unter Umständen möchten Sie verschiedene Implementierungen für eine Rolle gleichzeitig nutzen können. Beispielsweise können Sie sich eine persistente und eine nicht-persistente Variante des oben definierten Speichers implementieren. Innerhalb der Anwendung wird dann unterschieden, ob die eine oder die andere Implementierung benötigt wird. Die Rolle, also das Java-Interface, ist allerdings für beide Komponenten gleich.

Avalon unterstützt auch diesen Aspekt durch einen sogenannten ComponentSelector:

import org.apache.avalon.excalibur.xml.Parser;

public void useParser(ComponentManager manager) {
Parser parser = null;
try {
parser = (Parser)manager.lookup( Parser.ROLE );

// Use Parser here

} finally {
manager.release( parser );
}
}

Nachdem die Anwendung sich über den ComponentManager den Selektor für components.StoreSelector geholt hat, kann sie sich über non-persistent respektive persistent die verschiedenen Ausprägungen abholen. Wichtig ist, hinterher alle Komponenten in der richtigen Reihenfolge – wie oben skizziert – wieder freizugeben.

Ob Sie als Komponente einen einzigen Store haben, der entsprechend konfiguriert werden kann, ob er persistent ist oder ob Sie einen ComponentSelector einsetzen, hängt ganz von Ihren Anforderungen ab. Allerdings sollten Sie dabei nie vergessen, dass die entsprechende Komponente möglichst allgemein gültig sein sollte, damit sie auch wirklich in anderen Projekten ohne Änderung eingesetzt werden kann.

Durch den Nebel und auf nach Avalon

Komponenten sind eine gute Technik, bekannte Probleme bei der Softwareentwicklung zu vermeiden. Die Nützlichkeit steht und fällt mit dem eingesetzten Komponenten-Framework. Avalon ist ein stabiles und sehr flexibles Framework. Insbesondere durch die Konzepte Separation of Concerns und Inversion of Control ist Avalon anderen Ansätzen überlegen. Es bietet eine einheitliche Basis für die Behandlung von Komponenten und die Entwicklung einer Komponente wird auf das Wesentliche reduziert. Dieses zeigt sich nicht zuletzt auch durch die Beliebtheit von Avalon in anderen Open Source-Projekten.

Darüber hinaus ist Avalon an sich ein erfolgreiches Open Source-Projekt. Zum einen kann jeder selber aktiv in die Entwicklung eingreifen, zum anderen sind die Hauptentwickler von Avalon immer bemüht, ihr Framework zu optimieren. Vor allem werden immer mehr verfügbare Komponenten entwickelt bzw. die Qualität der bestehenden verbessert. Innerhalb des Unterprojektes Excalibur werden verschiedene Komponenten zur Bearbeitung von XML und XSLT entwickelt. Darüber hinaus gibt es dort allgemeine Komponenten wie verschiedene Stores oder ein Cache-System. Obwohl die meisten dieser Komponenten längst produktiv in unterschiedlichen Projekten eingesetzt werden, existiert bisher noch kein offizielles Release. Daher benötigen Sie hier entweder ein Nightly-Build von Excalibur oder Sie können über CVS den letzten Stand untersuchen.

Somit haben Sie die Chance mit Avalon aus dem diffusen Nebel der Komponenten herauszufinden und effizient eigene Anwendungen auf Basis von Komponenten zu entwickeln.

Carsten Ziegeler ist Chef-Architekt und Consultant des Open Source Competence Centers der S&N AG. Er ist aktiver Committer von Avalon und entwickelt frei verfügbare Komponenten im Excalibur Projekt. Darüber hinaus beeinflusste er maßgeblich das Design von Apache Cocoon und ist dort verantwortlicher Release Manager.

Geschrieben von
Carsten Ziegeler
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.