Webserver-Applikation Teil 3 mit dem Vert.x-Framework – Währungsumrechner

Dies ist der dritte Teil des Vertex-Währungsumrechner-Projekts. Wir schreiben dazu eine kleine SPA, inklusive Bedienungsoberfläche.

Autor Mirko Eberlein
Datum 18.10.2017
Lesezeit 12 Minuten

Im dritten Teil unseres Vertex-Währungsumrechner-Projekts schreiben wir nun eine kleine SPA (Single Page Application), die unseren Service nutzt und dem User als Bedienungsoberfläche dient.

Im ersten Teil unserer kleinen Applikation habe ich euch gezeigt, wie man ein Vert-X-Maven-Projekt aufsetzt und wir haben unseren ersten kleinen Service geschrieben. Der Webservice hat eine statische Ressource geliefert und wir konnten unseren kleinen Webserver testen.

Vert.x Server-Applikation Teil 1: Server aufsetzen

Im zweiten Teil habe ich euch dann gezeigt, wie ihr dynamische REST-Services erzeugt und dieses mappt. Ausserdem haben wir noch die Tests dafür geschrieben. Als Ergebnis haben wir festgestellt, dass wir erfolgreich unseren calculate Service im Browser aufrufen können.

Vert.x Server-Applikation Teil 2: Währungsrechner aufsetzen

Was benötigen wir also für unsere SPA? Zunächst mal HTML5 und CSS3. Dazu verwende ich noch Bootstrap als CSS-Framework. Dies bringt mir die mobile Skalierbarkeit gleich mit.

Als Erstes bauen wir die Ordnerstruktur auf

Unter src/main/ressources lege ich den Ordner webroot an.
In diesem Ordner erstelle ich folgende Ordner: css, currency,ui,vendor und wro.
Unter ui erstelle ich noch den Ordner Home und unter vendor _jquery, angular, bootstrap und fonts.

Webserver-Applikation Teil 2 mit dem Vert.x-Framework
Fangen wir mit dem Vendor-Ordner an. Dort sind alle Fremdbibliotheken eingefügt, die ich verwenden werde. Wundert ihr euch, warum _jquery mit Unterstrich geschrieben ist? Dies hat den Hintergrund, dass ich alle Javascript-Files der Fremdbibliotheken in einem File bündeln möchte. Dazu verwende ich das Maven-Plugin wro4j. Das heisst, alle Fremdbibliotheken werden in einem Javascript File vendor.js liegen. Alle eigenen JS Files werden in dem File core.js abgelegt.

Die erstellten Dateien lege ich dann im Ordner Currency ab.

Webserver-Applikation Teil 2 mit dem Vert.x-Framework

Das Plugin dient zum einen dem Zusammenführen der verschiedenen Dateien. Zusätzlich benutze ich es noch, um sie zu minimieren. Das heisst, ich kann mein Java-Script ordentlich mit Platz schreiben. Ich kann es in verschiedene kleine Scripts kapseln und bekomme am Ende ein fertiges File.

Das heisst, in meiner index.htm werde ich nur folgende vier Dateien verwenden:

<script src="currency/vendor.min.js"></script>
<script src="currency/core.min.js"></script>
<link rel="stylesheet" href="currency/vendor.css" />
<link rel="stylesheet" href="currency/core.css" />

Die index.htm-Datei enthält ausserdem eine Top-Navigation und einen Footer.

<body ng-app="currencyWeb">
<nav class="navbar navbar-inverse">
<div class="container white">
<h1>Currency - Währungsrechner Digicomp</h1>
</div>
</nav>
<div ui-view>
</div>
<footer role="contentinfo"
class="navbar navbar-inverse navbar-fixed-bottom">
<div class="container">
<p class="pull-right">
Designed and built in Switzerland by
<a target="blank" href="http://mirko-eberlein.com">Mirko Eberlein</a>.
</p>
</div>
</footer>
</body>

Die Navigation enthält nur den H1 als Titel. Hier könnte man später noch problemlos ein Menü integrieren. Der Footerbereich ist beispielhaft eingefügt und man hätte ihn für unsere Applikation auch einfach weglassen können. Das ui-view div dient als Content-Holder in unserer Applikation. Auch dieser wäre nicht nötig, da wir nur eine Ansicht haben. Auch hier dient es dazu, euch näher zu bringen, wie man eine grössere Applikation aufbaut. Ich habe hier nur Standard-Bootstrap-Klassen verwendet. Im Body-Tag sehen wir noch ng-app=»currency Web». Das ist der Initiator unserer Angular App.

