Suche
Wir bauen eine einfache Bloganwendung mit JHipster

Angular, Bootstrap und Spring Boot unter einem Hut: durchstarten mit JHipster 4

Matt Raible

© Shutterstock / Vadim Savoski

Bootstrap, Angular und Spring Boot – drei der wohl erfolgreichsten Web Frameworks bringt das Projekt JHipster zusammen. Was mit der aktuellen Version JHipster 4 möglich ist, zeigt dieser Artikel von Java Champion Matt Raible.

Was ist JHipster?

JHipster kombiniert drei Frameworks aus der Web-Entwicklung: Bootstrap, Angular und Spring Boot. Bootstrap war eines der ersten erfolgreichen Web-Komponenten Frameworks. Dessen wichtigster Vorteil war, dass nur ein bisschen HTML nötig war – und schon hat alles funktioniert. Der Java-Coummunity mit all ihren Anstrengungen, Komponenten fürs Web zu entwickeln, hat Bootstrap gezeigt, wie es richtig geht. Bootstrap hat neue Spielregeln innerhalb der HTML/CSS-Entwicklung festgelegt, genau wie Apples Human-Interface-Richtlinien es für iOS-Anwendungen gemacht haben.

JHipster wurde von Julien Dubois am 21. Oktober 2013 gestartet. Das erste Public Release (Version 0.3.1) wurde am 7. Dezember 2013 veröffentlicht. JHipster ist Open Source und unter der Apache 2.0-Lizenz auf GitHub veröffentlicht. Es hat ein Kernteam von 16 Entwicklern und über 280 Kontributoren. Die Projektseite finden Sie hier. Wenn man sich das Projekt auf GitHub anschaut, kann man sehen, dass es überwiegend in JavaScript (42%) und Java (27%) geschrieben wurde.

Im Kern ist JHipster ein Yeoman Generator. Yeoman ist ein Code-Generator, den man mit einem yo-Befehl laufen lassen kann, um vollständige Anwendungen oder auch nützliche Teilstücke zu erzeugen. Yeoman Generatoren fördern das, was das Yeoman-Team den „Yeoman Workflow“ nennt. Das ist eine Client-seitige Palette von Tools, die Entwicklern helfen soll, schnell ansprechende Web-Anwendungen zu bauen. Es stellt das meiste direkt zur Verfügung, sodass man nicht die Mühen eines manuellen Set-ups hat. In JHipster 4 erwarten Entwickler die gewohnten JHipster-Features , aber auch einiges mehr: Genauer gesagt, Angular und Bootstrap 4 Support. Eine kleine Anmerkung: Wenn ich hier von „AngularJS“ schreibe, meine ich Angular 1.x. „Angular“ ist eine nach vorne gerichtete Namensgebung für Angular 2 und noch darüber hinaus.

JHipster 4 installieren

Die Installationsanweisungen für JHipster 4 zeigen einem alle Tools, die man braucht, um eine veröffentliche Version von JHipster zu verwenden.

    1. Installieren Sie Java 8 von Oracle
    2. Installieren Sie Git von https://git-scm.com
    3. Installieren Sie Node.js von http://nodejs.org. Ich habe Node 6.9.1 verwendet, um diesen Artikel zu schreiben
    4. Installieren Sie Yarn über die Yarn Installationsanweisungen
    5. Führen Sie folgenden Befehl aus, um Yeoman auszuführen:
yarn global add yo

6. Führen Sie folgenden Befehl aus, um JHipster zu installieren:

yarn global add generator-jhipster

Ein Projekt erstellen

Um ein Projekt zu erstellen, muss man zunächst ein Terminal-Fenster öffnen und ein Verzeichnis erzeugen, beispielsweise mdkdir blog. Anschließend navigiert man in das Verzeichnis und führt yo jhipster aus. Es werden ein paar Fragen über den Typ der Anwendung gestellt, die man erzeugen will und welche Features man einbauen will. Die folgende Abbildung zeigt meine Auswahl, um eine einfache Blog-Anwendung mit Angular zu erzeugen.

Abb.1.: Generiere die Applikation

Abb.1.: Generiere die Anwendung

