Erstellen von Microservices mit Eclipse MicroProfile

Erstellen von Microservices mit Eclipse MicroProfile

1. Überblick

In diesem Artikel konzentrieren wir uns auf die Erstellung eines auf Eclipse MicroProfile basierenden Mikroservices.

Wir werden uns ansehen, wie Sie eine RESTful-Webanwendung mit JAX-RS-, CDI- und JSON-P-APIs schreiben.

2. Eine Microservice-Architektur

Einfach ausgedrückt, Microservices sind Software-Architekturen, die ein vollständiges System aus mehreren unabhängigen Diensten bilden.

Jeder konzentriert sich auf einen Funktionsumfang und kommuniziert mit den anderen über ein sprachunabhängiges Protokoll wie REST.

3. Eclipse MicroProfile

Eclipse MicroProfile ist eine Initiative zur Optimierung von Enterprise Java für die Microservices-Architektur. Es basiert auf einer Teilmenge von Java EE-WebProfile-APIs, sodass wir MicroProfile-Anwendungen wie Java EE-Anwendungen erstellen können.

Das Ziel von MicroProfile ist es, Standard-APIs für den Aufbau von Mikrodiensten zu definieren und tragbare Anwendungen über mehrere MicroProfile-Laufzeiten bereitzustellen.

4. Maven-Abhängigkeiten

Alle Abhängigkeiten, die zum Erstellen einer Eclipse MicroProfile-Anwendung erforderlich sind, werden von dieser Stücklistenabhängigkeit bereitgestellt:


    org.eclipse.microprofile
    microprofile
    1.2
    pom
    provided

Der Bereich wird aufprovided festgelegt, da die MicroProfile-Laufzeit bereits die API und die Implementierung enthält.

5. Repräsentationsmodell

Beginnen wir mit der Erstellung einer schnellen Ressourcenklasse:

public class Book {
    private String id;
    private String name;
    private String author;
    private Integer pages;
    // ...
}

Wie wir sehen können, gibt es keine Anmerkung zu dieserBook-Klasse.

6. CDI verwenden

Einfach ausgedrückt ist CDI eine API, die Abhängigkeitsinjektion und Lebenszyklusmanagement bietet. Dies vereinfacht die Verwendung von Enterprise-Beans in Webanwendungen.

Erstellen wir nun eine CDI-verwaltete Bean als Speicher für die Buchdarstellung:

@ApplicationScoped
public class BookManager {

    private ConcurrentMap inMemoryStore
      = new ConcurrentHashMap<>();

    public String add(Book book) {
        // ...
    }

    public Book get(String id) {
        // ...
    }

    public List getAll() {
        // ...
    }
}

Wir kommentieren diese Klasse mit@ApplicationScoped, da wir nur eine Instanz benötigen, deren Status von allen Clients gemeinsam genutzt wird. Dafür haben wir einConcurrentMap als typsicheren In-Memory-Datenspeicher verwendet. Dann haben wir Methoden fürCRUD Operationen hinzugefügt.

Jetzt ist unsere Bean ein CDI-fähig und kann in die AnnotationBookEndpoint using the@Injectder Bean eingefügt werden.

7. JAX-RS API

Um eine REST-Anwendung mit JAX-RS zu erstellen, müssen Sie eine mit@ApplicationPath annotierteApplication-Klasse und eine mit@Path. annotierte Ressource erstellen

7.1. JAX RS-Anwendung

Die JAX-RS-Anwendung identifiziert den Basis-URI, unter dem die Ressource in einer Webanwendung verfügbar gemacht wird.

Erstellen wir die folgende JAX-RS-Anwendung:

@ApplicationPath("/library")
public class LibraryApplication extends Application {
}

In diesem Beispiel sind alle JAX-RS-Ressourcenklassen in der Webanwendung denLibraryApplicationzugeordnet, sodass sie unter demselbenlibrary-Pfad liegen. Dies ist der Wert vonApplicationPath annotation.

Diese mit Annotationen versehene Klasse teilt der JAX RS-Laufzeit mit, dass Ressourcen automatisch gefunden und verfügbar gemacht werden sollen.

