Webseiten erstellen mit JHipster

In diesem Blogartikel möchte ich einen weiteren Codegenerator vorstellen. Vor einiger Zeit hat Vivien einen Artikel über Celerio geschrieben – hier möchte ich JHipster vorstellen. JHipster ist eine Sammlung von Kommandozeilenwerkzeugen zum Erstellen von modernen Webanwendungen. Der Generator baut auf dem Yeoman Scaffolding Tool auf und soll ein Grundgerüst für die zu entwickelnde Webapplikation erstellen. Diese verwendet Spring Boot Framework für das Backend und AngularJS oder wahlweise AngularJS 2 für das Frontend. Genau diese Technologiekombination hat mich neugierig gemacht, weil wir beide Technologien bereits verwenden und auch weiterhin in neuen Projekten verwenden möchten. Da ist jede Hilfe beim Erstellen einer neuen Anwendung willkommen.

Die JHipster Webseite verspricht viel und listet eine Vielzahl von Optional und Frameworks für die zu erstellende Anwendung. Dazu gehöhren:

  • Authentifizierung und Authorisierung mit verschiedenen Optionen (Session basiert, Token basiert oder OAuth2)
  • „Responsive Web Design“ durch Verwendung von Bootstrap und HTML5Boilerplate
  • Internationalisierung
  • Sass Unterstützung
  • Monitoring der Anwendung
  • Cachingunterstützung (EhCache oder Hazelcast)
  • Nachvollziehbarkeit bei Änderungen (Auditing)
  • Umfangreiche Konfigurationsmöglichkeiten für das Logging
  • Liquibase zur Verwaltung von Datenbankversionen
  • Unterstützung von SQL und NoSQL Datenbanken
  • Websocketunterstützung (optional)

Das hört sich vielversprechend an. Im Folgenden möchte ich Antworten auf folgende Fragen finden:

  • Ist der Code in einer einfach verständlichen Struktur abgelegt?
  • Wie einfach sind Codeanpassungen?
  • Sind die verwendeten Frameworks aktuell und kann man diese auf neue Versionen aktualisieren?
  • Kann man Code später dazu generieren?

Installation von JHipster

Zur Installation von JHipster werden folgende Tools benötigt.

Eine Software zur Versionsverwaltung wie Git sollte ebenfalls vorhanden und Windowsbenutzern ist die Installation einer alternativen Konsole (z.B. cmder) zu empfehlen. Zur Erinnerung: JHipster ist eine Sammlung von Kommandozeilenwerkzeugen.

Sind beide Abhängigkeiten vorhanden, kann die JHipster Installation mit folgenden Befehlen durchgeführt werden:

Erstellen einer Web Anwendung

Sind alle benötigten Tools installiert, kann der Generator mit dem Befehl yo jhipster gestartet werden. Vorher sollte in der Verzeichnis gewechselt werden, in dem der Code generiert werden soll.

JHipster bietet eine Reihe von Optionen, um die zu konfigurierende Anwendung nach den eigenen Bedürfnissen anzupassen. Zum Einstieg habe ich mich für die folgenden Optionen entschieden:

project_setup

Sind alle Entscheidungen getroffen, wird der Code generiert die benötigten Frameworks werden heruntergeladen und installiert. Vorausgesetzt Maven ist bereits installiert, dann läßt sich die Anwendung mit dem Befehlt  mvn spring-boot:run bauen und starten. Wenn alles fertig ist, kann die Webseite im Browser unter  http://localhost:8080  aufgerufen werden. Die „nackte“ Anwendung hat eine Startseite, eine Benutzerverwaltung und einen durchaus umfangreichen Administrationsbereich. Die Startseite hat ein „responsive Design“ und passt sich dynamisch der Browserauflösung an. Die Startseite ist auf folgendem Screenshot zu sehen:

jhipster-landingpage

Um die Anwendung mit eigener Logik zu erweitern, können Entitiäten generiert werden.

Erstellen von Entitäten

Für unser Tutorial wollen wir ein ein einfaches Datenmodell mit drei Entitäten mit folgenden Abhängigkeiten betrachten:

