Wir haben es uns zur Aufgabe gemacht, verschiedene Microframeworks anhand eines kleinen Anwendungsfalles zu evaluieren, der detaillierte Anwendungsfall wurde bereits in unserem ersten Blog-Post beschrieben. Unser Artikel über Javalin ist unter dieser Adresse zu finden. Heute werden wir uns auf das Microframework Micronaut konzentrieren. Im Folgenden zeigen wir die wichtigsten Eigenschaften, Stärken und Schwächen von Micronaut. Das Codebespiel ist unter diesen Link auf Github zu finden.

https://micronaut.io/

Bei Micronaut handelt es sich um ein modernes, JVM-basiertes Full-Stack-Framework zum Aufbau modularer, leicht testbarer Microservices- und Serverless Anwendungen. Das Framework unterstützt die Implementierung in Java, Groovy und Kotlin. Weitere Eigenschaften des Frameworks sind ein geringer Speicherbedarf und eine schnelle Start-Up Zeit, was vor allem in Bezug auf die Verwendung im Serverless-Umfeld wichtig ist. Außerdem wird Micronaut unter Apache License 2.0 veröffentlicht.

Wenn man mit Micronaut arbeitet, ist häufig die Implementierung/Erweiterung bestehender Framework-Klassen notwendig. Einige Aspekte können einfach durch die Verwendung der entsprechenden Annotationen (@GET, @POST“¦) deklarativ hinzugefügt werden.

In diesem Teil haben wir erstmal allgemeine Informationen über Micronaut gegeben. Im Folgenden betrachten wir wie eine Micronaut Applikation entwickelt wird und beschreiben wichtigste Eigenschaften und Elemente des Frameworks.

Micronaut Projekt erstellen und kompilieren

Bevor wir anfangen, stellen wir sicher, dass wir ein Java 8 SDK oder höher installiert haben