7.2. JAX RS-Endpunkt

EineEndpoint-Klasse, auchResource-Klasse genannt, sollte eine Ressource definieren, obwohl viele der gleichen Typen technisch möglich sind.

Jede mit@Path annotierte Java-Klasse oder mindestens eine mit@Path or @HttpMethod annotierte Methode ist ein Endpunkt.

Jetzt erstellen wir einen JAX-RS-Endpunkt, der diese Darstellung verfügbar macht:

@Path("books")
@RequestScoped
public class BookEndpoint {

    @Inject
    private BookManager bookManager;

    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getBook(@PathParam("id") String id) {
        return Response.ok(bookManager.get(id)).build();
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAllBooks() {
        return Response.ok(bookManager.getAll()).build();
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response add(Book book) {
        String bookId = bookManager.add(book);
        return Response.created(
          UriBuilder.fromResource(this.getClass())
            .path(bookId).build())
            .build();
    }
}

Zu diesem Zeitpunkt können wir unter dem Pfad/library/booksin der Webanwendung auf die RessourceBookEndpointzugreifen.

7.3. JAX RS JSON-Medientyp

JAX RS unterstützt viele Medientypen für die Kommunikation mit REST-Clients, jedochEclipse MicroProfile restricts the use of JSON, da es die Verwendung der JSOP-P-API angibt. Daher müssen wir unsere Methoden mit@Consumes(MediaType.APPLICATION_JSON) und @Produces(MediaType.APPLICATION_JSON). kommentieren

Die Annotation@Consumeschränkt die akzeptierten Formate ein. In diesem Beispiel wird nur das JSON-Datenformat akzeptiert. Der HTTP-AnforderungsheaderContent-Type sollteapplication/json sein.

Die gleiche Idee steckt hinter der Annotation von@Produces. Die JAX RS Runtime sollte die Antwort auf das JSON-Format marshallen. Der HTTP-Header der AnforderungAccept sollteapplication/json. sein

8. JSON-P

JAX RS Runtime unterstützt JSON-P ab Werk, sodass wirJsonObject als Methodeneingabeparameter oder Rückgabetyp verwenden können.

Aber in der realen Welt arbeiten wir oft mit POJO-Klassen. Wir brauchen also eine Möglichkeit, das Mapping zwischenJsonObject und POJO durchzuführen. Hier spielt der JAX RS-Entitätsanbieter.

Um den JSON-Eingabestream für das POJO vonBookzu marshallen, müssen Sie eine KlasseBookMessageBodyReader: erstellen, um eine Ressourcenmethode mit einem Parameter vom TypBook, aufzurufen

@Provider
@Consumes(MediaType.APPLICATION_JSON)
public class BookMessageBodyReader implements MessageBodyReader {

    @Override
    public boolean isReadable(
      Class type, Type genericType,
      Annotation[] annotations,
      MediaType mediaType) {

        return type.equals(Book.class);
    }

    @Override
    public Book readFrom(
      Class type, Type genericType,
      Annotation[] annotations,
      MediaType mediaType,
      MultivaluedMap httpHeaders,
      InputStream entityStream) throws IOException, WebApplicationException {

        return BookMapper.map(entityStream);
    }
}

Wir machen den gleichen Prozess, um einBook für den JSON-Ausgabestream zu entmarschieren. Dabei wird eine Ressourcenmethode aufgerufen, deren RückgabetypBook, ist, indem einBookMessageBodyWriter: erstellt wird

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class BookMessageBodyWriter
  implements MessageBodyWriter {

    @Override
    public boolean isWriteable(
      Class type, Type genericType,
      Annotation[] annotations,
      MediaType mediaType) {

        return type.equals(Book.class);
    }

    // ...

    @Override
    public void writeTo(
      Book book, Class type,
      Type genericType,
      Annotation[] annotations,
      MediaType mediaType,
      MultivaluedMap httpHeaders,
      OutputStream entityStream) throws IOException, WebApplicationException {

        JsonWriter jsonWriter = Json.createWriter(entityStream);
        JsonObject jsonObject = BookMapper.map(book);
        jsonWriter.writeObject(jsonObject);
        jsonWriter.close();
    }
}

DaBookMessageBodyReader undBookMessageBodyWriter mit@Provider versehen sind, werden sie automatisch von der JAX RS-Laufzeit registriert.

9. Erstellen und Ausführen der Anwendung

Eine MicroProfile-Anwendung ist portabel und sollte in jeder kompatiblen MicroProfile-Laufzeit ausgeführt werden. Wir werden erklären, wie unsere Anwendung inOpen Liberty erstellt und ausgeführt wird. Wir können jedoch jedes kompatible Eclipse MicroProfile verwenden.

Wir konfigurieren die Open Liberty-Laufzeit über eine Konfigurationsdateiserver.xml:


    
        jaxrs-2.0
        cdi-1.2
        jsonp-1.0
    
    
    
    

Fügen wir das Pluginliberty-maven-plugin zu unserer pom.xml hinzu:



    net.wasdev.wlp.maven.plugins
    liberty-maven-plugin
    2.1.2
    
        
            io.openliberty
            openliberty-runtime
            17.0.0.4
            zip
        
        ${basedir}/src/main/liberty/config/server.xml
        ${package.file}
        ${packaging.type}
        false
        project
        
            /
            ${project.artifactId}-${project.version}.war
            9080
            9443
        
    
    
        
            install-server
            prepare-package
            
                install-server
                create-server
                install-feature
            
        
        
            package-server-with-apps
            package
            
                install-apps
                package-server
            
        
    

Dieses Plugin kann über eine Reihe von Eigenschaften konfiguriert werden:


    
    library
    ${project.build.directory}/${app.name}-service.jar
    runnable

Das obige exec-Ziel erstellt eine ausführbare JAR-Datei, sodass unsere Anwendung ein unabhängiger Microservice ist, der isoliert bereitgestellt und ausgeführt werden kann. Wir können es auch als Docker-Image bereitstellen.

Führen Sie den folgenden Befehl aus, um eine ausführbare JAR-Datei zu erstellen:

mvn package

Und um unseren Microservice auszuführen, verwenden wir diesen Befehl:

java -jar target/library-service.jar

Dadurch wird die Open Liberty-Laufzeit gestartet und unser Service bereitgestellt. Wir können auf unseren Endpoint zugreifen und alle Bücher unter dieser URL abrufen:

curl http://localhost:9080/library/books

Das Ergebnis ist ein JSON:

[
  {
    "id": "0001-201802",
    "isbn": "1",
    "name": "Building Microservice With Eclipse MicroProfile",
    "author": "example",
    "pages": 420
  }
]

Um ein einzelnes Buch zu erhalten, fordern wir diese URL an:

curl http://localhost:9080/library/books/0001-201802

Und das Ergebnis ist JSON:

{
    "id": "0001-201802",
    "isbn": "1",
    "name": "Building Microservice With Eclipse MicroProfile",
    "author": "example",
    "pages": 420
}

Jetzt fügen wir ein neues Buch hinzu, indem wir mit der API interagieren:

curl
  -H "Content-Type: application/json"
  -X POST
  -d '{"isbn": "22", "name": "Gradle in Action","author": "example","pages": 420}'
  http://localhost:9080/library/books

Wie wir sehen können, lautet der Status der Antwort 201, was darauf hinweist, dass das Buch erfolgreich erstellt wurde, undLocation ist der URI, über den wir darauf zugreifen können:

< HTTP/1.1 201 Created
< Location: http://localhost:9080/library/books/0009-201802

10. Fazit

In diesem Artikel wurde gezeigt, wie ein einfacher Mikroservice auf der Basis von Eclipse MicroProfile erstellt wird, wobei JAX RS, JSON-P und CDI erläutert werden.

Der Code ist verfügbarover on Github; Da es sich um ein Maven-basiertes Projekt handelt, sollte es einfach zu importieren und so auszuführen sein, wie es ist.