Spring Boot Profiles in unterschiedlichen Umgebungen nutzen

Mit Spring Boot Profiles bietet Spring Boot ein wichtiges und mächtiges Werkzeug mit dem man Umgebungsspezifische Einstellungen und Implementierungen nutzen kann.
Spring Boot Profile

Spring Boot – Profiles in unterschiedlichen Umgebungen verwenden

Einleitung

Als Softwareentwickler steht man irgendwann vor der  Herausforderung, dass man für unterschiedliche Systeme unterschiedliche Implementierungen benötigt!

Man stelle sich folgendes Scenario vor. Ihr habt einen Microservices entwickelt und der Auftraggeber verlangt von euch, dass dieser Microservice je nach Umgebung sich anders verhalten soll. Die schlechteste Variante wäre es jetzt diesen bestehenden Microservice zu kopieren und die Implementierung auf die neue Umgebung anzupassen. Eine ebenfalls schlechte Variante wäre es nun einen Flag einzubauen, der prüft auf was für einer Umgebung der Microservice läuft und dann entsprechend im Quellcode mit if-Anweisungen entscheidet welche Implementierung verwendet wird.

Viel eleganter und wartbarer wäre es doch, wenn man dem Microservice über einen Parameter mitteilen könnte auf welcher Umgebung es läuft und dieser verwendet dann die Implementierung für die entsprechende Umgebung.

Genau hier setzt Spring Boot mit Profiles an. Mit Profiles ist es möglich in Spring Boot Anwendungen nicht nur Konfiguration-Parameter zu setzten, sondern auch unterschiedliche Implementierungen zu verwenden.

Wie das geht werde ich euch in diesem Tutorial zeigen.

Voraussetzung

Spring Boot bietet mit Profiles ein wichtiges und mächtiges Werkzeug mit dem man Umgebungsspezifische Einstellungen und Implementierungen nutzen kann.

Wie oben in der Einleitung beschrieben wollen wir unterschiedliche Implementierungen nutzen. Wir gehen davon aus, dass wir einen Rest Controller haben der uns über die GET URL http://localhost:8080/info die Info zurück gibt auf welcher Umgebung die Anwendung läuft oder bzw für welche Umgebung sie konfiguriert ist. Das Beispiel ist absichtlich recht trivial gehalten, da der Focus auf die Nutzung der Profiles gelegt ist.

In unserem Beispiel haben wir einen Rest Controller der über die GET URL http://localhost:8080/info Anfragen annimmt und diese dann an die InfoService Implementierung im Backend weiterleitet.

spring boot profiles project structure

Der Rest Controller ist wie folgt implementiert

package de.ertantoker.tutorial;

import de.ertantoker.tutorial.service.InfoService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
public class InfoController {

    private InfoService infoService;

    public InfoController(InfoService infoService) {
        this.infoService = infoService;
    }

    @GetMapping("/info")
    public ResponseEntity<String> getInfo() {
        return new ResponseEntity<>(infoService.getInfo(), HttpStatus.OK);
    }
}

Die Implementierung der InfoService Klasse sieht wie folgt aus

package de.ertantoker.tutorial.service;

import org.springframework.stereotype.Service;

@Service
public class InfoService {

    private String info = "Default Info";

    public String getInfo() {
        return info;
    }
}

Wie wir sehen können, wird beim Aufruf immer Default Info zurück gegeben. Egal in welcher Umgebung wir diese Spring Boot Anwendung starten, wir erhalten immer als Antwort „Default Info“.

Jetzt ist es aber so, dass wir noch eine Umgebung Premium haben. Wir wollen, wenn die Spring Boot Applikation in der Premium Umgebung läuft, dass dann „Default Info“  durch „Premium Info“ ausgetauscht ist.

In dem Kontext wollen wir aber nicht jedes mal die Anwendung neu compilieren und bauen, daher verwenden wir Spring Boot Profiles.

