Che ist ein Java-Framework, das der Erstellung verteilter und lose gekoppelter Anwendungen dient, die über einen browserbasierten Client sowie serverseitige RESTful Services verfügen. Die Anwendungen werden durch Zusammensetzen von Extensions gebaut und folgen zahlreichen Grundsätzen der Eclipse RCP.
Am 27. Oktober 2014 wurde Eclipse Che angekündigt. Eclipse Che ist die technologische Basis von Codenvy, einem Start-up mit Hauptsitz in San Francisco; die Entwicklung findet in Cherkays (Ukraine) statt – daher auch der Projektname „Che“. Dieser Artikel gibt einen kurzen Überblick über die Entwicklungsgeschichte von Che, den Wert von Cloud-Entwicklung und eine Einführung in das Schreiben von Extensions mit Che.
Codenvy wurde 2009 entwickelt, und zwar ursprünglich als Cloud-IDE. Die Codenvy-IDE wurde gut aufgenommen und von über 100 000 Usern genutzt: Studenten, Beratungsunternehmen und Start-ups. Eine breitere Anwendung von Seiten der Industrie blieb ihr jedoch verwehrt. Man gelangte zu der Erkenntnis, dass Großunternehmen Cloud-Entwicklungstechnologien erst dann übernehmen würden, wenn Cloud-IDEs genauso erweiterbar wie ihre Desktopgegenstücke wären.
Die Entwicklung des ursprünglichen Kernels begann im Jahr 2012; in den vergangenen Jahren wurde Codenvy dergestalt umgeschrieben, dass es Gebrauch von Che machen kann. Der Gedanke an Che wurde aus der Idee geboren, eine Plattform zu erschaffen, die mithilfe von Extensions für jeden Anwendungsfall angepasst werden kann.
Im Oktober 2014 stellte Codenvy das neue auf Che basierende Codenvy vor, das über codenvy.com auf dem Kernel basierende, kommerzielle Lösungen bieten soll.
Im Sommer 2014 wurde Che der Eclipse-Community angetragen; bereits im selben Herbst wurde es Teil des Top-Level-Projekts „Eclipse Cloud Development“. Codenvy ist ein strategisches Mitglied der Eclipse Foundation und fühlt sich den Themenbereichen Open-Source-Lizensierung, Ökosystementwicklung sowie IT-Governance besonders stark verpflichtet.
Codenvy ist eine Cloud, die Entwicklerumgebungen bereitstellt, teilt und skaliert. Es handelt sich um eine Microservices-basierte Plattform, die durch Ches Infrastruktur und Kernel betrieben wird. Um zu verstehen, was für das Schreiben von Che Extensions nötig ist, muss zunächst die Rolle von Extensions bei der Cloud-Entwicklung erörtert werden.
Codenvy basiert auf Microservices, um besonders schnell ladende und responsive Workspaces liefern zu können. Jeder Microservice automatisiert einen Teil des Entwicklerworkflows, seien es Codeanalyse, SQL-Abfragen, die Kompilierung oder Runner. Projekte werden mithilfe einer Automatisierungs-Engine gebaut, die Code, Plug-ins, Abhängigkeiten, Builder und Runner konfiguriert. Entwickler müssen also nichts installieren und können sowohl online als auch offline mit der Che-IDE oder einer beliebigen anderen Entwicklungsumgebung arbeiten.
Schnell und schmerzlos: Entwicklerumgebungen können per Mail oder IM geteilt werden. Datenschutz und Zugriffskontrolle stehen jedem Entwickler bereit, während Workspaceadministratoren Gruppen- und Ressourcenrichtlinien festlegen. Da die Extensions das System zentral verwalten, kann eine neue Ebene der Berechtigungs- und Ressourcenkontrolle auf eine Art zentralisiert werden, wie es bei einer Desktoporchestrierung nicht möglich ist.
Tasks wie etwa Abhängigkeitsanalysen und Modultests werden parallel ausgeführt, was dem Workspace Ressourcen bietet, die weit jenseits der Grenzen eines Desktops oder einer VM liegen. Runner und Custom Tasks erhalten isolierte Docker-Container (Abb. 1), die in den Sourcecode und Artefakte eingespeist sind.
Codenvy wurde dahingehend designt, dass Entwickler Entwicklerumgebungen erschaffen, teilen und verteilen können; dass ihnen Möglichkeiten zum Bauen und Ausführen von Anwendungen an die Hand gegeben sind, die weit über die Limitierungen eines einzelnen Computers hinausgehen. So kann online wie offline von jeder Maschine aus gearbeitet werden.
Codenvy (Abb. 2) ist ein Cloud-System, das über viele Knoten hinweg läuft. Die Dienste sind über RESTful APIs und anschließend per Kommandozeile, API oder eine browserbasierte IDE zugänglich. Che stellt den Kernel bereit, der eine logische Extension entweder als einen Dienst oder eine UI-Extension betreibt, die Teil der Che-IDE ist. Bei Letzterer handelt es sich um eine Cross-Browser-, JavaScript-optimierte Clientanwendung. Die Extensions werden in Java geschrieben; der Che-Kernel übernimmt die Übersetzung in JavaScript sowie die Bereitstellung des Diensts und des API.
Die Che-IDE ist eine Sammlung von 55 Extensions, die die Funktionalität des Systems erweitern. Che hält voreingestellte Projekttypen für viele beliebte Stacks, sowie Implementierungen von für Entwickler relevante Kernfunktionen bereit, die das gesamte Spektrum von der Editierung bis zur Bereitstellung abdecken. Die IDE kann sowohl lokal auf dem Desktop als auch innerhalb eines Servlet-Containers laufen. WSO2 arbeitet an einem Chromium-Assembler, um die Verteilung zu vereinfachen. Die IDE und jedes der Plug-ins sind mittlerweile Teil des Che-Projekts.
Eclipse Che ist für sich genommen ein Einzelknotensystem. Alle Funktionen laufen im Kontext des Einzelservers. Es kann potenziell Tausende Entwickler gleichzeitig auf derselben Knoteninstanz hosten, allerdings ist die Kapazität eingeschränkt. Die im Eclipse-Che-Runtime-Kernel laufenden Erweiterungen verleihen dem System insgesamt Skalierbarkeit, Sicherheit und gute Handhabbarkeit. Ein grundlegendes Architekturanliegen der Plattform ist die getrennte Verarbeitung, die eine größtmögliche Nutzerdichte bei kleinstmöglichem Hardwareeinsatz ermöglicht. Jede Operation des Entwicklungsprozesses wird zu verschiedenen Microservices-Knoten geleitet, was für die Entwickler effektiv bedeutet, über mehrere Rechner zu verfügen. Beispielsweise wird ein build Request in eine Builder Queue überführt und einem speziellen Set von Builder-Knoten gewartet, die für die Handhabung aller Builder-Knoten der gesamten Cloud zuständig sind. Während ein Builder-Job ausgeführt wird, wird die Entwicklerumgebung weder blockiert, noch erfährt sie Anzeichen von Überlastung durch den Editor. Das Trennverfahren kommt bei Editoren, Codeassistenten, Buildern, Runnern, der Datenquellenverwaltung sowie externen API-Aufrufen zur Anwendung. Die Plattform läuft auf jedem Infrastructure-as-a-Service-Provider, wodurch ihr auf Abruf zusätzliche physikalische Knoten zur Verfügung stehen, die den verschiedenen Clustern der Hardwareverarbeitung zugeteilt werden können.
Eclipse Che wurde ursprünglich als ein SDK designt; die IDE ist im Grunde eine Aggregation vieler verschiedener zusammengepackter Extensions. Wenn sie im SDK bereitgestellt werden, werden die Extensions in serverseitige Logiksysteme und Cross-Browser JavaScript konvertiert. Eine einzelne Extension kann sowohl client- als auch serverseitig sein. Es ist möglich, eigene Extensions zu erschaffen, die in der Lage sind, sämtliche Aspekte des Systems zu überschreiben, angefangen bei der Struktur der APIs über das Erscheinungsbild der IDE bis hin zum Interaktionsmodell der Microservices. Durch das Zusammenpacken der Extensions im SDK wird ein neuer Webanwendungsdienst generiert. Der User kann auswählen, ob er seine eigenen Extensions hinzufügen will oder ob er bestehende modifizieren oder entfernen möchte.
Eine Che-Anwendung ist eine Kombination aus einem Set von Extensions, die als JAR-Dateien gepackt sind, sowie dem SDK, das aus einem Set von Java-Klassenbibliotheken besteht, die innerhalb eines Servlet-Containers laufen. Um eine Che-Anwendung zu erstellen, muss man die Extension als JAR-Datei packen und anschließend im SDK bereitstellen. Wenn das SDK bootet, wird die Extension in die Anwendung integriert, und man erhält eine Che-Anwendung.
Che-Extensions werden in Java geschrieben und unter Zuhilfenahme des Google Web Toolkits, einer Java-Bibliothek, die Java-Code in Cross-Browser-optimiertes JavaScript umwandelt, erstellt. Die Extension kann entweder als JAR-Datei bereitgestellt oder in Kombination mit dem SDK-Sourcecode in eine einzige GWT-Anwendung kompiliert werden. Nach einer derartigen Kompilierung wird die Che-Anwendung zu einer einzelnen, optimierten Programmdatei. Entschließt man sich dazu, die Extension als in sich abgeschlossene JAR-Datei bereitzustellen, so muss man ein Integrationskommando ausführen, das die Extension-JAR-Datei mit dem SDK kompiliert, um so die integrierte Anwendung zu erstellen.
Da Che Extensions auf Java basieren, erfordern Änderungen an einer Extension eine Neukompilierung. Eine dynamische Aktualisierung von Che Extensions für den Produktionseinsatz wird zurzeit nicht unterstützt. Allerdings bietet das GWT den Super Dev Mode, der inkrementelle Änderungen des Quellcodes sowie das Testen dieser Änderungen in einem laufenden Container ermöglicht.
Im Folgenden werden wir eine Hello World Extension kompilieren und das SDK mit ihm booten. Die Struktur der Extension sowie die Editierung werden wir in späteren Abschnitten besprechen. Falls noch nicht geschehen, installieren Sie zunächst Che:
$ git clone https://github.com/codenvy/plugin-sdk.git $ cd plugin-sdk $ mvn clean install
Dies klont und kompiliert das Repository, das eine Auswahl von Beispiel-Extensions bereithält, inklusive dem genannten Hello-World-Beispiel. Die kompilierten Artefakte jeder Auswahl werden in einem Zielunterverzeichnis abgelegt, das sich innerhalb des jeweiligen Extension-Verzeichnisses befindet. Für die folgenden Befehle wird angenommen, dass Che unter ~/sdk installiert wurde und die Beispiel-Extensions unter ~/plugin-sdk geklont wurden:
$ cd ~/sdk/assembly-sdk/target/tomcat-ide/ext $ cp ~/plugin-sdk/codenvy-sdk-tutorials/helloworld-ext/target/helloworld-extension-1.1.0-SNAPSHOT.jar . $ cd .. $ ./extInstall.sh $ cd ~/sdk $ ./codenvy_sdk.sh start
Diese Befehle kopieren die im vorhergehenden Schritt generierte JAR-Datei in den ext/-Ordner der erzeugten Che-Anwendung. Diese spezielle Che-Anwendung ist darauf optimiert, innerhalb von Tomcat als Servlet-Container zu laufen. Das ext/-Verzeichnis enthält alle von Dritten entwickelten Extensions. Führt man extInstall.sh aus, so wird das SDK mit der eigenen neuen Extension neu kompiliert und somit eine neue Che-Anwendung geschaffen, die alle Extensions und APIs in sich vereint. Anschließend muss Che neu gestartet werden; dies nimmt einige wenige Minuten in Anspruch. Wir werden Ihnen zeigen, wie man den GTW Super Dev Mode einrichtet, um die inkrementelle Kompilierung und das Testing zu beschleunigen.
Wenn Sie eine Che-Anwendung laufen lassen, werden Sie bemerken, dass die Hello World Extension installiert wurde; in der Ereigniskonsole wird eine Hello-World-Nachricht angezeigt. Mit derselben Technik können Sie alle anderen im plugin-sdk-Verzeichnis generierten Extensions bereitstellen.
Im Folgenden wird die denkbar einfachste Dateistruktur einer Extension gezeigt:
pom.xml src/main/java/{package-name}/{extensionName}.java src/main/resources/{package-name}/{extensionName}.gwt.xml <!--Optional: only if you choose to use GWT injection as an abstraction tool--> src/main/java/{package-name}/inject/GinModule.jav
Che Extensions sind GWT-Module, die mithilfe von CDI, GIN und der Java-Klassenbibliothek von Che mit anderen Modulen interagieren. Als Build-Manager kommt Maven zum Einsatz. Ihre Extension muss Teil eines Java Package Name sein, da Che keine leeren Package Names unterstützt. Der Package Name muss ein vollqualifiziertes Set von Unterverzeichnissen unter den /src/main/java- und src/main/resources-Verzeichnissen sein. Für das Folgende werden wir das Beispiel in die example-Package mit folgendem Verzeichnislayout legen:
src/main/java/example/HelloWorldExtension.java src/main/resources/example/HelloWorldExtension.gwt.xml pom.xml Listing 1: Extension: Java Source package example; import com.codenvy.ide.api.extension.Extension; import com.codenvy.ide.api.notification.Notification; import com.codenvy.ide.api.notification.Notification.Type; import com.codenvy.ide.api.notification.NotificationManager; import com.google.inject.Inject; @Extension(title = "Hello world", version = "1.0.0") public class HelloWorldExtension { @Inject public HelloWorldExtension(NotificationManager notificationManager) { notificationManager.showNotification(new Notification("Hello World", Type.INFO)); } }
Das @Extension-Tag in Listing 1 verwandelt diese Java-Klasse in eine Che Extension. Das @Inject-Tag führt eine Konstruktorinjektion aus, die automatisch das für die Extension benötigte notificationManager-Objekt erstellt. Es können viele Arten von Java-Objekten in den Konstruktor eingefügt werden; die Google-Injektion erstellt von ihnen automatisch Instanzen. Diese Extension speist Hello World als eine Informationsmitteilung ein, die in der Eventkonsole erscheint. Die NotificationManager-Klasse wird in Ches Java-Bibliotheken zusammen mit zahlreichen weiteren Helferklassen, die die Interaktion mit der Anwendung ermöglichen, bereitgestellt.
Listing 2: Extension: GWT-Moduldefinition <module> <inherits name="com.google.gwt.user.User"/> <!--This inherits the standard Codenvy module with the applications entry point--> <inherits name="com.codenvy.ide.Api"/> <!--This is the GIN module, which is GWT Injector--> <!--Gin is what performs the special injection of objects when you see @Inject in source--> <inherits name="com.google.gwt.inject.Inject"/> <source path=""/> </module>
Die GWT-Moduldefinitionsdatei in Listing 2 enthält die Basiskonfiguration des GWT-Frameworks. Ein GWT-Modul ist ein einzelnes Konfigurationselement, das in Form von XML-Dateien gespeichert wird. Ein Modul bündelt alle Konfigurationseinstellungen, über die ein GWT-Projekt verfügen muss; was geerbte Module, den Klassennamen der Einstiegsanwendung und den Ort Ihres Klassenpfads einschließt.
Im Fall von Che muss Ihre Extension immer von com.codenvy.ide.Api erben, da hier der Einstiegspunkt enthalten ist, den GWT beim Starten der Klasse aufruft. Eine vollständige Erläuterung der GWT-Moduldefinitionsdateien finden Sie in der GWT-Dokumentation. Es ist ebenfalls möglich, externe JavaScript-Bibliotheken mit einzubinden, die von Ihrer Extension aufgerufen und während der Laufzeit durch Referenzierung in der GWT-Moduldefinitionsdatei geladen werden.
GIN ist eine GWT-Injektionstechnologie, die das dynamische Injizieren von Parametern und Objekten während der Laufzeit ermöglicht. Dank ihr können Objekte gegen eine bestimmte Schnittstelle definiert werden. Anschließend wird durch Konfiguration festgelegt, welche Implementierungen später in den Code injiziert werden sollen. Beispielsweise können Sie das Interface MyInterface.java erstellen, von dem sie mehrere Implementierungen erhalten können; diese können Sie anschließend zu unterschiedlichen Zeitpunkten in die Extension injizieren, z. B. eine für die Qualitätssicherung, eine andere für die Produktion. Auch für GIN steht ein Tutorial bereit.
Im Package plug-sdk ist zudem ein GIN-Tutorial enthalten, das zahlreiche Beispiele für Injektionen liefert. Wenn Sie GIN in Ihrem Projekt verwenden möchten, müssen Sie Ihrem Quellcode eine GIN-Modulklasse hinzufügen, und zwar an folgender Stelle:
/src/main/{package-name}/inject/GinModule.java
Statische Assets, von denen Ihre Extension abhängig ist (Bilder, CSS, Lokalisierungsdateien), können Sie im Resources-Verzeichnis platzieren.
Listing 3: Extension: Maven Pom <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <!--Identifying information. You can change this to match your project.--> <groupId>che-samples</groupId> <artifactId>che-helloworld-extension</artifactId> <version>1.1.0-SNAPSHOT</version> <name>Codenvy Extension :: Hello World</name> <properties> <codenvy.ide.version>3.1.0-SNAPSHOT</codenvy.ide.version> <com.google.gwt.gin.version>2.1.2</com.google.gwt.gin.version> <com.google.gwt.version>2.6.1</com.google.gwt.version> </properties> <dependencies> <dependency> <groupId>com.codenvy.ide</groupId> <artifactId>codenvy-ide-api</artifactId> <version>${codenvy.ide.version}</version> </dependency> <dependency> <groupId>com.google.gwt.inject</groupId> <artifactId>gin</artifactId> <version>${com.google.gwt.gin.version}</version> </dependency> <dependency> <groupId>com.google.gwt</groupId> <artifactId>gwt-user</artifactId> <version>${com.google.gwt.version}</version> <scope>provided</scope> </dependency> </dependencies> <repositories> <repository> <id>codenvy-public-repo</id> <name>codenvy public</name> <url>https://maven.codenvycorp.com/content/groups/public/</url> </repository> </repositories> <!--Indicates where the source and compiled classes should be located--> <build> <sourceDirectory>src/main/java</sourceDirectory> <outputDirectory>target/classes</outputDirectory> <resources> <resource> <directory>src/main/java</directory> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> </build> </project>
Um ein Plug-in zu bauen und zu packen, muss eine Extension über eine Maven-Projektobjektmodelldatei (pom.xml)verfügen, die die erforderliche Konfiguration enthält. Sie können Ihre eigenen Build-Voraussetzungen und Abhängigkeiten in der pom.xml platzieren.
Wenn als Build-Technologie Maven zum Einsatz kommt, so können Ihre pom.xml-Dateien eine Parent-POM designieren, die alle zusätzlichen Abhängigkeiten und Build-Technologien enthält. Für Extensions, die in die Kern-Codebasis von Che integriert werden, stellen wir ein Parent-POM bereit, die geerbt werden muss. Die Parent-POM wird automatisch von einer Abhängigkeitsmanagement-POM geerbt, die unter https://github.com/codenvy/maven-depmgt-pom zu finden ist. Diese POM liefert eine lange Liste von Abhängigkeiten, die einige Dienstprogramme bereithalten, um die Erstellung von Extensions zu unterstützen. Die Dienstprogramme werden in den Tutorials für die jeweilige Extension genauer erläutert.
Alle Beispiele im unter https://github.com/codenvy/plugin-sdk.git zu findenden Repository sind dahingehend verfasst, dass sie Gebrauch von der Abhängigkeitsmanagement-POM machen. Die Parent-POM ruft zwei Anforderungen auf – ein Sortierungs-POM-Plug-in und ein Lizenzcheck. Die Sortierungs-POM legt fest, dass alle POM-Elemente in einer bestimmten Ordnung strukturiert sind; sollte dies nicht der Fall sein, wird eine Fehlermeldung ausgegeben. Das Lizenz-Plug-in legt fest, dass alle Extension-Dateien eine Codenvy-Lizenzdatei enthalten müssen. Dies gilt für jede Che-Extension, die im Rahmen des öffentlichen SaaS-Angebots auf Codenvy.com bereitgestellt wird. Allerdings arbeiten wir an einem neuen Abhängigkeitsmanagement-POM, das Zugang zu all unseren Abhängigkeiten gewährt, aber keinen Lizenz-Header verlangt, was Ihnen die Erstellung eigener Cloud-Extensions mit anderen Lizenzanforderungen ermöglicht.
Das in diesem Artikel vorgestellte Beispiel ist sehr einfach. Im Che-SDK ist eine lange Liste von APIs für die Arbeit innerhalb der Fensterstruktur enthalten. Mit dabei sind Klassen für die Arbeit mit Editoren, Benachrichtigungen, Events, Buildern, Runnern, Themes, Wizards, Keyboards und mehr. Extensions können sowohl serverseitig als auch clientseitig geschrieben und bereitgestellt werden. Außerdem sind Abstraktionen für die Arbeit mit JavaScript-Bibliotheken sowie für Modellierungen innerhalb des Browsers verfügbar (Abb. 3).
Um mehr über die Erstellung Ihrer eigenen Eclipse-Che-Anwendungen und Extensions zu erfahren, besuchen Sie die Eclipse-Che-Seite unter http://eclipse.org/che.
Aus dem Englischen von Michael Thomas.
Aufmacherbild von Shutterstock / Urheberrecht: faithie