Schauen wir uns nun das erste Java Script File currency.js an

(function(){
"use strict";
var currencyWeb = angular.module('currencyWeb', 'ngResource')
.config(function($urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
});
})();

Sehen wir uns diesen Code an. Zuerst erkläre ich, warum wir den Ausdruck (function(){ … })() verwenden. Durch diesen Ausdruck sorgt man dafür, dass man den Namespace sauber hält. Als Nächstes bringe ich den Ausdruck «use strict», womit ich dem Browser mitteile, dass ich einen strengeren Massstab wünsche. Ich muss dann Variablen immer deklarieren. Die Auslegung ist dann etwas strenger, dafür ist meiner Meinung nach die Fehleranfälligkeit im fertigen Programm kleiner.

Mit dem urlRouteProvider sage ich, dass default auf /home geleitet wird.

Das war es schon von den zwei Hauptdateien. Gehen wir nun in den ui -> ordner.

Webserver-Applikation Teil 2 mit dem Vert.x-Framework

Dort finden wir vier Dateien.

Fangen wir mit home.js an.

(function(){
"use strict";
angular.module('currencyWeb')
.config( '$stateProvider', function($urlRouterProvider) {
$stateProvider
.state('home', {
url: "/home",
templateUrl: "ui/Home/home.html",
});
});
})();

Dies ist eine Angular-Config.

Hier gebe ich den stateProvider und den urlRouterProvider mit. Ich gebe an, dass wenn /home aufgerufen wird, der status .home gesetzt wird. Ausserdem wird dann in die ui-view das templateUrl «ui/Home/home.html» geladen.

Schauen wir uns nun diese Datei an. Ich definiere in dem Container – div den Angular Controller HomeController. In den beiden SelectFeldern changeFrom und changeTo verknüpfe ich mit ng-Model Angular. Mit einem ng-repeat zeige ich die vorhandenen Währungen an. Wie die Verknüpfung geschieht, erkläre ich dann im Controller. Das Input Feld amount ist ebenfalls mit einem Angular Model verknüpft. Der Input-Button ist mit einem Angular Event onclick versehen, der die Funktion calculate() aufruft.

Am Ende sehen wir noch zwei Alerts, die als Text jeweils eine Angular-Scope-Variable enthalten.

<div class="container" ng-controller="HomeController">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h3 class="panel-title">Kursdaten</h3>
    </div>
  </div>
  <div class="panel panel-default">
    <div class="panel-heading">
      <h3 class="panel-title">Wechselkurs berechnen</h3>
    </div>
    <div class="panel-body">
      <form>
        <div class="form-group">
          <select class="form-control" name="changeFrom" id="changeFrom"
            ng-model="dataFrom.model">
            <option value="">--- von ---</option>
            <option ng-repeat="option in dataFrom.availableOptions"
               value="{{option.code}}">{{option.name}}</option>
          </select>
        </div>
        <div class="form-group">
          <select class="form-control" name="changeTo" id="changeTo"
            ng-model="dataTo.model">

            <option value="">--- in ---</option>
            <option ng-repeat="option in dataTo.availableOptions"
              value="{{option.code}}">{{option.name}}</option>
          </select>
        </div>
        <div class="form-group">
          <input class="form-control" name="amount" type="text"
            ng-model="amount"
            placeholder="Betrag">
        </div>
        <div class="form-group">
          <input ng-click="calculate()" class="btn btn-primary" type="button"
            value="umrechnen">
        </div>      </form>
 <div id="result" class="alert alert-success uiHide">
        <strong>Erfolg!</strong> {{result}}
      </div>
      <div id="error" class="alert alert-danger uiHide">
        <strong>Achtung!</strong> {{errortext}}
      </div>

Schauen wir uns nun den Controller home.ctrl.js an.

vertx-05-b

Der Start sieht bekannt aus. Ich erstelle einen Controller in meiner currencyWeb Angular Modul und gebe ihm den Namen HomeController. Diesen haben wir in der home.html-Datei eingebunden.