Wenn Sie die gleiche Anwendung erzeugen möchten, können Sie die folgende .yo-rc.json-Datei in einem leeren Verzeichnis platzieren und yo jhipster darin ausführen. Man wird keine Fragen mehr gefragt, weil die Antworten bereits in der .yo-rc.json sind.

{
  "generator-jhipster": {
    "jhipsterVersion": "4.0.5",
    "baseName": "blog",
    "packageName": "org.jhipster",
    "packageFolder": "org/jhipster",
    "serverPort": "8080",
    "authenticationType": "jwt",
    "hibernateCache": "ehcache",
    "clusteredHttpSession": false,
    "websocket": false,
    "databaseType": "sql",
    "devDatabaseType": "h2Disk",
    "prodDatabaseType": "postgresql",
    "searchEngine": false,
    "messageBroker": false,
    "serviceDiscoveryType": false,
    "buildTool": "maven",
    "enableSocialSignIn": false,
    "jwtSecretKey": "a895eda190e4ddf6eba453aa725bb4da8a565dfc",
    "clientFramework": "angular2",
    "useSass": true,
    "clientPackageManager": "yarn",
    "applicationType": "monolith",
    "clientFramework": "angular2",
    "testFrameworks": [
      "gatling",
      "protractor"
    ],
    "jhiPrefix": "jhi",
    "enableTranslation": true,
    "nativeLanguage": "en",
    "languages": [
      "en",
      "es"
    ]
  }
}

Das Erzeugen des Projekts wird einige Minuten dauern, das hängt von der Internetverbindung ab. Wenn es fertig ist, sollte der Output folgendermaßen aussehen:

generation-success-1-1024x365

Abb.2.: Generation erfolgreich

Führen sie /.mvnw aus, um die Anwendung zu starten und navigieren sie dann zu http://localhost:8080 mithilfe des favorisierten Browsers. Das erste, was einem auffallen sollte, ist ein adretter junger Mann, der einem erklärt, wie man sich einloggt bzw. registriert.

Abb.3.: Default Homepage

Abb.3.: Default Homepage

Logt man sich mit dem User-Namen admin und Passwort admin ein, bekommt man Zugang und kann durch den Admin-Bereich navigieren. Die Sektion bietet ein ansprechendes UI, auf einer Vielzahl von Monitoring- und Konfigurations-Features von Spring Boot . Es erlaubt zudem, Benutzer zu verwalten.

1user-management-1-1024x596

Abb. 4.: Benutzer-Verwaltung

Es gibt Einsicht in Anwendungs- und JVM-Metriken.

2app-metrics-1024x741

Abb. 5: Anwendungsdaten

Außerdem ermöglicht es die Swagger Docs zu sehen, die mit dem API des Blogs assoziiert sind.

3swagger-docs-1024x542

Man kann folgenden Befehl ausführen (in einem separaten Terminal-Fenster), um den Protractor-Test laufen zu lassen:

yarn run e2e

Hier empfiehlt es sich, das eigene Projekt in Git einzuchecken, so dass man einfach sehen kann, welche Veränderungen ab sofort getätigt wurden.

git ini
git add
git commit -m "Project created"

Entitäten erzeugen

Für jede Entität, die man erzeugen will, braucht man eine Datenbank-Tabelle, ein Liquibase Change Set, eine JPA-Entitäten-Klasse, ein Spring Data JpaRepository Interface, eine Spring MVC RestController -Klasse, einen Angular Model / State / Komponent / Dialog Komponenten / Service und verschiedene HTML-Seiten für jede Komponente. Außerdem sollte man einen Integrations-Test haben um zu verifizieren, dass alles funktioniert und Perfomance-Tests um sicherzustellen, dass alles schnell läuft. In einer idealen Welt braucht man zudem noch einen Unit- sowie Integrations-Test für den Angular-Code. Die gute Nachricht ist, dass JHipster diesen ganzen Code für uns erstellen kann, inklusive Integrations-und Performance-Test. Sofern man Entitäten mit Relationships hat, wird es außerdem das notwendige Schema erzeugen, um diese zu unterstützen (mittels Foreign Key), sowie den TypeScript- und HTML-Code, um sie zu verwalten. Man kann eine Validierung so einrichten, dass bestimmte Felder notwendig sind und zudem ihre Länge kontrollieren.