Mit Spring Boot Profile können wir für jede Umgebung eine eigene Implementierung erstellen. Beim starten der Anwendung können wir dann über den Parameter „spring.profiles.active“ festlegen unter welchem Profil die Spring Boot Anwendung läuft. Dazu aber später mehr.

Damit unsere Anwendung auf unterschiedlichen Umgebungen auch so funktionieren kann, wie wir es möchten müssen wir noch einige Änderungen am Quellcode vornehmen.

Aus der Klasse InfoService.java machen wir ein Interface, welches nur die Methode „Spring getInfo()“ hat. Anschließend werden wir für jede Umgebung eine Implementierung des Interfaces InfoService.java erstellen.

package de.ertantoker.tutorial.service;

public interface InfoService {

    String getInfo();
}

Die Implementierung der DefaultInfoService.java sieht wie folgt aus.

package de.ertantoker.tutorial.service;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Service
@Profile("default")
public class DefaultInfoService implements InfoService {

    private String info = "Default Info";

    @Override
    public String getInfo() {
        return info;
    }
}

Anhand der Implementierung sehen wir jetzt, dass die Service Klasse eine Annotation @Profile(„default“) hat. Durch diese Annotation legen wir fest, dass die Klasse immer dann genutzt werden soll, wenn die Anwendung unter dem „default“ Profil gestartet ist. Das „default“ Profil wird immer dann verwendet, wenn man kein Profil angibt oder explizit das „default“ Profil angibt.

Wir sehen, dass die Implementierung den Wert der privaten Variable info zurück gibt. Diesem ist der Wert „Default Info“ zugewiesen.

Als nächste betrachten wir die PremiumInfoService Klasse.

package de.ertantoker.tutorial.service;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Service
@Profile("premium")
public class PremiumInfoService implements InfoService {

    private String info = "Premium Info";

    @Override
    public String getInfo() {
        return info;
    }
}

Auch hier sehen wir, dass die getInfo Methode den Wert der privaten Variable info zurück gibt.

Beide Implementierungen sind in diesem Beispiel fast Identisch. Der einzige Unterschied ist die Annotation @Profile.

Wie weiter oben erwähnt, kann man das Profil unter dem die Spring Boot Anwendung läuft beim starten der Anwendung mitgeben. Hierfür wird der Parameter „spring.profiles.active“ verwendet.

Wenn wir jetzt die Spring Boot Anwendung ohne einen Parameter starten, wird die Anwendung unter dem Profil „default“ gestartet. Möchten wir jetzt, dass die Anwendung unter dem Profil „premium“ gestartet wird, dann müssen wir die Anwendung wie folgt starten:

Console Default

Das Ergebnis vom Postman Aufruf

Console Premium

Das Ergebnis vom Postman Aufruf

Wie Ihr nun sehen könnt, wurde die Spring Boot Anwendung einmal unter dem „default“ Profil und einmal unter dem „premium“ Profil gestartet.

Somit ist unsere Anwendung in der Lage je nach Umgebung bzw Profil eine andere Implementierung zu nutzen. In diesem Beispiel haben wir nur String Werte zurück gegeben, was nicht wirklich kompliziert ist. Wenn man in Zukunft als Entwickler vor der Herausforderung steht, dass je nach Umgebung eine komplett andere Berechnung oder Algorithmus verwendet werden soll, dann kann man mit der selben Vorgehensweise dafür sorgen, dass die Implementierungen ausgetauscht werden.

Ich hoffe euch hat mein Tutorial gefallen. Solltet Ihr Fragen, Kritik oder Anregungen haben, dann gerne in die Kommentare schreiben.

Weitere Informationen zu dem Thema Spring Boot Profiles findet ihr auf der Doku Seite von Spring

[amazon_link asins=’3864905257,3864905265,3864904838,3864902908′ template=’ProductCarousel‘ store=’fitnes06-21′ marketplace=’DE‘ link_id=’6e5bbb31-b4f6-11e8-8e0e-a516a4623524′]

Verwandte Beiträge

Leave a comment