Geschrieben von Thomas Kruse
am 2. Oktober 2020
Ein typisches Java Projekt besteht nicht nur aus dem eigenen Code, sondern in der Regel auch vielen externen Bibliotheken als Abhängigkeiten.
Diese Abhängigkeiten machen dabei in einem Microservice mehr als 90% Anteil am gesamten Code aus.
Die Wartung erfolgt zwar durch den jeweiligen Hersteller, jedoch muss das Projekt Team darauf achten, dass entsprechende Aktualisierungen auch im Projekt aufgenommen werden.
Kritisch wird es dann, wenn Sicherheitsupdates zwar verfügbar sind, jedoch nicht die zugehörige Maven oder Gradle Konfiguration aktualisiert wird.
Um das Problem zu lösen gibt es verschiedene Ansätze mit einem unterschiedlichen Automatisierungsgrad.
Wir wollen einen pragmatischen Ansatz vorstellen, der sich in der Praxis sehr bewährt hat und seinerseits keine zusätzlichen Abhängigkeiten einführt.
Geschrieben von Thomas Kruse
am 4. September 2020
Dank Spring Boot ist die Erstellung von Java basierten Anwendungen und Microservices extrem leicht geworden:
Mit Spring Initializr ( https://start.spring.io ) ist eine API Anwendung schnell erstellt.
Sinnvolle Standardeinstellungen und eine gute Entwicklerproduktivität machen Spring Boot auch im weiteren Verlauf eines Softwareprojekts zu einer beliebten Plattform.
Doch was ist, wenn man von den vorgegebenen Pfaden abweichen will?
Spring Boot zeigt sich hier flexibel:
Am Beispiel von YAML als Datenformat für unsere Anwendung schauen wir uns das einmal genauer an.
Geschrieben von Thomas Kruse
am 3. August 2020
Auch wenn Microservice Architekturen und damit einhergehend Single-Module-Repositories im Trend liegen, gibt es immer wieder Gründe für ein Multi-Module Projekt.
Sogar bei Microservice als Deployment.
Wenn es nun darum geht, die Code-Coverage zu ermitteln, um diese bei GitLab CI anzuzeigen oder Trends zu ermitteln, muss man sich etwas behelfen. GitLab CI ist im Verglech zu Jenkins nämlich deutlich dünner ausgestattet, so dass eine Fancy Plugins die Arbeit abnehmen.
Damit ist Jenkins nicht automatisch besser oder GitLab CI schlechter, als Jenkins:
Die Ausrichtung ist einfach anders.
Im folgenden betrachten wir einmal, wie die modulübergreifende Auswertung von Code Coverage, erhoben mit dem JaCoCo Maven Plugin, aussehen könnte.
Der Ansatz lässt sich natürlich auf andere Coverage-Tools und Sprachen analog übertragen.
Geschrieben von Thomas Kruse
am 15. Juni 2020
OpenID Connect und OAuth2 sind vielleicht etwas moderner und hipper als das bereits etwas in die Jahre gekommene SAML 2 Protokoll.
Soll jedoch im Enterpriseumfeld eine Anwendung in bestehende Landschaften integriert werden, führt selten ein Weg an SAML 2 vorbei.
Das gilt um so stärker, wenn es sich um eine Branche mit hohem Sicherheitsbedarf wie Luftfahrt, Banken oder Versicherungen handelt.
Keycloak hat sich als zuverlässige und gleichzeitig sehr leicht zugängliche Plattform zur Umsetzung von OpenID Connect oder SAML erwiesen.
Dabei kann Keycloak sowohl produktiv eingesetzt werden, als auch sehr komfortabel als lokale Testumgebung für Entwicklung und Test verwendet werden.
Zur Integration von Keycloak in Spring Boot existieren neben einem Keycloak Modul auch Spring-Security-SAML bzw. OAuth2 Client und Resourceserver.
Gerade wenn es um das Thema Security geht, bringen automatisierte Tests ein wichtiges Sicherheitsnetz für die Software.
Wir wollen Keycloak als SAML 2 IdP verwenden und mit einer Spring Boot Anwendung Authentifizierung mit SAML 2 als Beispielanwendung für automatisierte Integrationstests verwenden.
Ein - relativ einfacher - Weg wäre, Keycloak als Docker Container im Rahmen der CI-Pipeline mit Jenkins, Bamboo oder GitLab-CI bereitzustellen, so dass die zu testende Software darauf zugreifen kann.
Allerding verliert man damit die Möglichkeit, die Tests lokal genauso zu entwickeln und zu validieren, wie sie nachher in der Buildserver Umgebung laufen.
Eine Alternative stellen Testcontainers dar.
Die allgemeine Verwendung von Testcontainers wurde bereits in Testcontainers mit JUnit 5 erläutert.
Nun schauen wir uns an, wie Keycloak, Testcontainers und Spring Boot SAML 2 zusammen eingesetzt werden kann.
Geschrieben von Thomas Kruse
am 26. Mai 2020
Regelmäßig kommt in unseren Docker Schulungen Verwunderung auf, wenn wir Beispiele zum Einsatz von Containern im Entwicklungsprozess aufzeigen.
Denn Container bzw. Docker bringt gerade da auch immense Vorteile:
Neben einer möglichen Parität zwischen Produktionsumgebung und Entwicklersystem ist es gerade die sehr einfache Möglichkeit, Umsysteme als Container bereitzustellen.
Das kann für einen Frontendentwickler das Backend sein, für einen Backendentwickler kann es die richtige Datenbank, Message-Queue oder ein anderer (Micro-)Service sein.
Verfügen aktuelle IDEs in der Regel über Docker-Integration oder wird docker-compose
eingesetzt, stellt sich die Frage, wie in CI-Umgebungen Container für Integrationstests am besten eingesetzt werden können.
Hier hat das Projekt Testcontainers eine Lösung ins Rennen geschickt:
Durch eine gelungene Abstraktion lassen sich Container sehr leicht in Tests verwalten und zusammen mit den Tests orchestrieren.
Container-Typen und Versionen werden gemeinsam mit dem Testcode versioniert, was die Wartung und Refactoring erleichtert.
Auch ein häufiges Problem, nämlich auf den erfolgreichen Start eines Containers bzw. des damit bereitgestellten Dienstes zu warten, wird gut gelöst.
Testcontainers gibt es für verschiedene Programmiersprachen bzw. Plattformen.
Wir schauen uns im folgenden einmal die Umsetzung für Java speziell im Kontext von JUnit 5 genauer an.
Geschrieben von Thomas Kruse
am 31. Januar 2020
Jib eignet sich sehr gut, um Docker Images mit Maven oder Gradle zu erzeugen, ohne dass dazu ein Docker Daemon verwendet werden muss.
Im Gegensatz zu Docker unterstützt Jib derzeit noch keine Multi-Arch Images.
Damit ist ein automatischer Build für die jeweilige Plattform nicht möglich, was sich zum Beispiel auf einem Raspberry Pi, ODROID oder anderen Maschinen auf Basis der ARM Architektur bemerkbar macht.
Mit einer kleinen Konfigurationsanpassung ist es jedoch möglich, passende Images zu erzeugen.
Geschrieben von Thomas Kruse
am 28. Mai 2019
Kubernetes bietet mit seiner erweiterbaren API eine sehr einfache Möglichkeit zusätzliches Verhalten mit Kubernetes zu integrieren.
Neben der API-Spezifikation als OpenAPI (ehemals Swagger) stellt das Kubernetes-Projekt auch fertige Clients für verschiedene Programmiersprachen an.
Eine besondere Rolle nimmt der Kubernetes Go-Client ein, da dieser auch innerhalb von Kubernetes selbst eingesetzt wird.
Auf Basis der OpenAPI-Spezifikation stehen generierte Clients für Java, Python, C# und JavaScript.
Zu den offiziellen Kubernetes-Clients kommen noch durch die Community erstellte und gepflegte Libraries für diverse Sprachen hinzu.
Im Folgenden wird demonstriert, wie die Kubernets-API mit Java verwendet werden kann.
Wie der dazu benötigte lesende API-Zugriff eingerichtet werden kann, wurde bereits in Kubernetes Readonly API Zugriff erklärt.
Geschrieben von Thomas Kruse
am 4. Januar 2019
Lange Zeit war Spring zusammen mit Spring Boot der Defacto-Standard, wenn es um die Entwicklung von Microservices bei hoher Entwicklerproduktivität ging.
Nun schicken die Entwickler von Grails ein neues Framework ins Rennen: Micronaut.
Das Versprechen von Micronaut:
Aus den Ansätzen von Grails, Spring Boot und Spring zu lernen und ein Framework bereitzustellen, das den Anforderungen von modernen Cloud- und Microserviceumgebungen gewachsen ist.
Aus technischer Sicht sind einige Punkte, wie minimierter Einsatz von Java-Reflection und Proxies, spannend, die für die Verwendung der Substrate VM und Graal relevant sind.
Werfen wir einen Blick auf Micronaut - eine Einführung.
Geschrieben von Thomas Kruse
am 24. Dezember 2018
Java Anwendungen haben den Ruf, schwergewichtig und langsam zu sein.
Langsam ist Java dank ausgefeilter Optimierungen der JVM zwar nicht (mehr), jedoch sind Docker Container Images von Anwendungen relativ gross.
Das ist dadurch bedingt, dass eine JVM und ein Betriebssystem mitgeliefert werden muss, damit die Java Anwendung im Docker Container ausgeführt werden kann.
In aktuellen Java Versionen ist dank GraalVM die Möglichkeit gegeben, Java Anwendungen als native Programme zu kompilieren und statisch zu linken.
Damit ist weder eine JVM noch ein Betriebssystem im Container Image erforderlich - vergleichbar mit dem aus der Go Welt bekanntem Vorgehen.
Wie das ganze funktioniert, wird im folgenden Beitrag vorgestellt.
Geschrieben von Thomas Kruse
am 19. Dezember 2018
gRPC hat bisher vor allem im Backend oder bei der direkten Kommunikation zwischen Anwendungen auf dem Endgrät und dem Backend eine Rolle gespielt.
Aufgrund der zunehmenden Rolle von Browseranwendungen sollte gRPC auch in clientseitigen Webanwendungen genutzt werden können.
Das zugehörige Projekt ist gRPC-Web: https://github.com/grpc/grpc-web
In diesem Beitrag wurde die Erstellung eines Spring Boot gRPC Backends demonstriert.
Nun get es darum, das Backend in einer Angular Webanwendung mit gRPC-Web anzubinden.
Geschrieben von Thomas Kruse
am 7. Dezember 2018
In verteilten Systemen, zu denen etwa solche mit Microservice- und Cloud-Architekturen zählen, müssen in der Regel über Anwendungsgrenzen hinweg Funktionsaufrufe erfolgen.
Typischerweise kommt dabei für synchrone Aufrufe HTTP als Transportschicht zum Einsatz, das Format der ausgetauschten Daten kann XML, JSON oder eine andere spezifische Datenstruktur sein.
Welche HTTP-Verben und welche Adressen (URLs) wie zu verwenden sind, ist dabei eine fast schon in philosophische Bereiche ausufernde Debatte zwischen den verschiedenen Ansätzen.
Am häufigsten finden sich REST und Abwandlungen davon als Schnittstellenkonzept.
Im Gegensatz zu der reichhaltigen API-Oberfläche von REST findet sich SOAP als XML-basiertes RPC- (Remote-Procedure-Call-) Verfahren, bei dem lediglich HTTP POST-Requests zum Einsatz kommen.
Neben dem oft als schwerfällig bezeichneten Vorgehen von Design und Implementierung von SOAP-Schnittstellen hat XML als Transportformat auch deutliche Auswirkungen auf möglichen Durchsatz und erforderliche CPU- und Speicherresourcen bei der Verarbeitung.
Als Alternative zu diesen Ansätzen hat Google gRPC entwickelt:
gRPC setzt ebenfalls auf HTTP auf, verwendet jedoch Google Protocol Buffers als optimiertes Datenformat.
Wie der Einsatz im Kontext einer Java-Spring-Boot-Anwendung aussehen kann, wird im Folgenden dargestellt.
Geschrieben von Thomas Kruse
am 3. Oktober 2018
Mit Docker haben sich Container als Auslieferungsformat (nicht nur) für Microservices zum Status Quo für Cloudanwendungen etabliert.
Zur Erstellung der Container-Images war lange Zeit Zugriff auf einen Docker-Daemon erforderlich.
Besonders in Umgebungen wie Kubernetes-Clustern oder Public-Clouds mit gemeinsam genutzter Infrastruktur soll auf privilegierte Container verzichtet werden.
Mit dem typischen Ansatz von Docker-in-Docker oder Docker-Outside-Docker erhält ein so ausgeführter Build nämlich relativ viele Rechte.
Dank der OCI Spezifikation für Image-Formate ist Docker mit einem Dockerfile jedoch nur noch eine Möglichkeit, zum auslieferbaren Image zu gelangen.
Ein weiterer Aspekt sind die oft schwer umzusetzenden Optimierungsmöglichkeiten für Docker Images:
Um vom Layer-Caching optimal zu profitieren und damit sowohl I/O-Operationen als auch Speicherplatz zu sparen, sollten die Daten, die sich weniger häufig ändern, in einem separaten Layer positioniert werden, als Daten, die sich regelmäßig ändern.
Bei einer Spring Boot Anwendung könnte man zum Beispiel zwischen allen Abhängigkeiten und den eigentlichen, zu der Anwendung selbst gehörenden Class-Dateien differenzieren:
Die Abhängigkeiten werden sich seltener ändern, als das Programm, das bei jedem Bugfix und jeder Erweiterung Änderungen erfährt.
Nur dieser geänderte Image-Layer muss dann verteilt werden.
Für beide Probleme soll das Google Projekt "Jib" eine Lösung liefert.
Am Beispiel einer Spring Boot Anwendung und Maven wird der Einsatz von Google Jib demonstriert.