JHipster unterstützt verschiedene Methoden, um Code zu erstellen. Die erste benutzt einen Entity Sub-Generator. Dieser Entity Sub-Generator ist ein Command-Line Tool, dass einen mit Fragen konfrontiert, die man beantworten muss. JDL-Studio ist ein Browser-basiertes Tool, mit dem man das Domain-Modell mit der JHipster Domain Language (JDL) definiert. Zu guter Letzt gibt es JHipster-UML als Option für diejenigen, die UML mögen. Unterstützte UML-Editoren sind Modelio, UML Designer, GenMyModel und Visual Paradigm. Ich mag die visuelle Beschaffenheit des JDL-Studios, weswegen ich es auch für dieses Projekt benutzt habe. Im Anschluss (Abb. 7) sieht man das Entitätendiagramm und den JDL-Code, der nötig ist, um einen einfachen Blog zu erstellen, der Blogs, Einträge und Tags hat.

4jdl-studio-1024x754

Abb. 7. Blog-Entitäts-Diagramm

Wer jetzt immer noch mitmachen möchte, kann auf diese URL klicken oder den Inhalts des folgenden Listings auf die Festplatte kopieren und einfügen.

entity Blog {
    name String required minlength(3),
    handle String required minlength(2)
}
 
entity Entry {
    title String required,
    content TextBlob required,
    date ZonedDateTime required
}
 
entity Tag {
    name String required minlength(2)
}
 
relationship ManyToOne {
    Blog{user(login)} to User
        Entry{blog(name)} to Blog
}
 
relationship ManyToOne {
    Entry{blog(name)} to Blog
}
 
relationship ManyToMany {
    Entry{tag(name)} to Tag{entry}
}
 
paginate Entry, Tag with infinite-scroll

Man kann folgenden Befehl (in dem Ordner blog) ausführen, um die Datei zu importieren und Entitäten, Tests und eine UI zu erstellen:

yo jhipster:import-jdl ~/Downloads/jhipster-jdl.jh

Man wird dann aufgefordert, die src/main/resources/config/liquibase/master.xml zu überschreiben. Tippen Sie a um diese und andere Dateien zu überschreiben. Wenn man die Anwendung mit /.mvnw  neu startet und sie mit yarn start ausführt, kann man sich das UI für die erstellten Entitäten ansehen. Erstellen Sie ein paar Blogs für die existierenden Benutzer admin und user und zusätzlich ein paar Blog-Einträge.

5blogs-1024x540

Abb. 8: Blogs.

6entries-1024x595

Abb. 9: Einträge

Auf den oberen Screenshots kann man erkennen, dass die Benutzer die Daten der anderen Benutzer sehen und auch bearbeiten können. Man kann die veränderten Entitäten nun auf GitHub einchecken.

git init
git add .
git commit -m "Entities generated"

Businesslogik hinzufügen

Tipp: Unter folgendem Link kann man erfahren, wie man eine IDE mit dem eigenen JHipster-Projekt  konfigurieren kann. Es sind Anweisungen für Eclipse, IntelliJ IDEA, Visual Studio Code und NetBeans vorhanden. Um weitere Sicherheit für die Blogs und Einträge hinzuzufügen, öffnet man BlogResource.java und sucht dort die getAllBlogs() -Methode. Folgende Zeile muss geändert werden:

src/main/java/org/jhipster/web/rest/BlogResource.java

List<Blog> blogs = blogRepository.findAll();

Zu:

src/main/java/org/jhipster/web/rest/BlogResource.java

List<Blog> blogs = blogRepository.findByUserIsCurrentUser();

Die findByUserIsCurrentUser() Methode wurde mit JHipster in der BlogRespository -Klasse erzeugt und ermöglicht es dem gegenwärtigen Benutzer, die Ergebnisse zu beschränken.

src/main/java/org/jhipster/repository/BlogRepository.java

public interface BlogRepository extends JpaRepository<Blog,Long> {

@Query("select blog from Blog blog where blog.user.login = ?#{principal.username}")
List<Blog> findByUserIsCurrentUser();

}

Nachdem das verändert wurde, sollte eine Re-Kompilierung von BlogResource einen Neustart der Anwendung triggern, mithilfe der Entwickler-Tools von Spring Boot. Wenn man zu http://localhost:8080/blogs navigiert, sollte man nur den Blog vom aktiven Benutzer vorfinden.