Entities für das Datenmodelle können entweder interaktiv mit Hilfe des Kommandozeilenwerkzeugs oder mit dem von JHipster bereitgestellten OnlineTool (JDL Studio) erstellt werden. Im Beispiel habe ich mich für letzteres entschieden, da Änderungen am Datenmodell und die erneute Codegenerierung viel Schneller mit einer Textdatei gehen, als jedes Mal alle Entitäten mit der Kommandozeile zu Erstellen. Außerdem ist die Reihenfolge beim Erstellen der Entitäten mit der Kommandozeile wichtig, um Abhängigkeiten korrekt abzubilden. Mehr Informationen über die JHipster Domain Language (JDL) gibt es auf der JHipster Webseite. Das für unser Beispiel verwendete Datenmodell kann hier (bitte in entities.jh umbenennen) heruntergeladen werden.

Hat man die Datei erstellt, wird mit dem Befehl  yo jhipster:import-jdl entities.jh  Code generiert. Alternativ können mit dem Befehl  yo jhipster:entity <Name der Entität>  interaktiv auf der Commandozeile Entitäten und Abhängigkeiten erstellt werden.

Für jede Entität werden

  • eine Tabelle in der Datenbank
  • ein Liquibase change set
  • eine JPA Entityklasse
  • ein Spring Data JPA Repository inklusive Restcontroller
  • ein AngularJS Router, Controller und Service
  • ein Html View zum Anzeigen und Editieren des Entities
  • sowie Integrations- und Performancetests

generiert.

Aktualität der verwendeten Frameworks

Zum Zeitpunkt des Schreibens verwendet JHipster die aktuelle Version des Spring Boot Frameworks (1.5.2). AngularJS 1 wird in Version 1.5.8 verwendet. Hier kommt nicht die aktuelle Version der AngularJS Webseite (1.6.3) zum Einsatz. Im zusammenspiel mit AngularJS1 kommt Bootstrap in der nicht mehr ganz aktuellen Version 3 zum Einsatz. Erst mit AngularJS 2 im Frontend, dessen Unterstützung sich im Beta Stadium befindet, wird Bootstrap 4 benutzt. Dass kann darauf hindeuten, daß mit dem der Unterstützung von AngularJS 2 nicht mehr auf die Aktualität des Frontends mit AngularJS 1 geachtet wird. Falls gewünscht, lassen sich die Frontendkomponenten aber recht einfach mit Bower auf neuere Versionen aktualisieren.

Verzeichnisstruktur

Der Code ist in folgender Verzeichnisstruktur abgelegt:

Im Hauptverzeichnis sind Konfigurationen für die eingesetzten Werkzeuge, wie zum Beispiel Maven, Bower, Gulp, Git abgelegt. Der Code für die Anwendung befindet sich Maven typisch im Verzeichnis src/main, Tests sind in src/test abgelegt. Anwendungsspezifische Konfigurationen befinden sich in den src/**/resources  Verzeichnissen. Dazu gehören Templates für statische HTML Seiten, Sprachdateien, Templates für HTML Emails, und Datenbank- und Logging Konfigurationen. Die Struktur des Codes für Front bzw. Backend werden wir im folgenden genauer betrachten.

Spring Boot Backend

Die Verzeichnisstruktur im Backend ist für mich als Java Entwickler sehr vertraut. Die Anwendung folgt der Struktur einer klassischen Spring MVC Anwendung. Es exisitieren Packages für Konfiguration (config), Domainobjekte (domain), Datenbackzugriff (repository), Authentifizierung (security), Serviceklassen mit dem Code für die Businesslogik (service), und Restendpunkte (web). Der Datenbankzugriff wird mit dem Spring-Data Framework realisiert. Das heißt es werden nur Interfaces generiert.  Die eigentliche Implementierung wird vo Spring Data zur Laufzeit generiert.

Die Struktur wirkt sehr vertraut und ist übersichtlich strukturiert. Nicht benötigte Funktionalitäten können bei Bedarf einfach entfernt oder deaktiviert werden. Für jedes Entity existiert ein Domainobjekt, ein Spring Data Repository und eine Klasse mit Restendpunkten für den Zugriff auf die Funktionalitäten vom Frontend. Wie in unserem Beispiel gewünscht wurde auch eine Serviceklasse und ein DTO Objekt mit Hilfsklassen zum Konvertieren zwischen Entity und DTO angelegt. Domainobjekte und Repositories enthalten Code der leicht verständlich ist. Die Domainobjekte beinhalten die Felder mit javax.persistence Annotationen, Getter und Setter Methoden, Implementierungen für hashCode und equals sowie builder Methoden. Ich finde mich auf Anhieb gut im Code zurecht. Eine Änderung – falls notwendig – kann sehr einfach gemacht werden. Im Paket Service sind Interfaces und Implementierungen getrennt generiert, enthalten keine Logik, sondern nur wenige Zeilen Code um vom Entitiy in das DTO zu konvertieren, wie folgendes Beispiel zeigt:

Integrationstests

JHipster erstellt Integrationstests für das Backend zum Tested der Restendpunkte. Die Tests folgen den Empfehlungen des Spring Boot Frameworks und basieren auf JUnit 4 und dem MockMvc Framework. Sie Testen die Endpunkte für Erstellen, Aktualisieren und Löschen von Entities, sowie korrektes Verhalten in Fehlerfällen. Dass heisst, wenn ein benötigtes Feld nicht im Request gesetzt ist wird eine Antwort mit HTTP Status 400 erwartet und das Objekt wurde nicht in der Datenbank persistiert. Das Erweitern um eigene Testfälle Unit und Integrationstests ist problemlos möglich.

AngularJS Frontend

Das Frontend wird im Ordner src/main/webapp  erstellt und folgt John Papa’s AngularJS 1 Styleguide. Die Ordernstruktur ist übersichtlich strukturiert. Im Verzeichnis src/main/webapp/app befindet sich der Code der Anwendung der nach Funktionalitäten gruppiert ist. Alle Seiten rund um die Administration befinden sich im src/main/webap/app/admin Ordner. Code für die erstellten Entitäten sind in einem jeweils eigenem Ordner unter src/main/webapp/entities. So läßt sich der generierte Code leicht aufspühren. Sprachdateien sind im Verzeichnis  src/main/webapp/i18n/ abgelegt und lassen sich somit unabhängig vom Code bearbeiten.

Code Statistiken

Ein Blick auf die Statistik des generierten Codes mit Hilfe von cloc lässt den Eindruck entstehen, das man von der Menge des Codes erschlagen wird. Die Basisanwendung umfasst stolze 2742 Dateien mit mehr als 250.000 Zeilen Code. Glücklicherweise gehört der meiste Code zu den verwendeten WebFrameworks, die sich sich im Ordner src/main/webapp/bower_components/ befinden.

Anpassungen

Das Backend bindet die Spring Boot Developer Tools ein, um die Entwicklung angenehmer zu gestalten. Das macht es indem es Caches deaktiviert um Änderungen sofort sichtbar zu machen und die Anwendung automatisch neu zu starten, sobald Änderungen im Classpath entdeckt werden. Ansonsten kann Postman benutzt werden, um Restendpunkte aufzurufen.

Anpassung am Frontend sind durch die Einbindung von Browersync sehr angenehm. Damit sind Codeänderungen im Frontendcode sofort nach dem Speichern sichtbar. Um Browersync zu aktivieren muss das Backend bereits laufen. Anschliessend kann mit dem Befehl  gulp  im Projektverzeichnis das Frontend inklusive Browsersync gestartet werden. Wenn alles geklappt hat, ist die Oberfläche ist unter http://localhost:9000/ im Browser erreichbar und wenn du Änderungen im Verzeichnis src/main/webapp speichert aktualisiert der Browser automatisch die angezeigte Seite und macht Änderungen sofort sichtbar.

Fazit

JHipster macht was er verspricht. Es generiert ein Grundgerüst für eine moderne Webanwendung basierend auf Spring Boot und AngularJS. Es sind keinerlei Abhängigkeiten zu JHipster eigenen Code vorhanden, was sehr positiv zu werten ist. Sollen diese Technologien die Wahl der Wahl im neuen Webprojekt sein, ist es auf jeden Fall einen Versuch Wert die Anwendung mit Hilfe von JHipster innerhalb kürzester Zeit aufzusetzen. Es Bedarf zwar einige Einarbeitungszeit um mit dem erstelltem Projekt inklusive Code vertraut zu werden, aber die Vorteile liegen auf der Hand: Das Projektsetup spart eine Menge Zeit, der generierte Code ist übersichtlich strukturiert und die angebotenen Funktionalitäten sind in den meisten Projekten sehr nützlich.

Für Anfänger kann der generierte Code auch als Referenz für ein gutes Projektsetup dienen. Die vorhandene Struktur läßt sich sehr gut um eigenen Code erweitern. Für unser Beispiel für den Blogartikel haben wir eine monolythische Architektur gewählt. JHipster unterstützt aber auch Microservicearchitekturen basierend auf dem Netflix OSS Stack und weitere interessante Optionen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.