Legosysteme – Java Module und Container Übersicht und Vergleich über aktuelle Standards und Frameworks Abstrakt: Die Enterprise Java Welt ist in ständiger Bewegung. Abgesehen von der Vielfalt neuer dynamischer Sprachen ist auch viel Bewegung in der „traditionellen“ Java Landschaft. Dieser Artikel will einen Übersicht und Vergleich über aktuelle Modulsysteme, Standards und Frameworks in der Enterprise Java Welt geben. Weder .NET noch dynamische Sprachen wie Groovy, (J)Ruby, Jython, Rhino, …können in diesem Artikel betrachtet werden. Der Schwerpunkt in diesem Beitrag liegt auf den unterschiedlichen Modul- und Containersystemen bzw. Standards in Java. Legosysteme aus (Standard-)Modulen, Container, die Legobausteine enthalten, Container, die selber aus Standard-Legobausteinen bestehen. Es gibt vielfältige Modul- und Containersysteme in der aktuellen Enterprise Java-Landschaft, die auch auf unterschiedlichste Weise miteinander kombiniert werden können. Neben der klassischen J2EE Umgebung mit ihrem unterschiedlichen Container sind etliche weitere Modul- und Containersysteme entstanden von denen einige mittlerweile große Verbreitung gefunden haben. Einige davon sind offizielle Standards, andere davon proprietär bzw. Quasi-Standards. Allen voran das Spring Framework und die jetzt neu veröffentliche SpringSource Application Plattform, die zum Zeitpunkt der Artikelerstellung in der Version 1.0.0.beta1 vorliegt. Dazu kommen Konkurrenten wie Google-Guice, Apache-HiveMind und etliche andere aus dem OpenSource und dem kommerziellen Bereich. Konzepte wie IoC (Inversion of Control) und Dependency Injection sind beliebte Merkmale dieser Containersysteme. Daneben gibt es jede Menge Projekte um Module zu erstellen. Relativ unbeobachtet von der Öffentlichkeit ist in den letzten Jahren ein sehr interessanter Standard entstanden, der großes Potential hat und sich schon erstaunlich weit verbreitet hat. Die Rede ist von OSGi. Im ersten Teil des Artikels werden die wichtigsten Konzepte wie Inversion of Control (IoC), Dependency Injection,… vorgestellt. Danach werden im zweiten Teil die verschiedenen Umgebungen vorgestellt. Dabei beschränkt sich dieser Artikel auf die bekanntesten. Dies ist keine vollständige Liste, da sich die Enterprise Java Welt in ständiger Bewegung befindet. Es wurde aber darauf Wert gelegt die bekanntesten Umgebungen hier mit aufzunehmen. Anschließend werden diese unterschiedlichen Systeme in einem kurzen Vergleich gegenübergestellt. 1) Überblick über die wichtigsten Konzepte: Dieser Abschnitt möchte die wichtigsten Konzepte vorstellen, auf die nachfolgend laufend verwiesen wird. Inversion of Control (IoC) Der Begriff Inversion of Control (IOC - deutsch: „Umkehrung der Steuerung“ oder „Steuerungsumkehr“) bezeichnet ein Umsetzungsparadigma. IoC beschreibt eine Änderung des Kontrollflusses. Es ist der wesentliche Unterschied zwischen einem Framework und einer Bibliothek. Bei einer Bibliothek kommt der Programmfluss aus dem eigenen Code und ruft an der Bibliothek Funktionen auf, erzeugt Objekte die von der Bibliothek angeboten werden und schickt diesen Objekten Nachrichten. Die Bibliothek wird vom Programm benutzt und der Kontrollfluss kommt vom eigenen Programm. Anders ist es bei einem Framework. Dort kommt der Kontrollfluss vom Framework. Das Framework ruft eine überschriebene Funktion auf, der Kontrollfluss ist somit umgekehrt. Bei Inversion of Control liegt die Kontrolle hauptsächlich im Framework, welches dann eine Funktion des Programmierers aufruft und somit kurzzeitig die Kontrolle an diese abgibt. Inversion of Control ist besonders in der Programmiersprache Java verbreitet. Ein einfaches Beispiel einer solchen Umkehrung sind Listener oder Servlets. Ein typisches Beispiel sind auch GUI-Frameworks. Dort wird z.B. für einen Button ein Listener geschrieben und als Callback beim Framework registriert. Der Kontrollfluss kommt vom Framework, dieses ruft den Listener auf, wenn ein Benutzer auf diesen Button drückt. Dependency Inversion (DIP) Dieses Prinzip wird oft als Synonym für IoC verwendet. Jedoch kann DIP als ein einfacherer Bestandteil von dem umfassenderen Konzept IoC oder sogar als notwendige Grundlage für IoC angesehen werden. (Quelle: Wikipedia): Das Dependency Inversion Principle (DIP - dt. "AbhängigkeitsInvertierungs-Prinzip") ist ein Prinzip beim Objektorientierten Entwurf von Software. Es beschäftigt sich mit der Abhängigkeit von Modulen. • Beschreibung: Module hoher Ebenen sollten nicht von Modulen niedriger Ebenen abhängen. Beide sollten von Abstraktionen abhängen. Abstraktionen sollten nicht von Details abhängen. Details sollten von Abstraktionen abhängen. • Problem: Objektorientierte Entwürfe werden in Module strukturiert, die unterschiedliche Verantwortlichkeiten umsetzen. Eine gängige Praxis ist das Anordnen der Module in Ebenen. Umso niedriger das Modul, umso spezieller sind die Vorgänge, die es definiert. In den Modulen höherer Ebenen werden allgemein Abläufe definiert, in denen Module niedrigerer Ebene benutzt werden. Das entstehende Problem ist die Abhängigkeit der höheren Ebene zu der niedrigeren. Änderungen im niedrigeren Modul führen unweigerlich zu Änderungen im höheren Modul. Dies widerspricht aber dem eigentlichen Ansatz der Hierarchie. • Lösungsansatz von DIP: Der Lösungsansatz ist die Invertierung der Abhängigkeit. Das Modul der höheren Ebene definiert die Schnittstelle, mit der es arbeitet. Module niedrigerer Ebene realisieren die Schnittstelle. Dependency Injection Dependency Injection ist ein Entwurfsmuster und dient in einem objektorientierten System dazu, die Abhängigkeiten zwischen Komponenten oder Objekten zu minimieren. Dependency Injection ist eine Anwendung des Prinzips der Inversion of Control (IoC), bezieht sich aber nur auf die Erzeugung und Initialisierung von Objekten. Sie kann als Verallgemeinerung der Fabrikmethoden verstanden werden. Die Funktionalität bleibt trotz dieser Kontrollumkehr als Einfügung enthalten. Dadurch ist es einfach möglich, Abhängigkeiten zu erkennen. In einem klassisch aufgebauten OO-System ist jedes Objekt selbst dafür zuständig, seine Abhängigkeiten, also benötigte Objekte und Ressourcen, zu erzeugen und zu verwalten. Dafür muss jedes Objekt einige Kenntnisse seiner Umgebung mitbringen, die es zur Erfüllung seiner eigentlichen Aufgabe normalerweise nicht benötigen würde. Insbesondere muss es, um die entsprechenden Objekte erzeugen zu können, ihre konkrete Implementierung kennen. Dependency Injection überträgt die Verantwortung für das Erzeugen und die Verknüpfung von Objekten an ein extern konfigurierbares Framework, entsprechend einem Komponentenmodell. Dadurch wird der Code des Objektes unabhängig von seiner Umgebung und von der konkreten Umsetzung der Klassen, die es benötigt. Das vermeidet unnötige Abhängigkeiten beim Kompilieren und erleichtert besonders die Erstellung von Unit-Tests. Andererseits wird so Programmlogik in Konfigurationsdateien ausgelagert, was die Übersichtlichkeit vermindern und die Wartung erschweren kann. Aspektorientierte Programmierung (AOP): (Wikipedia:) Aspektorientierte Programmierung (AOP) ist ein Programmierparadigma, das anstrebt, verschiedene logische Aspekte eines Anwendungsprogramms (kurz Anwendung) getrennt voneinander zu entwerfen, zu entwickeln und zu testen. Die getrennt entwickelten Aspekte werden dann zur endgültigen Anwendung zusammengefügt. AOP ist besonders zur Programmierung von so genannten Cross-Cutting Concerns geeignet. Beispiele dafür sind Fehlerbehandlung, Persistenz, Validierung und Sicherheit. Wesentliche Bestandteile sind Pointcuts, Advices, Introductions und „normale" Java-Methoden und Felder, die durch das sog. Weaving (einweben in den Code) einem System ohne SourceCode Änderung hinzugefügt werden können. AOP erweitert die Möglichkeiten der Strukturierung von Code: • Prozedurale Programmierung erlaubt die Strukturierung von Code nur in einer Dimension: Nur GoSUBs und GOTOs ermöglichen eine geringe Strukturierung. • • Objektorientierte Programmierung (OOP) erweitert die prozedurale Programmierung um Objekte, die ihre Eigenschaften vererben können, was eine Schachtelung des Codes ermöglicht, jedoch auch hohe Abhängigkeiten schafft, was die Entwicklung gerade bei komplexen Verflechtungen des Codes in großen Projekten oft stagnieren lässt. Außerdem wirken sich kleine Fehler an den Basisklassen norm auf alle weitere Klassen aus. Sie potenzieren sich. Aspektorientierte Programmierung (AOP) erweitert OOP wiederum um eine Dimension, nämlich die Aspekte, die den oft hochgradig verschachtelten Code entzerren, und die Code-Teile, die viele Klassen gemeinsam haben, in eigene Klassen auslagert. Dies ermöglicht eine hohe Modularität des Codes und vermeidet insbesondere doppelten Code. 2) Kurzüberblick: OSGi Die Open Services Gateway Initiative (OSGi) definiert eine Architektur für die Entwicklung und das Deployment von Anwendungen und Bibliotheken. OSGi kommt ursprünglich aus dem Embedded Bereich. OSGi ist auch bekannt als das dynamische Modulsystem für Java. Es gibt einige Implementierungen des Standards, u.a. Knopflerfish, Equinox, und Apache Felix. Die grundlegende Idee von OSGI - die sog. Bundles - sind Module mit einer Reihe von interessanten Eigenschaften. Vor allem interessant ist die Tatsache, dass eine altbekannte Krankheit von Java und J2EE © Copyright © 2007 IBM Corporation and aQute SARL hier explizit betrachtet wird - das Aufbrechen des klassischen Classpaths. Verschiedene Bundles können - auch im selben Container - unterschiedliche Versionen von bestimmten Bibliotheken (z.B. log4j, Xerces, XML-Parser, ...) verwenden. Es gibt öffentliche und versteckte Klassen/Bibliotheken pro Bundle. OSGi definiert sehr ausführlich die Schnittstelle und die Kommunikation der verschiedenen Bundles untereinander, mit öffentlichen und privaten Klassen/Schnittstellen. Noch dazu können auch mehrere Versionen desselben Bundles gleichzeitig im gleichen Prozess aktiv sein. OSGi bietet prinzipiell folgende Eigenschaften: • Bundles können installiert, entfernt, gestartet und gestoppt werden ohne den Container durchzustarten • Mehrere Versionen des selben Bundles gleichzeitig im gleichen Prozess aktiv sein • OSGi ist durch seine extrem kleine Infrastruktur und Modularität sowohl für Service-Orientierte Architekturen (Enterprise/SOA) als auch für embedded und mobile Anwendungen und auch RIA (Rich Internet Applications) geeignet. OSGi wurde nicht für spezielle Arten von Anwendungen entwickelt (z.B. Web, EJB, GUI, mobile, ...), sondern generell für Anwendungen, die in eigenständige Module unterteil werden sollen. Des Weiteren definiert die Spezifikation, wie sich Bundles dynamisch – also zur Laufzeit – informieren können welche anderen Bundles aktiv sind, sich benachrichtigen lassen können wenn andere Bundes aktiviert bzw. deaktiviert werden. Bundleabhängigkeiten, dynamisches importieren von Packages u.v.m. sollen alle helfen um die üblichen Dynamiken abzubilden, die in einem lebendigen System vorherrschen können. Mit Hilfe von Fragment-Bundles können bestehende Bundles auch erweitert werden. Die weiter höher angesiedelte Service-Schicht (siehe Grafik) definiert, wie innerhalb des OSGI Systems Objekte als Services verwendet werden können. Dafür hilft die OSGi Service-Registry. OSGi Dienste sind einfache Java POJOs. Diese werden innerhalb eines Bundles erzeugt und dann an der schon erwähnten Service-Registry angemeldet. Damit ist es dann möglich, dass diese Dienste auch über Bundle-Grenzen hinweg genutzt werden können. Eine der wirklich interessanten Eigenschaften von OSGi ist es, das Bundles (und damit auch die Services) zu beliebigen Zeitpunkten und in beliebiger Reihenfolge in das OSGi Framework installiert werden können. Daher ist die Möglichkeit auf Änderungen in dieser Service-Registry reagieren zu können ein wesentlicher Bestandteil des OSGi Frameworks. Das OSGi Framework definiert zusätzlich eine Reihe von Standard-Diensten, die verschiedene allgemeine Funktionalitäten (z.B. Logging, Konfiguration, Event-Admin,…) zur Verfügung stellen. Eine durchgehende Sicherheitsschicht rundet das OSGi Modell und dessen Implementierungen ab. Es besteht auch eine realistische Chance, das OSGi als Modularisierungsgrundlage in das JDK aufgenommen wird. Evt. ist dies schon für JDK 7 der Fall. J2EE J2EE oder seit einiger Zeit JEE, die Java Enterprise Edition ist ein umfassendes Standardwerk für serverseitige Javaanwendungen. J2EE ist ein sehr mächtiger Standard, der unterschiedliche Container (EJB, Web, Applikation und Applet) definiert. Es werden ausführlich die unterschiedlichen Technologien und Dienste definiert die im jeweiligen Container unterstützt werden müssen. Da es sich hier um eine große Anzahl unterschiedlicher APIs und Technologien handelt, die unterstützt werden müssen (siehe Grafik mit den 4 Containern) existieren am Markt nur wenige Implementierungen, die alle APIs voll unterstützen und bis inklusive JEE-5 ist es unwahrscheinlich, das neue Hersteller dazukommen werden. Prominente Vertreter sind IBM-WebSphere, BEA-Weblogic, JBoss, Apache-Gernonimo, Borland Enterprise Server, SUN, Ionas, ... wobei nicht alle Hersteller alle JEE Versionen, bzw. alle Teile der Spezifikation unterstützen. Es wird erwartet, das sich mit JEE-6 und den kommenden Profilen (Web, Light, Full oder wie immer diese auch in der endgültigen Spezifikation heißen werden) dies wieder ändern wird, da dann der Einstieg in den zertifizierten(!) Appserver Markt wieder einfacher wird. Die Liste der geforderten Standards im JEE ist lang. Diese umfasst u.a.: • EJB Spezifikation, Servlet, JSP, JSF, J2EE Connector Architecture • Persistenz: JPA (ab J2EE 5), JDBC • Management: JEE-Management, JEE-Deployment, JMX, JACC • Sicherheit: u.a. CSIv2, EJB/J2EE Security, JAAS, PAM, SAAJ, JSSE, SSL, TLS, JCE, digitale Zertifikate. ... • Kommunikation: JMS, RMI, IIOP, RMI-IIOP, HTTP, HTTPS, SOAP, Java IDL • Basisdienste: JTA, JTS, JNDI, JavaMail, JAF • XML: JAXP, StAX • Web Services: JAX-WS, JAX-RPC, JAXB, JAXR, WS-* (nicht ausdrücklich in der Spezifikation gefordert aber für Webservices notwendig) (die einzelnen Spezifikationen können im Rahmen dieses Artikels nicht weiter erläutert werden. Siehe hierzu die JEE Spezifikationen) Die JEE Spezifikationen wurden geschrieben um Komponenten Plattform- und Infrastruktur (Kommunikation, Namensdienst, Transaktionen, Persistenz, Sicherheit) unabhängig zu entwickeln. Dies ist durch das Container-Prinzip möglich. Als Deployment-Packete beschreibt die Spezifikation hierfür unterschiedliche (abhängig vom Zielkontainer) Archivtypen. EJB-Archive, Web-Archive, ClientArchive, Resourceadapter-Archive und als übergeordnete Einheit das EAR (Enterprise ARchiv). Die meisten JEE-Implementierungen erweitern diese Liste um eigene Archivtypen. JEE Komponenten werden bei den eigentlich allen Applikationsserver abgeschottet voneinander in unterschiedlichen Classloadern geladen um Fähigkeiten wie Hot-Deployment u.a. zu erreichen. Alle JEE Komponenten bestehen aus der eigentlichen Implementierung und zusätzlich aus einem oder mehreren sog. Deployment-Deskriptoren (XML), die dem Container beschreiben, wie diese Komponente zu behandeln ist. Ab JEE-5 können die meisten Einträge dieser Deskriptoren auch als Java Annotations im Code hinterlegt werden. Java Module (JSR 291,294,277) Java Module System (JSR-277) beschreibt eine Architektur für die Entwicklung und das Deployment von modulbasierten Anwendungen und Bibliotheken und wird ab Java-7 verfügbar sein. “A Java module is a unit of encapsulation. It is generally written as a development module in a programming language in the Java platform, and is ultimately compiled into metadata and packaged together with classes and other resources as a deployment module.” (JSR-277) Architektur Das Java Module System definiert eine Architektur mit den folgenden Bestandteilen: - Format für die Verteilung (z.B. Java Modul) und dessen Metadaten als eine Einheit von Java Klassen und zugehörigen Ressourcen. Die Metadaten beschreiben das Modul und dessen Abhängigkeiten und definieren ebenfalls, welche Klassen/Ressourcen außerhalb des Moduls sichtbar sein sollen. - Versionierung: Eigene Versionierung und die Definition von Abhängigkeiten zu anderen Modulen auch auf Basis der Version. - Verwaltung für Module mit Versionierung - Laufzeitunterstützung und Classloader Definition für das finden, laden und prüfen von Modulen Eines der erzeugten Artefakte beim Erstellen eines Moduls sind dessen Metadaten. Das besondere Format der Metadaten ist Bestandteil von JSR-294. Nachdem JCP (Java Community Process) eine Zeit lang parallel zu OSGi diese beiden JSRs entwickelt hat, ergab sich bei SUN ein Umdenken, nachdem die Projekte Glassfish und Fuji (https://fuji.dev.java.net/) – eine ESB/JBI Implementierung, auf OSGi umgestellt hatten. JSR 291 soll eine Vereinheitlich bringen und wer heute die JSR-291 Spezifikation herunterladen will bekommt die OSGi-R4 Spezifikation! Spring Framework Das Springframework ist ein mittlerweile sehr beliebtes Framework geworden, das als Kern einen IoC Container besitzt und Beziehungen mittels Dependency-Injektion steuern kann, die normalerweise in der XML basierten Spring Konfigurationsdatei definiert sind, oder – wenn man die Spring Annotations benutzt – auch mittels Annotations deklariert werden können. Als grundlegender Kern besitzt Spring seinen IoC Container. Darauf aufbauend gibt es für Spring eine Reihe von Erweiterungen, so dass Spring mittlerweile eine ganze Familie von Erweiterungen mit zusätzlichen Funktionen besitzt (siehe Grafik). Als Beispiele könnten hier Spring AOP (Integration von AspectJ) und Acegi (umfassendes Sicherheitsmodul) genannt werden. Sowohl AOAP als auch Sicherheit sind sehr grundlegende Springmodule. Kurze Packet Übersicht: - Das "CORE" Packet ist grundlegend für Spring und stellt den IoC und die Dependency Injection Möglichkeit zur Verfügung. Das wichtigste Konzept ist die BeanFactory - Das "Context" (nicht in der Grafik) Packet stellt eine Möglichkeit zur Verfügung um auf die Objekte in Framework Art-und-Weise zugreifen zu können (z.B. Ressource-Einheiten (Internationalisierung), Ereignis-Verarbeitung, Laden von Ressourcen, ...) Das "DAO" stellt eine Abstraktionsebene für JDBC zur Verfügung und nimmt dem Entwickler viel Standard-JDBC Programmierung/Prüfungen ab. Das "ORM" ist eine Integrationsschicht für ORM Werkzeuge wie JPA, JDO, Hibernate und iBatis Das "AOP" Packet bietet eine AOP Alliance konforme aspektorientierte Implementierung für Interceptoren und Pointcuts Das "Web" bietet verschiedene Integrationseigenschaften für Webanwendungen Module die heute zum Springframe gehören umfassen: - Spring Web Flow - Spring Web Services - Spring Security (Acegi Security) - Spring Dynamic Modules For OSGi(tm) Service Platforms - Spring Batch - Spring Integration - Spring LDAP - Spring IDE - Spring Modules - Spring JavaConfig - Spring Rich Client - Spring .NET - Spring BeanDoc (eine genauere Beschreibung finden Sie unter: http://www.springframework.org/projects) Auch Spring ist schon eine Weile auf dem Markt und wird daher gerade für die neue Version etwas aufgeräumt. Einige nicht mehr benötigte Unterstützungen fallen weg und der Spring Kern wird auf JDK 1.5 gehoben. SpringSource Application Plattform: Die SpringSource Application Plattform ist ein leichtgewichtiger OSGi Container. Diese Umgebung komplett aufsetzend auf dem OSGi Modulsystem - bietet eine komplette Lösung für die Verwaltung, Laufzeit und Entwicklung von Java Enterprise Anwendungen. Als Basis werden folgende Technologien verwendet und durch eine Reihe weitere Eigenschaften ergänzt: Tomcat, Sprint, Equinox, Spring/OSGi Modul, SpringSource Tool Suite. Die Grundlage bildet ein OSGi Container mit verschiedenen Diensten für Verwaltung und mehr. Für Webanwendungen wird Tomcat eingebettet. Dieser unterstütz selbstständige WAR Archive als auch WAR Archive, die sich anderer OSGi Bundles bedienen kann. ( © SpringSource Application Platform Das Spring eigene Plattform Archiv (PAR) dient als Programmer Guide ) Deployment Modell. Auf der Webseite gibt es bereits eine große Vielzahl von (OSGi-)Archiven für diese Plattform. Google Guice Guice ist ein sehr schmaler, leistungsfähiger Container mit dem Fokus auf Dependency Injection. Guice basiert auf JDK 5, Generics und Annotations und nicht auf XML Konfigurationsdateien. Guice unterstützt nicht nur das Einfügen(Injection) von Settern (set* Methoden) sondern auch das Einfügen von Konstruktoren, Feldern und Methoden. Darüber hinaus hat Guice erweiterte Fähigkeiten wie ringförmige Abhängigkeiten, Einfügen von statischen Elementen, die Integration mit Spring und ebenso AOP Alliance konforme Methodeninspektion. Die Architektur von Guice kann in zwei elementare Abschnitte unterteilt werden, nämlich in die Startphase und die Laufzeitphase. Während der Startphase wird ein sog. Injector erzeugt, der dann zur Laufzeit genutzt wird um Objekte einzufügen. Apache HiveMind HiveMind ist Microkernel, der von der Apache Foundation gepflegt wird (http://hivemind.apache.org/) und unterstützt Eigenschaften wie IoC (Inversion of Control) Eigenschaften: - Dienste: HiveMind Dienste sind reine POJOs die einfach kombiniert werden können. HiveMind ist für den Lebenszyklus seiner Dienste verantwortlich. Dienste können via Dependency Injection zusammenarbeiten. - Konfiguration: Bei HiveMind können auch komplexe Konfigurationsinformationen in einem Format der Wahl zur Verfügung gestellt werden. Andere Apache Projekte die HiveMind nutzen oder erweitern: - Tapestry: Ein Web Framework, das als Basis HiveMind nutzt. - HiveMind Utilities: Sammlung von HiveMind Erweiterungen für die Unterstützung von Transaktionsverarbeitung, Sicherheit, Netzwerkzugriff, Ereignisse und mehr. - Crispy: Klient für den entfernten Zugriff auf unterschiedliche Dienste via Proxies. Crispy bietet eine Erweiterung für HiveMind Dienste. - Mule: Mule ist ein Enterprise Service Bus (ESB), der HiveMind als Kontainersystem unterstützt. WebBeans Endlich ist auch in der JEE Welt das Verständnis erwacht, das ein Komponentenmodell für JEE notwendig wird. Wie in der JEE Welt aber leider üblich benutzt man keine existierenden Standards, wie z.B. OSGi sondern definiert einen neuen Standard. Dieser den (meiner Meinung nach) etwas unglücklichen Namen WebBeans - JSR 299. Auch Spring oder einer der anderen Container wäre möglich gewesen, leider sind diese aber kein Standard. WebBeans stellt ein vereinheitlichtes Komponentenmodell für JEE dar und definiert: • Ein Programmiermodell für zustandsbehaftete Komponenten, bei denen Metadaten via Annotations oder XML Dateien beschrieben werden können • Integration mit der Unified Expression Language (EL). • Eine Möglichkeit Implementierungen zur Deployzeit auszutauschen • Web-Context Modell und JPA erweitertes Persistenzmodell • Packetierung die kompatibel mit den existierenden JEE Standards sind. Besonders erlaubt WebBeans die Verwendung von EJB 3.x Komponenten als JSF Managed-Beans. Die Spezifikation beschreibt die Verantwortlichkeiten des Entwicklers und des Container-Herstellers. WebBeans ist mit Java EE 5 oder höher kompatible. J2EE 1.4 oder darunter wird nicht unterstützt. Die Unterstützung von JEE 6 ist Pflicht, die Unterstützung von JEE 5 optional. Diese Spezifikation definiert ein eigenständiges Komponentenmodell. Jedoch fehlt der WebBeans Spezifikation einige nützliche/notwendige Eigenschaften, die schon in anderen Spezifikationen definiert sind. Resin IoC Resin IoC ist - anders als viele andere - kein OSGi Container, sondern eine Implementierung des WebBeans Standard (der zur Zeit - Mai 2008 ) noch nicht verabschiedet ist (s.o.). WebBeans erlaubt Entwicklern und Administratoren ihre Objekte außerhalb des Anwendungscodes zu konfigurieren. Eigenschaften von Resin umfassen u.a. einfachere Konfiguration von Nachrichten. JMS Verbindungen, Queues und Topics können via XML konfiguriert werden. Diese können dann durch Annotations und die Java Expression Language (EL) in die Beans injiziert werden. Das erleichtert ebenfalls die Konfiguration von MDBs (Message driven Beans). Sowohl eine eingebaute JMS Implementierung, als auch JCA Konfigurationsmöglichkeiten stehen zur Verfügung. Resin benutzt die neue Concurrency API von Java 1.5 PicoContainer PicoContainer ist ein sehr kleiner Container (was man vom Namen schon vermuten kann), der POJOs verwaltet. Dabei müssen die POJOs nicht von PicoContainer Klassen oder Interfaces abhängen. Der Container kann somit für die POJOs transparent sein. Sowohl das einfügen (Injection) von Konstruktoren als auch von Setter-Methoden und Listen(Collections) ist unterstützt. Verschiedene Schnittstellen stehen für die Verwaltung während des gesamten Lebenszyklus zur Verfügung. Der Lebenszyklus von Komponenten kann überwacht werden. Container können verschachtelt und/oder hierarchisch organisiert werden. NanoContainer NanoContainer, wie man vom Namen ebenfalls vermuten kann, ist etwas mächtiger als der PicoContainer. Konkret baut der NanoContainer auf dem PicoContainer auf und erweitert diesen um zusätzliche Funktionen. Wichtigste Erweiterungen sind u.a. Meta-Daten Support (XML Konfigurationen) und die Unterstützung von dynamischen Skriptsprachen (z.B. Groovy, Beanshell, Jython, Rhino (Javascript)). Dazu kommen zusätzlich noch die Unterstützung von Reflection auf der Basis von Klassennamen, Classloader Management, Booter und Deployer. Die Kernkomponenten vom NanoContainer werden durch weitere Module für Persistenz, Remoting, ... ergänzt. Auch Adapter für andere IoC Frameworks stehen zur Verfügung. JDon JDon Framework ist ein kleines Java Framework, das speziell für Webanwendungen gebaut wurde. IoC und AOP wird unterstützt. JDon = IOC/DI + AOP + CRUD + CACHE Eigenschaften: • Dependency Injection • Standardimplementierung für CRUD (Create, Read, Update, Delete) • Stellt ein automatisches Pagination-Framework (abschnittsweises Lesen von großen Ergebnisdatenmengen) zur Verfügung • Unterstützt zustandsbehaftete Serverkomponenten JDon kann alleine oder z.B. auch innerhalb eines J2EE Containers benutzt werden. JBoss Microcontainer JBoss Microcontainer ist ein kleiner Container mit IoC und Dependency Injection Unterstützung. Er erlaubt die Konfiguration von POJOs durch XML und unterstützt die verschiedenen Lebensabschnitte (Lifecycle) so dass diese als Dienste behandelt werden können. Microcontainer benötigt den JBoss Application Server NICHT, so das er in jeder Art von Java Anwendung (J2EE oder nicht) benutzt werden kann. Abhängigkeiten werden vollständig unterstützt und überwacht, so das POJOs erst dann deployed werden können, wenn alle abhängigen Komponenten deployed sind. JBoss Microcontainer hat einige sehr nützliche Eigenschaften, die sich in Umgebungen wie Spring/PicoContainer/.. nicht finden. Dazu gehört u.a. hot-redeployment und hot-reconfiguration. Dazu implementiert JBoss Microcontainer eine Zustandsautomaten um die Zustandsübergänge der Komponenten zu verwalten. Zu den Zuständen gehören Not Installed, Described, Instantiated, Configured, Create, Start, Installed und Error. Anwendungen werden als .beans Dateien deployed. CORBA 3.x Component Modell Auch die OMG (Object Management Group) hat vor langer Zeit ein Komponentenmodell definiert, das auf CORBA (Common Object Request Architecture) aufsetzt. Dies trägt den Namen CCM (Corba Component Model). Leider hat dessen Spezifizierung zu lange gedauert, und zur selben Zeit ist parallel der EJB Standard entstanden. Es gab Ansätze diese beiden Standards zu vereinheitlichen, und da das CCM sogar plattform- und sprachneutral definiert wurde wäre dies eine interessante Entwicklung gewesen. Durch diese lang andauernde Standardisierung hat das CCM leider schnell an Bedeutung verloren und wurde kommerziell so gut wie nie eingesetzt. Es gibt eine Reihe von (Teil-)Implementierungen, u.a. OpenCCM, MicoCCM, StarCCM, Component Integrated ACE ORB (CIAO), Enterprise Java CORBA Component Model (EJCCM). Ähnlich wie der JEE Standard definiert auch das CCM Kontainerumgebungen mit Transaktionen, Sicherheit, … Da sich das CCM im Markt nicht durchsetzen konnte, wird es im weiteren Verlauf dieses Artikels nicht weiter betrachtet. Sonstige IoC Container Im OpenSource Bereich gibt es eine Menge weitere IoC Container, die mehr oder weniger aktiv weiterentwickelt werden. Eine Betrachtung aller würde den Rahmen dieses Artikels sprengen, daher werden einige von ihnen hier nur aufgelistet - DNA: (http://dna.codehaus.org/), neueste Version ist 1.1 vom 2.5.2004 - Soto: Soto ist ein Kontainer-Framework mit einem mächtigen Konfigurationsformat basierend auf Java's Introspection. U.a. werden JMX und AOP unterstützt. (http://www.sapia-oss.org/projects/soto/site/html/ ), neueste Version 3.0b3 vom 4.6.2007 - Carbon: (http://carbon.sourceforge.net/), neueste Version ist 2.1 vom 23.11.2003 - Gravity: (https://gravity.dev.java.net/), neueste Version ist 1.0beta vom 26.5.2004 - Loom: (http://loom.codehaus.org/) Loom ist ein Microkernel der auf dem DNA (s.o.) Framework aufbaut. Loom unterstützt Komponenten die mit dem Avalon Framework entwickelt wurden. Neueste Version ist 1.0 vom 14.2.2005 - Yan (Yet Another Non-intrusive container) stellt eine kompakte unabhängige Java API, mit Monitoring, Lifecycle-Management,XML Konfiguration,... bereit. Neueste Version 5.0.2, 13.4.2007 (http://yan.codehaus.org/) - JICE: (http://jicengine.sourceforge.net/) JICE ist ein XML basierter IoC-Kontainer für die Initialisierung und Konfiguration von Java Anwendungen. JICE besteht aus der JIC Spache (XML Beschreibung) und der JIC Engine (Kontainer). Neueste Version 2.1.3 vom 17.6.2006 2) Einordnung und Vergleich: OSGi und Java Modules (JSR 291,294,277) Zwei Standards für dasselbe Problem. Zum Glück werden beide mit JSR 291 zusammengeführt. OSGi und Spring/JEE Diese beiden lassen sich eigentlich nicht gut vergleichen, da diese Frameworks keine Konkurrenten sind, sondern sich perfekt ergänzen. OSGi ist bereits die Grundlage verschiedenster Applikationsserver (z.B. BEA-Weblogic, IBM WebSphere, SUN Glassfish). Hier trifft man auf der Ebene der Applikationsserver auf das Phänomen (wie am Anfang erwähnt): Container die aus Legobausteinen gebaut sind. OSGi bietet vom Standard her eigentlich keine direkte Unterstützung für entfernte Aufrufe oder Protokolle (abgesehen von den http Service von OSGi). Sieht man jedoch den gesamten JEE Container oder den Spring Container als eine Möglichkeit diese modular durch OSGi Bundles aufzubauen, so ergeben sich ganz neue Möglichkeiten. Z.B. können Dienste (wie der EJB Container, …) zur Laufzeit dynamisch (und das standardisiert !) in den Appserver hinzugeladen werden. Nicht nur das die eigentlichen JEE Archive auch OSGi Archive sein können, die einzelnen Teile des Containers können durch OSGi Bundles und Services modular aufgebaut werden. Nimmt man z.B. die Interceptormöglichkeiten, die ab EJB 3.0 hinzugekommen sind, ist die ebenfalls eine elegante Variante, derartige Interceptoren dynamisch nachzuladen (z.B. erweitertes Logging im Problemfall). Genau dasselbe wie für OSGi gilt auch für Spring. Genau aus diesem Grund basiert die neue SpringSource Application Plattform auch zu 100% auf OSGi. JEE und Spring Über den Vergleich von Spring und J2EE sind schon viele Bücher und Artikel geschrieben worden. Die Suche von „J2EE“ und „Spring“ bringt bei Google über 500000 Treffer. Beide sind mächtige Frameworks die sich gut für Enterprise Java Anwendungen eignen. Für viele ist die Entscheidung für Spring oder J2EE eher eine Geschmacksfrage oder eine politische Entscheidung. Für umfangreiche Vergleiche dieser Umgebungen sei auf die vielfältigen Internet Artikel und Bücher verwiesen. Einige Anmerkungen: - JEE ist ein umfangreicher Standard, der von verschiedenen Herstellern implementiert wird. Durch die neuen Profiles in JEE-6 werden auch wieder neue Namen hinzukommen. Spring dagegen ist kein Standard und wird von genau einer Firma gepflegt (SpringSource). Wer also nur auf Standards setzen will kommt an JEE nicht vorbei. Bei Spring bindet man sich an genau einen Hersteller (was JEE von Anfang an vermeiden wollte). - Spring ist universeller als JEE. Spring bietet für viele unterschiedliche Aspekte Module an (z.B. AOP, Hibernate, WebFlow, …). Die IoC/DI Eigenschaften können selbstverständlich auch in ganz normalen Anwendungen genutzt werden. Das ist bei JEE nicht so einfach möglich - JEE hat besonders im Persistenzbereich eine mehrfache Wiederholung von ungeschickten Fehlern zu verbuchen (Entity Beans 1.0,1.1 waren ziemlich unbrauchbar und auch 2.x hat etliche Schwächen. Erst ab 3.0 wurden diese Fehler zu einem großen Teil beseitigt). Spring geht einen anderen Weg und besonders mit Hibernate steht ein mächtiges ORM Werkzeug zur Verfügung das sehr weit verbreitet ist. - AOP ist fester Bestandteil von Spring. In JEE-5 wurden Interceptoren eingeführt, die aber nur einen kleinen Teil dessen können, was AOP leisten kann. Selbstverständlich können Bibliotheken wie ASPECTJ,… auch in jedem JEE Server eingesetzt werden aber nur mit großer Vorsicht und Sorgfalt - JEE ist aufgrund des JCP Prozesses ein Standard der sich langsam entwickelt (aber es ist ein Standard). Spring ist flexibler und kann schneller neue Module/Erweiterungen/Änderungen herausbringen Guice und Spring Ein kurzer Vergleich dieser beiden Frameworks. Spring basiert sehr stark auf Dependency Injection und sicherlich ist es Spring zu verdanken, dass sich diese Technik so weit verbreitet hat. Guice und Spring stehen nur teilweise in direkter Konkurrenz. Spring ist mittlerweile (s.o.) zu einem sehr umfassenden Framework geworden, Guice jedoch legt den Fokus primär auf Dependency Injection. Guice ist kein zweites Spring und sollte dies auch nie sein. Es ist schlicht Goolge's eigenes Framework. Aus diesem Grund hat Guice auch nur die Unterstützungen, die Google brauchte. dazu gehören Annotations und Generics. Daher kann Guice nicht mit JDK 1.4 oder niedriger verwendet werden. Swing bis zur Version 2.5 dagegen schon. Annotations müssen nur in folgenden Fällen verwendet werden: - Wenn der Bind-Typ alleine nicht ausreicht. - Annotation Types können an verschiedenen Stellen wiederverwendet werden. Spring unterstützt zwei gegensätzliche Konfigurationsmöglichkeiten: Explizite und automatische Verknüpfung (sog. auto-wiring). Spring unterstützt XML und Annotations (nur JDK 5). Guice unterstützt nur Annotations. Sollten Annotations jedoch nicht möglich sein, kann in Guice ein sog. Custom Provider geschrieben werden. Guice kann mit Spring zusammenarbeiten - Existierende Spring Beans können eingebunden werden - AOP Alliance Methoden Interceptoren werden unterstützt, daher können Springs beliebte Transaktionsinterceptoren eingebunden werden. Unter http://www.javalobby.org/articles/guice-vs-spring/ befindet sich ein interessanter Performanzvergleich dieser beiden Frameworks von William Louth, der Guice erstaunliche Geschwindigkeitswerte bescheinigt. Spring und WebBeans Der WebBeans Standard ist noch nicht verabschiedet. Es wird erwartet, das dieser Bestandteil von JEE-6 sein wird. Und wieder ist es dem JCP gelungen, für ein Problem, das längst in verschiedensten Frameworks gelöst wurde einen Standard zu definieren, der wieder andere Implementierungen erfordert. Da es bis jetzt nur wenige Implementierungen gibt (z.B. Resin IoC) sind Vergleiche dieser beiden Frameworks noch schwierig. Von der Draft-Spezifikation ausgehend, besitzt WebBeans aber wesentlich weniger Eigenschaften als Spring Spring und NanoContainer/PicoContainer Der Arbeitsaufwand bei PicoContainer und Spring um IoC Informationen zu definieren unterscheidet sich prinzipiell wenig. Spring kann entweder via XML oder mittels Annotations konfiguriert werden. PicoContainer unterstützt im Kern nur die Konfiguration in Java selber. Im erweiterten NanoContainer oder durch das PicoExtras Project ist ebenfalls XML Konfiguration möglich. PicoContainer ist der wesentlich(!) kleinere Container, der sich auf IoC konzentriert. Spring dagegen stellt viele weitere Klassen für die Unterstützung der anderen Module (z.B. Hibernate, ...) zur Verfügung. PicoContainer/NanoContrainer können mit Spring kombiniert werden. Aufgrund der kleinen Größe eignen sich PicoContainer/NanoContrainer besser für den embedded-Bereich. Features Spring Pico Yan/Nuts Yes Through Nano Container Yes Auto wiring Yes Yes Yes Manual wiring Yes Yes Yes xml configuration Extensible auto wiring support No Auto Bean Registration No Life cycle Singleton only Singleton only Both singleton and prototype Eager Instantiation Default for all singletons Yes Yes Lazy Instantiation Yes Yes Default Parametered and ad-hoc life cycle No No Through <lifecycle> tag Yes Yes Constructor Injection Yes No Yes. Custom Autowire Mode - EJB3 style Yes Setter Injection Yes Yes Yes Factory Method Injection Yes Yes Yes Referencing Field FieldRetrievingFactoryBean Implement ComponentAdapter Through <field> tag. No Yes No Through <sequence> or <callcc> tags Anonymous sub-bean Ad-hoc bean combination Yes No Concise collection literal No No Yes named local bean No No Through <local> tag abstract bean Yes No bean function no yes import module Yes Yes Yes module private beans No No Through "export" and "hide" attribute of <module> Selective import by bean names No No Through "includes" and "excludes" attribute of <import> Import with namespace No No Through "namespace" attribute of <import> Singleton bean with prototype property Requires Cglib and bytecode generation ComponentAdapter combination Through component combination Dependency Injection for objects not managed by container Supported at the cost of Spring API dependency No Through <function> and <factory> tag Extensible tag library No. But FactoryBean is a substitute No By implementing subclasses of Nut Configuration unit-testable within configuration file. No No By using <sequence> together with <assertEqual>, <assertSame>, <if>, <unless>, <fail> etc. autoproxy Yes Custom PropertyEditor Yes Yes Yes Container hierarchy Yes Yes Yes AOP support Both Spring AOP and AspectJ Via dynaop Any AOP solution can be plugged in. An integration package for spring AOP is No provided out-of-box. Declarative Transactional support No. But Spring's declarative transaction support is integrated. Yes Scripting language support Not yet Nano Container Not yet (Quelle: http://docs.codehaus.org/display/YAN/Spring,+Pico+and+Nuts+Compared) JDon und Spring/JEE Vergleich von EJB2/EJB3/Spring/Jdon EJB2/EJB3 loose coupling full-stack stand-alone Spring Framework supports Application Jdon Framework supports Application EJB3 supports Application POJO but the framework POJO itself is not managed in a ioc. more full-stack full-stack no location transparency performance trap POJO and the framework itself is managed in a ioc. less full-stack location transparency, and the performance of the location transparency framework's components are optimized.excellent stand-alone performance. not supports cluster, but can not supports cluster,but support EJB, can be a proxy of EJB. autowiring is not default core simple but powerful, function, when there are hundreds of beans, many support core autowiring, donot take care of the time will spent on taking beans invovation relations. care of their invocation relations. scalablity supports cluster. RAD Tool need business IDE Tool system large system or medium system. medium and small system weight,but banting. lightweight, but maybe being lightweight, always simple fat but quick and powerful weight lightweight Quelle: https://jdon.dev.java.net/doc.htm small and medium system 3) Zusammenfassung Die (Enterprise-)Java Welt kennt zurzeit viele unterschiedliche Standards und Frameworks für Modularisierung und Laufzeitumgebung. Neue Standards/Umgebungen kommen, andere versinken in Vergessenheit. Dieser Artikel hat verschiedene dieser Umgebungen vorgestellt. Dabei gibt es verschiedene Möglichkeiten diese Umgebungen zu kategorisieren: - Standard: OSGi, JEE, Java Module, CCM - Modularisierungsframeworks: OSGi, Java Module - IoC Container: Swing, Guice, HiveMind, WebBeans, YAN, Pico/Nano, Resin,JDon,… - Grundlage ist ein Standard-Modulsystem: Resin (WebBeans), SpringSource Application Plattform (OSGi) Die Entscheidung welches Framework in einem Projekt zum Einsatz kommt, hängt von vielen Faktoren ab. Typische Faktoren können sein: Standard ja/nein, weite Verbreitung, zukünftige Entwicklung, basierend auf Standards, Flexibilität, Verwendung aktueller Technologien, Kombinierbarkeit mit anderen Bibliotheken und Frameworks, … Es gibt keine einheitliche Entscheidung (sonst gäbe es ja auch nicht so viele Umgebungen). Diese Entscheidung ist entweder auf Firmen-Architekur-Ebene oder Projektabhängig zu treffen. Ein wichtiger Faktor bei den IoC Containern ist sicherlich die Zielplattform. Für den embedded und mobilen Bereich ist das mächtige Spring-Framework sicherlich nicht so gut geeignet wie die wesentlich kleineren Pico/NanoContainer. Umgekehrt eignen sich JEE und Spring für mächtige Enterprise Anwendungen besser als Pico/NanoContainer. Die hier vorgestellten Standards und Frameworks lassen sich in verschiedene Gruppen einteilen. Die folgende Tabelle soll dies verdeutlichen: Name OSGi Stand ard Modulsystem IoC Dependency Injection OpenSource Java Module J2EE Spring SpringSource Application Framework Google Guice Ein Hersteller Aktuelle Version OSGi R4 Version 4.1 draft Aktuelles Release April 2007 JEE-5 28.4.2006 2.5.4 28.4.2008 1.0beta 30.4.2008 (Basis OSGi) 1.0 8.3.2007 PicoContainer 1.1.1 2.0 in beta 2.2 Januar 2006 10.5.2008 NanoContainer 1.1.2 11.12.2007 WebBeans draft HiveMind Resin IoC JDon JBoss MicroContainer YAN CORBA CCM + professional Version 3.1.6 5.5.2008 5.2 2.4.2008 1.0.2 25-Jan2006 (2.0.0 Beta9 – Mai 2008) 5.0.2 13.4.2007 4.0 1.4.2006 Ein Standard, den man sicherlich im Auge behalten muss, da dieser eine immer größere Bedeutung erlang ist OSGi. Im Embedded-Bereich schon seit längerem verbreitet, hat sich dieser Standard auch im Enterprise Bereich etabliert und wird sehr wahrscheinlich schon bald als neues Java Modulsystem Kernbestandteil des JDKs sein. Für viele unbekannt ist auch, das ab der Version 3.0 die komplette Eclipse Umgebung auf OSGi aufbaut (auch wenn der Name Plugins beibehalten wurde). Alle Eclipse Bestandteile sind OSGI Bundles. Auch basieren schon viele Enterprise Umgebungen auf OSGi. Referenzen - - - - - - - Generell o Martin Fowler: http://martinfowler.com/articles/injection.html o http://en.wikipedia.org/wiki/Dependency_injection o http://de.wikipedia.org/wiki/Dependency_Inversion_Principle o http://en.wikipedia.org/wiki/Inversion_of_control o http://www.theserverside.com/tt/articles/article.tss?l=IOCBeginners o http://tutorials.jenkov.com/dependency-injection/index.html o http://www.javalobby.org/articles/di-heritage/ o http://www.objectmentor.com/resources/articles/dip.pdf o http://www.informatik.uni-hamburg.de/SWT/publications/papers/Dipl/diplom.pdf o http://java-source.net/open-source/containers OSGi o OSGi Webseite http://www.osgi.org/ o http://www.aqute.biz/osgi o Die OSGi Service Platform (ISBN: 978-3-89864-457-0) o Equinox [http://www.eclipse.org/equinox/] o Knopflerfish o Apache Felix - http://felix.apache.org/ o Gravity: Richard S. Hall, OSGi and Gravity Service Binder Tutorial, 2004, http://oscarosgi.sourceforge.net/tutorial/ o KF: Erik Wistrand, Develop OSGi Bundles, 2004, http://www.knopflerfish.org/programming.html o OSGi Intro: OSGi Alliance, OSGi Technology, 2004,http://www.osgi.org/osgi_technology/index.asp?section=2 Java Module o http://jcp.org/en/jsr/detail?id=294 o http://www.osgi.org/blog/ o http://felix.apache.org/site/presentations.data/osgi-apachecon-20060628.pdf J2EE o http://java.sun.com/javaee/ o http://en.wikipedia.org/wiki/Java_EE o Spring und SpringSource Application Platform o http://www.springframework.org/ o Buch “Spring in Action” by Craig Walls o http://www.springframework.org/osgi o http://docs.codehaus.org/display/YAN/Spring,+Pico+and+Nuts+Compared Guice o http://code.google.com/p/google-guice/ o Performance-Vergleich: http://www.javalobby.org/articles/guice-vs-spring/ o http://code.google.com/p/google-guice/wiki/SpringComparison HiveMind o http://hivemind.apache.org/ JDon o http://jdon.dev.java.net Resin IoC o http://www.caucho.com/press/2008-04-23.xtp CORBA-CCM o http://www.omg.org/docs/formal/06-04-01.pdf NanoContainer o http://www.nanocontainer.org/ WebBeans o http://jcp.org/en/jsr/detail?id=299 o http://www.jboss.com/pdf/press/webbeans.pdf Über den Autor: Martin Heinzl arbeitet als Senior Consultant für den Bereich Enterprise Technologien bei der Firma Borland und beschäftigt sich schon über 10 Jahre mit Java Enterprise Technologien und Frameworks, u.a. CORBA, J2EE. Kontakt: [email protected]