7blogs-admin-1024x489

Abb. 10: Admin Blog

Um die selbe Logik für die Einträge hinzuzufügen, öffnet man EntryResource.java und sucht die getAllEntries() -Methode. Ändern Sie folgende Zeile:

src/main/java/org/jhipster/web/rest/EntryResource.java

Page<Entry> page = entryRepository.findAll(pageable);

zu:

src/main/java/org/jhipster/web/rest/EntryResource.java

Page<Entry> page = entryRepository.findByBlogUserLoginOrderByDateDesc(SecurityUtils.getCurrentUserLogin(), pageable);

Erstellen Sie diese Methode innerhalb der EntryRepository -Klasse mithilfe ihres IDEs. Es sollte wie folgt aussehen:

src/main/java/org/jhipster/repository/EntryRepository.java

Page<Entry> findByBlogUserLoginOrderByDateDesc(String currentUserLogin, Pageable pageable);

Rekompilieren Sie die beiden veränderten Klassen und stellen Sie sicher, dass der Benutzer User nur diejenigen Einträge sieht, die von ihm auch erstellt wurden.

8entries-user-1024x494

Abb. 11: Benutzer Einträge.

Sobald die Veränderungen gemacht wurden, sollten sie ins Git eingecheckt werden.

git add
git commit -m "Add business logic"

Vielleicht fällt Ihnen auf, dass die Anwendung nicht wie ein Blog aussieht und kein HTML im Content-Feld erlaubt.

UI-Erweiterungen erstellen

Wenn man UIs auf einer von JHipster erstellten Anwendung entwickelt, ist es gut, die Veränderungen angezeigt zu bekommen, sobald man eine Datei abspeichert. JHipster 4 nutzt Browsersync und Webpack, um dieses Feature anzutreiben. Um es zu ermöglichen, muss man folgende Befehlszeile im Verzeichnis blog ausführen:

yarn start

In dieser Sektion kann man folgendes verändern: Das gerenderte Content Feld, um HTML anzuzeigen, sowie die Liste der Einträge, sodass es wie ein Blog aussieht.

HTML erlauben

Wenn man HTML in das Content -Feld eines Blog-Eintrags eingibt, wird man bemerken, dass es auf der Listen-Ansicht „Escaped“ ist.

9entries-with-html-escaped-1024x494

Abb. 12: Escaped HTML

Um dieses Verhalten zu verändern, muss man entry.component.html öffnen und die folgende Zeile verändern:

src/main/webapp/app/entities/entry/entry.component.html

<td>{{entry.content}}</td>

Zu:

src/main/webapp/app/entities/entry/entry.component.html

 <td [innerHTML]="entry.content"> </td>
10entries-with-html-1-1024x494

Abb. 13: HTML in Einträgen

Wenn man diese Veränderungen gemacht hat, wird man sehen, dass das HTML nicht mehr länger escaped aussieht.

Layout verbessern

Um eine die Liste der Einträge wie auf einem Blog aussehen zu lassen,  muss man <div class="table-responsive"> mit HTML ersetzen, sodass es ein Stapel-Layout in einer einzelnen Kolumne benutzt.

src/main/webapp/app/entities/entry/entry.component.html

<div class="table-responsive" *ngIf="entries">
    <div infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
        <div *ngFor="let entry of entries; trackBy: trackId">
            <h2>{{entry.title}}</h2>
            <small>Posted on {{entry.date | date: 'short'}} by {{entry.blog.user.login}}</small>
            <div [innerHTML]="entry.content"></div>
            <div class="btn-group mb-2 mt-1">
                <button type="submit"
                        [routerLink]="['/', { outlets: { popup: 'entry/'+ entry.id + '/edit'} }]"
                        replaceUrl="true"
                        class="btn btn-primary btn-sm">
                    <span class="fa fa-pencil"></span>
                    <span class="hidden-md-down" jhiTranslate="entity.action.edit">Edit</span>
                </button>
                <button type="submit"
                        [routerLink]="['/', { outlets: { popup: 'entry/'+ entry.id + '/delete'} }]"
                        replaceUrl="true"
                        class="btn btn-danger btn-sm">
                    <span class="fa fa-remove"></span>
                    <span class="hidden-md-down" jhiTranslate="entity.action.delete">Delete</span>
                </button>
            </div>
        </div>
    </div>