Diesem gebe ich noch ein eigenes Modul zur Verwendung: CurrencyEndpoint. Dies werde ich im Anschluss noch zeigen, da wir auch dieses Modul selbst schreiben.

Webserver-Applikation Teil 2 mit dem Vert.x-Framework

Als Nächstes schaue ich mir die ersten Zeilen an. Mit var vm = this sorge ich dafür, dass ich interne Versionen mit einem Namespace versehen kann. Dies ist eine Möglichkeit, Funktionen in Java Script Private zu deklarieren. Anschliessend deklariere ich die $scope Variablen amount, arrortext, result, dataFrom und dataTo. Dies sind die Variablen, die ich im home.html verwende. Mit $scope stelle ich die Verbindung zwischen html und Javascript her. Die Variable vm.currencies enthält die ganzen Währungen. Wie diese vom Server geholt werden, erkläre ich noch.

Wie Sie sehen, haben die dataTo und dataFrom.aviableOptions diese Währungsliste verknüpft.

Webserver-Applikation Teil 2 mit dem Vert.x-Framework

Webserver-Applikation Teil 2 mit dem Vert.x-Framework

Schauen wir uns die restlichen Funktionen an. Der User wählt die Währungen, gibt einen Betrag ein und klickt auf den Button «umrechnen». Darin rufe ich zuerst die Funktion vm.validate auf.

Richtig, ich muss ja prüfen, ob die Usereingabe korrekt ist. Zuerst prüfe ich in der Funktion, ob nur Ganzzahlen eingegeben sind. Dafür habe ich eine Regex geschrieben und prüfe, ob der amount-Wert auf diese zutrifft. Anschliessend prüfe ich, ob from und to gewählt sind. Ist die Antwort korrekt, so gebe ich true zurück, wenn nicht, false. In jeder Abfrage erstelle ich auch Fehlermeldungen, sodass ich die zusammengesetzte Fehlermeldung ausgebe, wenn etwas fehlerhaft ist. Mit activateUI sage ich, ob der Fehler oder das Ergebnis angezeigt werden soll.

Mit getLangText hole ich mir den aktuellen Namen einer Währung.

Kommen wir nun also zu unserem Endpoint. Mit CurrencyEndpoint.caluclate rufe ich diesen auf und gebe die Usereingabe mit. Schauen wir aber in die Funktion Endpoint hinein:

Webserver-Applikation Teil 2 mit dem Vert.x-Framework

Bei der EndpointFactory handelt es sich um eine factory. Ressource bietet uns ein Mittel, einen einfachen Ajax-Call einzubauen. Die beiden Paths sind die Verknüpfung auf unsere im zweiten Teil angelegten REST-Services. Bei Calculate gebe ich noch die passenden Parameter mit. In den Funktionen getAll rufe ich mit allPath.query einfach den REST-Service auf und gebe das Ergebnis zurück. In der calculate-Funktion gebe ich die Parameter mit und gebe sie an den REST-Call über ein get mit.

Was bleibt, ist die css-Datei

Webserver-Applikation Teil 2 mit dem Vert.x-Framework

Ich gebe dem background eine Farbe. Ausserdem noch kleine Änderungen an dem Bootstrap navar-Object. Die Klasse uiHide habe ich angelegt, um die Alerts standardmässig zu verstecken. Und Pull-Right sorgt für ein float-right.

Webserver-Applikation Teil 2 mit dem Vert.x-Framework

Nun gehe ich mit Rechtsklick auf das Projekt wähle Run As > Maven install.

Anschliessend kann ich das Projekt starten und finde mich mit http://localhost:8081/ auf der Startseite wieder.

Das ganze Projekt ist unter https://github.com/bulli1979/VertxCurrency erreichbar.

Über Feedback würde ich mich freuen.
Mirko Eberlein

JavaScript-Kurse bei Digicomp


Über den Autor

Mirko Eberlein

Mirko Eberlein ist Senior Developer bei der Webgate Consulting AG und Trainer im Bereich Webentwicklung bei Digicomp. Er ist seit 17 Jahren im IT-Umfeld tätig und sich über die Jahre Wissen über verschiedene Programmiersprachen angeeignet. Er versucht sich stets neue Techniken und Trends anzusehen.