Micronaut bietet eine CLI an. Mit Hilfe der CLI kann man Projekte erstellen und löschen. Verschiedene Möglichkeiten die Micronaut CLI zu installieren finden sich in der offiziellen Dokumentation (https://docs.micronaut.io/latest/guide/index.html#buildCLI).

Um Micronaut CLI benutzen zu können, muss man zuerst die letzte Binärdatei aus https://micronaut.io/download.html herunterladen und die an einen geeigneten Ort extrahieren. Danach wird eine Umgebungsvariable MICRONAUT_HOME erstellt, die auf das Installationsverzeichnis zeigt und die Umgebungsvariable PATH wird aktualisiert. Nachher kann man das Micronaut CLI ausführen über die Command Line ausgeführt werden (siehe Abbildung 1).

Über das Micronaut CLI kann einen neue Micronaut Anwendung am schnellsten und einfachsten erzeugt werden.

1.	$ mn
2.	| Starting interactive mode...
3.	| Enter a command name to run. Use TAB for completion:
4.	mn>


Abbildung 1-Micronaut CLI von der Eingabeaufforderung starten

Der folgende Befehl (siehe Abbildung 2) erstellt eine neue „micronaut-demo“- Anwendung in Java mit einem Gradle-Build.

1.	mn create-app micronaut-demo


Abbildung 2-Applikation über Micronaut CLI erstellen

Wenn Maven anstelle von Gradle verwendet werden soll, kann dies im Rahmen der Anwendungserstellung mittels des Parameters „–build maven“ definiert werden. Eine Gradle-baiserte Anwendung kann mit dem folgenden Befehl ausgeführt werden:

1.	$ ./gradlew run
2.	> Task :run


Abbildung 3 - Applikation über CLI ausführen

Ein Java-Microservice mit Micronaut

Kommen wir nun zur Implementierung unsereres Microservices. Wir benötigen für unsere Technologie Management Webseite jeweils eine Detailseite pro Technologie. Dafür haben wir erstmal unsere „TechnologyApplication“ Main-Klasse (siehe Abbildung 4) erstellt, diese wird beim Ausführen der Anwendung verwendet.

1.	public class TechnologyApplication {
2.	     public static void main(String[] args) {
3.	     Micronaut.run(TechnologyApplication.class);
4.	     }
5.	}


Abbildung 4- Main Klasse Technology Applikation

Danach haben wir unsere Controller Klasse implementiert. In dieser Klasse sehen wir schon manche Eigenschaften von Micronaut, und zwar Annotationen(siehe bitte Codebeispiel unter den „LINK“) . GET, POST, PUT, DELETE Methoden werden in der Controllerklasse (siehe bitte Abbildung 5)implementiert und für die Bearbeitung von Requests verwendet. In diesen Methoden neben den Annotationen steht in Klammern („/technologies/{id}“), das ist unsere URI und id ist eine Variable. Beispielsweise werden alle Informationen zu der Technologie Micronaut mit id Nummer 2 unter folgender URL „http://localhost:7000/technologies/2“ zurückgegeben.

Wichtig: Standardmäßig ist der Micronaut Server so konfiguriert, dass er auf Port 8080 läuft. Dies kann aber geändert werden. Wir haben es auch als 7000 geändert. (siehe bitte https://docs.micronaut.io/latest/guide/index.html#runningSpecificPort).

1.	@Controller("/")
2.	public class TechnologyController {
3.	protected final TechnologyRepository technologyRepository;
4.	
5.	public TechnologyController(TechnologyRepository technologyRepository) {
6.	   this.technologyRepository = technologyRepository;
7.	}
8.	
9.	@Get("/technologies/{id}")
10.	public Technology getTechnology(@PathVariable int id) {
11.	   return technologyRepository.getTechnology(id).orElse(null);
12.	}
13.	
14.	@Post("/technologies")
15.	public HttpResponse insertTechnology(@Body @Valid TechnologyInsertCommand cmd) {
16.	       "¦"¦"¦"¦"¦"¦"¦"¦
17.	}
18.	
19.	@Put("/technologies/{id}")
20.	public HttpResponse updateTechnology(@Body @Valid TechnologyUpdateCommand cmd){
21.	"¦"¦"¦"¦"¦"¦"¦
22.	}
23.	
24.	@Delete("/technologies/{id}")
25.	public void removeTechnology(@PathVariable int id) {
26.	   technologyRepository.removeTechnology(id);
27.	   return location(technology.getId());
28.	}
29.	}


Abbildung 5 -Controller Klasse

Datenbankverbindung

Wir wollen in unserem Beispiel die Technologien in einer Datenbank speichern oder auch gespeicherte Daten auslesen. Micronaut ermöglicht unter anderem die Anbindung von relationalen Datenbanken via JDBC/JPA/Hibernate. Um uns mit der Datenbank zu verbinden, haben wir uns für MyBatis entschieden. MyBatis ist ein Java-Persistenz-Framework, das Objekte mit Stored Procedures oder SQL-Anweisungen unter Verwendung eines XML-Deskriptors oder von Annotationen koppelt. Im Gegensatz zu ORM-Frameworks bildet MyBatis keine Java-Objekte auf Datenbanktabellen ab (kein Mapping), sondern Java-Methoden auf SQL-Anweisungen.

Um MyBatis benutzen zu können, müssen wir die notwendigen Dependencies in unserer „build.gradle“-Datei hinzufügen.(siehe Abbildung 6)

1.	implementation("org.mybatis:mybatis:3.4.6") 
2.	//MyBatis-Abhängigkeit hinzufügen.
3.	
4.	implementation("io.micronaut.sql:micronaut-jdbc-hikari") 
5.	// Konfiguriert SQL-DataSource-Instanzen 
6.	
7.	compile group: 'org.postgresql', name: 'postgresql', version: '42.2.8.jre7'
8.	//postgresql jdbc driver dependency


Abbildung 6 "“ build.gradle

Zudem müssen wir unsere Datenquelle in der zentralen Applikationskonfigurationsdatei „application.yml“ Datei definieren (siehe Abbildung 7).

1.datasources:
2.  default:
3.  url: ${JDBC_URL:`jdbc:postgresql://localhost:5432/postgres`}
4.  driverClassName: org.postgresql.Driver
5.  username: ${JDBC_USER:postgres}
6.   password: ${JDBC_PASSWORD:*********}


Abbildung 7-application.yaml

Da es in Micronaut noch keinen Out-of-the-Box-Support für MyBatis gibt, ist es notwendig, SqlSessionFactory manuell zu verdrahten (siehe Abbildung 8).

1.@Factory
2.public class MyBatisFactory {
3.	private  DataSource dataSource ;
4.    public MyBatisFactory(DataSource dataSource)
      {this.dataSource=dataSource;}}
5.	
6.@Bean
7.SqlSessionFactory sqlSessionFactory() {
8.	TransactionFactory transactionFactory = new JdbcTransactionFactory();
9.	Environment environment = new Environment("dev", transactionFactory, dataSource);
10.	Configuration configuration = new Configuration(environment);
11.	configuration.addMappers("micronaut");
12.	return new SqlSessionFactoryBuilder().build(configuration);
13.	}
14.}


Abbildung 8-src/main/java/micronaut/MybatisFactory.java

Nachdem Domänenobjekte (in unserem Fall die Klasse „Technology“) erstellt wurden, erstellen wir ein Interface, um die Operationen für den Zugriff auf die Datenbank zu definieren. Wir verwenden die Annotations von MyBatis, um die Methoden auf SQL-Abfragen abzubilden (siehe Abbildung 9).

1.	public interface TechnologyMapper {
2.	
3.	@Select("SELECT * FROM technologies")
4.	List getTechnologies();
5.	
6.	@Select("SELECT * FROM technologies WHERE id=#{id}")
7.	Technology getTechnology(int id) ;
8.	
9.	@Insert("INSERT INTO technologies (name, description, recommendation, relevance, complexity, url,) values(#{name}," +
10.	"#{description},#{recommendation},#{relevance},#{complexity},#{url})")
11.	void insertTechnology(Technology technology) ;
12.	
13.	@Delete("DELETE FROM technologies WHERE id=#{id}")
14.	void removeTechnology(int id);
15.	
16.	@Update("UPDATE technologies SET name=#{name}, description=#{description},recommendation=#{recommendation}, " +
17.	"relevance=#{relevance}, complexity=#{complexity}, url=#{url}, WHERE id=#{id}")
18.	void update(@Param("id") Integer id, @Param("name") String name, @Param("description") String description,
19.	     	@Param("relevance") Integer relevance, @Param("recommendation")Integer recommendation,
20.	       @Param("complexity")Integer complexity, @Param("url") String url);
21.	}


Abbildung 9-TechnologyMapper.java

Nun gibt es noch eine wichtige Sache, und zwar die Erstellung des Datenbankschemas. Dafür haben wir die Micronaut-Integration mit Flyway verwendet. Zunächst wird die Dependency hinzugefügt (Abbildung 10):

1.implementation("io.micronaut.flyway:micronaut-flyway")

Abbildung 10-build.gradle

Danach konfigurieren wir die application.yaml für das Datenbankmigrationsverzeichnis(Abbildung 11):

1.	flyway:
2.	   datasources:
3.	       default:
4.	           locations: classpath:db/migration


Abbildung 11 - application.yaml

Nun erstellen wir das Datenbankschema unter dem Verzeichnis „src/main/resources/db/migration/V1__schema.sqlsiehe Abbildung 12:

1.	CREATE TABLE technologies(
2.	id SERIAL  primary key,
3.	name VARCHAR(100) NOT NULL,
4.	description VARCHAR(1500) NOT NULL,
5.	recommendation smallint CHECK (recommendation >0 AND recommendation <6),
6.	relevance smallint  CHECK (relevance >0 AND relevance <6),
7.	complexity smallint  CHECK (complexity >0 AND complexity <6),
8.	url VARCHAR(200) NOT NULL,
9.	tags varchar(210));


Abbildung 12- Datenbankschema

Sonstige Features von Micronaut

Natively Cloud Native

Die Cloud-Unterstützung von Micronaut ist direkt integriert. Das bedeutet, dass Micronaut Cloud Nativeist. Micronaut ist ein Framework mit dem sowohl Cloud- als auch On-premises Anwendungen erstellt werden können.

Die meisten heute in der JVM verwendeten Frameworks wurden vor dem Aufkommen von Cloud-Deployments und Microservice-Architekturen entwickelt. Mit diesen Frameworks erstellte Anwendungen sollten in herkömmliches Java/Java EE-Containern zum Beispiel in Java EE server, in Enterprise JavaBeans (EJB) Container oder in Application client container bereitgestellt werden. Daher wird die Cloud-Unterstützung in diesen Frameworks in der Regel eher als Add-On bereitgestellt.

Micronaut wurde von Grund auf für den Aufbau von Microservices für die Cloud entwickelt. Infolgedessen sind in Ihrer Anwendung selbst viele wichtige Funktionen verfügbar, für die normalerweise externe Bibliotheken oder Dienste erforderlich sind. Micronaut-Anwendungen sind nativ Cloud-native, um eines der derzeit beliebtesten Schlagworte der Branche zu verwenden.

Im Folgenden sind einige der Cloud-spezifischen Funktionen aufgeführt, die direkt in die Micronaut-Laufzeit integriert sind:

  • Distributed Configuration
  • Service Discovery
  • Client-Side Load-Balancing
  • Distributed Tracing
  • Serverless Functions

Verteilte, dynamisch veränderbare Konfiguration

Ein weiteres Merkmal von Micronaut ist die gemeinsame Nutzung der Cloud-Konfiguration. Auf diese Weise können Konfigurationen extern gespeichert werden, sodass skalierte Instanzen eines Dienstes eine gemeinsame Konfiguration in einer Cloud-Umgebung nutzen können und Ü„nderungen direkte Auswirkungen auf alle Instanzen haben.

Abhängig von der Infrastruktur der Anwendung können beispielsweise verschiedene Beans aktiviert werden. Micronaut erkennt Umgebungen wie Android, Test, Cloud, Amazon EC2, Google Compute, Kubernetes, Heroku, Cloud Foundry, Azure oder die IBM Cloud. Neben einem internen Mechanismus zum manuellen Auflösen verteilter Konfigurationen können Dienste wie Consul oder AWS Systems Manager Parameter Store verwendet werden.

Nachrichtengesteuerte Microservices

Apache Kafka ist beliebt für die Verarbeitung verteilter Datenströme und Echtzeitdaten. Mit der Unterstützung von Micronaut für Kafka können Entwickler mit AOP-Annotationen zur Kompilierungszeit wie @KafkaClient, @KafkaListener, @Topic, @Body, @Header, @KafkaKey und einigen Zeilen der YAML-Konfiguration in nur wenigen Schritten nachrichtengesteuerte Microservices implementieren. Der Micronaut Guide enthält umfassende Anweisungen (siehe bitte https://micronaut-projects.github.io/micronaut-kafka/latest/guide/).

Micronaut JWT Authentication

Micronaut erleichtert die Konvertierung von JSON in Java-Objekte. Micronaut unterstützt die RFC 6750 Bearer Token-Spezifikationen. Micronaut stellt das JWT-Token im HTTP-Header zur Autorisierung bereit.

Zusammenfassung

Das Framework bietet einen vertrauten Entwicklungsablauf, jedoch mit minimaler Startzeit und minimalem Speicherverbrauch. Dadurch kann Micronaut in unterschiedlichen Szenarien eingesetzt werden, darunter Android-Anwendungen, serverlose Funktionen und CLI-Anwendungen.

Außerdem ist Micronaut Cloud native und stellt viele wichtige Basisfunktionalitäten zur Verfügung, für die normalerweise externe Bibliotheken oder Dienste erforderlich sind. Micronaut ist auf der Homepage gut dokumentiert. Eine kleine, aber wachsende Auswahl an Schritt-für-Schritt-Tutorials ist ebenfalls unter https://guides.micronaut.io/ verfügbar, einschließlich Leitfäden für alle drei von Micronaut unterstützten Sprachen: Java, Groovy und Kotlin. Ein schneller Einstieg ist somit gewährleistet.

Alle Beiträge von Meryem Cigdem

1 Kommentar

Schreibe einen Kommentar