</div>

Jetzt sieht es wie ein richtiger Blog aus!

11blog-entries-1024x669

Abb. 14: Blog Einträge

Alle Einträge sollten ins Git committet werden:

git add .
git commit -m "UI enhancements"

In die Cloud deployen

Eine JHipster App kann überall dort deployt werden, wo eine Spring-Boot-Anwendung deployt werden kann. JHipster enthält Support für das Deployen in Cloud Foundry, Heroku, Kubernetes, AWS und AWS mit Boxfuse. Ich benutze Heroku in diesem Beispiel, weil das Hosten kostenlos ist.

Wenn man eine JHipster-Anwendung für die Produktion vorbereitet, empfiehlt es sich, die vor-konfigurierten „Produktions“-Profile zu benutzen. Mit Maven kann man die Anwendung packen, indem man das prod -Profil beim Bau spezifiziert.

mvn -Pprod package

Das Produktions-Profil wird benutzt, um einen optimierten JavaScript-Client zu bauen. Man kann es anrufen, indem man das Webpack nutzt, wofür wiederum yarn run webpack:prod ausgeführt werden sollte. Das Produktionsprofil konfiguriert zudem Gzip-Kompression mit einem Servlet-Filter, Cache Header und Monitoring via Metrics. Wenn man einen Graphite-Server in der application-prod.yaml -Datei hat, wird die eigene Anwendung automatisch metrische Daten zu dieser senden. Wird dieser Befehl ausgeführt, erhält man wahrscheinlich einen Fehler im Test:

Results :

Tests in error:
  BlogResourceIntTest.getAllBlogs:171 » NestedServlet Request processing failed;...
 
Tests run: 62, Failures: 0, Errors: 1, Skipped: 0

Der Grund dafür zeigt sich in einem Stack Trace im Terminal:

getAllBlogs(org.jhipster.web.rest.BlogResourceIntTest)  Time elapsed: 0.041 sec  &lt;&lt;&lt; ERROR!

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is

org.springframework.dao.InvalidDataAccessApiUsageException: Authentication object cannot be null;

nested exception is java.lang.IllegalArgumentException: Authentication object cannot be null

Um das zu korrigieren, kann man @WithMockUser von Spring Security Test benutzen. Öffnen Sie nun BlogResourceIntTest.java und fügen Sie UserRepository als eine Abhängigkeit ein.

src/test/java/org/jhipster/web/rest/BlogResourceIntTest.java

 
@Autowired
private UserRepository userRepository;

Ändern sie die createEntity() -Methode so, dass sie nicht statisch ist und die userRepository nutzt, um einen Benutzer auf die Blog-Entität zu setzen.

 
public Blog createEntity(EntityManager em) {
    Blog blog = new Blog()
            .name(DEFAULT_NAME)
            .handle(DEFAULT_HANDLE)
            .user(userRepository.findOneByLogin("user").get());
    return blog;
}

Füge @WithMockUser hinzu, um die getAllBlogs() -Methode zu erhalten.

 
@Test
@Transactional
@WithMockUser
public void getAllBlogs() throws Exception {

Nachdem der Test korrigiert wurde, sollte man in der Lage sein, mv -Pprod packe ohne Fehler auszuführen. Um diese Anwendung auf Heroku zu deployen, habe ich mich in meinen Heroku Account eingeloggt, indem ich heroku login über die Befehlszeile ausgeführt habe. Ich hatte bereits Heroku CLI installiert.

 
$ heroku login
Enter your Heroku credentials.
Email: matt@raibledesigns.com
Password (typing will be hidden):
Logged in as matt@raibledesigns.com

Ich habe yo jhipster:heroku so ausgeführt, wie es in der Dokumentation Deployen in Heroku empfohlen wird. Wenn ich dazu aufgefordert werde, benutze ich den Namen „jhipster4-demo“ für meine Anwendung.

$ yo jhipster:heroku
Heroku configuration is starting
? Name to deploy as: jhipster4-demo
? On which region do you want to deploy ? us

Using existing Git repository

Installing Heroku CLI deployment plugin

Creating Heroku application and setting up node environment
heroku create jhipster-4-demo
https://jhipster-4-demo.herokuapp.com/ | https://git.heroku.com/jhipster-4-demo.git

Provisioning addons
Created heroku-postgresql --as DATABASE

Creating Heroku deployment files
create src/main/resources/config/bootstrap-heroku.yml
create src/main/resources/config/application-heroku.yml
create Procfile

Building application
...
remote: https://jhipster-4-demo.herokuapp.com/ deployed to Heroku
remote:
-----&gt; Done

Your app should now be live. To view it run
heroku open
And you can view the logs with this command
heroku logs --tail
After application modification, redeploy it with
yo jhipster:heroku

Ich führe zuletzt heroku open aus, logge mich als admin ein und freue mich zu sehen, dass es funktioniert!

12jhipster4-demo-heroku-1024x644

Abb. 15: JHipster 4 Demo auf Heroku

Um die Veränderungen auf Heroku zu speichern, muss man sie zu Git committen:

git add .
git commit -m "Deploy to Heroku"

Noch mehr dazulernen

Ich hoffe es hat Spaß gemacht zu lernen, wie JHipster für den Bau von Web-Anwendungen genutzt werden kann! Es ist ein kluges Projekt, mit einem einfach anzuwendenden Entitäts-Generator, einem hübschen UI und vielen Spring Boot Best Practices. Das Projektteam folgt fünf einfachen Policies, die ich kurz wiedergeben möchte:

  • Das Entwicklerteam stimmt über die Policies ab.
  • JHipster nutzt Technologien mit den Standardeinstellungen, sofern es möglich ist.
  • Weitere Optionen werden dem Code nur dann hinzugefügt, wenn sie wirklich Mehrwert bieten.
  • Für Java-Code, kann man den IntelliJ IDEA Default-Formatierungs- und Programmierrichtlinien folgen.
  • Man benutze explizit festgelegte Versionen für die Bibliotheken von Dritten.

Diese Policies helfen einem Projekt, eine klare Linie zu behalten und formen den Entwicklungsprozess. Wenn man Features hat, die man hinzufügen möchte oder bereits existierende verfeinern will, kann man das Projekt auf GitHub anschauen und bei seiner Entwicklung helfen und unterstützen. Wir suchen immer nach mehr Unterstützung!

Jetzt, wo sie wissen, wie man Angular, Bootstrap 4 und Spring Boot mit JHipster benutzt, so ziehen sie fort und entwickeln sie großartige Anwendungen!

Source Code

Der Source Code für dieses Projekt ist verfügbar auf GitHub unter https://github.com/mraible/jhipster4-demo .

eclipseorb_color Dieser Artikel wurde zuerst in der Januar 2017 Ausgabe des Eclipse Newsletters veröffentlicht: Exploring New Technology.

Weitere Informationen und Artikel findet man im Eclipse Newsletter.

Geschrieben von
Matt Raible
Matt Raible
Matt Raible ist Web-Entwickler und Großmeister in Java. Er liebt Architektur und beeindrucke UIs mithilfe von CSS und JavaScript zu bauen. Wenn er nicht Okta evangelisiert oder es open-sourct, dann ist er mit seiner Familie zum Ski Fahren, fährt einen seiner VWs herum oder genießt Craft-Bier. Er schreibt auf seinem persönlichen Blog und außerdem kann man ihn auf Twitter @mraible finden. Er ist Entwickler beim JHipster Team und Autor vom JHipster Mini-Book für InfoQ.
Kommentare
  1. Simon Ludwig2017-07-22 23:00:17

    Vielen Dank, hat mir geholfen!

  2. Patrick2017-12-12 11:20:14

    Danke für den tollen Artikel!
    JHipster sieht für mich super spannend und sehr sinnvoll aus.
    Was ich aber nicht ganz verstehe ist, weshalb generierter und eigener Code nicht strikte getrennt wird. Das scheint mir (zugegebenermaßen: ohne es ausprobiert zu haben) etwas unglücklich.
    Ich würde beispielsweise nie generierten Code in meinem GIT einchecken wollen.
    Disclaimer: ich hatte bisher wenig mit Web-Entwicklung am Hut...

Schreibe einen Kommentar

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