Einführung in Open Liberty

1. Übersicht

Mit der Popularität der Microservice-Architektur und der Cloud-nativen Anwendungsentwicklung wächst der Bedarf an einem schnellen und leichten Anwendungsserver.

In diesem Einführungs-Tutorial werden wir das Open Liberty-Framework untersuchen, um einen RESTful-Webdienst zu erstellen und zu nutzen. Wir werden auch einige der wesentlichen Funktionen untersuchen, die es bietet.

2. Öffnen Sie Liberty

Open Liberty ist ein offenes Framework für das Java-Ökosystem, mit dem Microservices mithilfe der Funktionen der Eclipse MicroProfile- und Jakarta EE-Plattformen entwickelt werden können .

Es ist eine flexible, schnelle und leichte Java-Laufzeit, die für die Entwicklung von Cloud-nativen Microservices vielversprechend erscheint.

Mit dem Framework können wir nur die Funktionen konfigurieren, die unsere App benötigt, was zu einem geringeren Speicherbedarf beim Start führt. Es kann auch auf jeder Cloud-Plattform mit Containern wie Docker und Kubernetes bereitgestellt werden.

Es unterstützt die schnelle Entwicklung durch Live-Neuladen des Codes für eine schnelle Iteration.

3. Erstellen und ausführen

Zuerst erstellen wir ein einfaches Maven-basiertes Projekt namens open-liberty und fügen dann das neueste liberty-maven-plugin- Plugin zur pom.xml hinzu :

 io.openliberty.tools liberty-maven-plugin 3.3-M3 

Oder wir können die neueste OpenLiberty-Laufzeit- Maven-Abhängigkeit als Alternative zum Liberty-Maven-Plugin hinzufügen :

 io.openliberty openliberty-runtime 20.0.0.1 zip 

Ebenso können wir der build.gradle die neueste Gradle-Abhängigkeit hinzufügen :

dependencies { libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '20.0.0.1' }

Dann fügen wir die neuesten Abhängigkeiten von jakarta.jakartaee-web-api und Mikroprofil- Maven hinzu:

 jakarta.platform jakarta.jakartaee-web-api 8.0.0 provided   org.eclipse.microprofile microprofile 3.2 pom provided 

Fügen wir dann der pom.xml die Standard-HTTP- Porteigenschaften hinzu :

 9080 9443 

Als Nächstes erstellen wir die Datei server.xml im Verzeichnis src / main / liberty / config :

  mpHealth-2.0    

Hier haben wir die Funktion mpHealth-2.0 hinzugefügt, um den Zustand der Anwendung zu überprüfen.

Das war's mit allen grundlegenden Einstellungen. Führen Sie den Befehl Maven aus, um die Dateien zum ersten Mal zu kompilieren:

mvn clean package

Zuletzt führen wir den Server mit einem von Liberty bereitgestellten Maven-Befehl aus:

mvn liberty:dev

Voila! Unsere Anwendung wird gestartet und ist unter localhost verfügbar : 9080 :

Außerdem können wir unter localhost auf den Zustand der App zugreifen : 9080 / health :

{"checks":[],"status":"UP"}

Der Befehl liberty: dev startet den Open Liberty-Server im Entwicklungsmodus , der alle am Code oder an der Konfiguration vorgenommenen Änderungen im laufenden Betrieb neu lädt, ohne den Server neu zu starten.

Ebenso steht der Befehl liberty: run zur Verfügung, um den Server im Produktionsmodus zu starten.

Wir können auch liberty: start-server und liberty: stop-server verwenden , um den Server im Hintergrund zu starten / stoppen .

4. Servlet

Um Servlets in der App zu verwenden, fügen wir der server.xml die Servlet-4.0- Funktion hinzu :

 ... servlet-4.0 

Fügen Sie die neueste Servlet-4.0- Maven-Abhängigkeit hinzu, wenn Sie die OpenLiberty-Runtime- Maven-Abhängigkeit in der Datei pom.xml verwenden :

 io.openliberty.features servlet-4.0 20.0.0.1 esa 

Wenn wir jedoch das Liberty-Maven-Plugin- Plugin verwenden, ist dies nicht erforderlich.

Anschließend erstellen wir die AppServlet- Klasse, die die HttpServlet- Klasse erweitert:

@WebServlet(urlPatterns="/app") public class AppServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String htmlOutput = "

Hello! Welcome to Open Liberty

"; response.getWriter().append(htmlOutput); } }

Hier haben wir die Annotation @WebServlet hinzugefügt , mit der das AppServlet unter dem angegebenen URL-Muster verfügbar gemacht wird.

Greifen wir auf das Servlet unter localhost zu: 9080 / app :

5. Erstellen Sie einen RESTful-Webdienst

Fügen wir zunächst die Funktion jaxrs-2.1 zur Datei server.xml hinzu :

 ... jaxrs-2.1 

Then, we'll create the ApiApplication class, which provides endpoints to the RESTful web service:

@ApplicationPath("/api") public class ApiApplication extends Application { }

Here, we've used the @ApplicationPath annotation for the URL path.

Then, let's create the Person class that serves the model:

public class Person { private String username; private String email; // getters and setters // constructors }

Next, we'll create the PersonResource class to define the HTTP mappings:

@RequestScoped @Path("persons") public class PersonResource { @GET @Produces(MediaType.APPLICATION_JSON) public List getAllPersons() { return Arrays.asList(new Person(1, "normanlewis", "[email protected]")); } }

Here, we've added the getAllPersons method for the GET mapping to the /api/persons endpoint. So, we're ready with a RESTful web service, and the liberty:dev command will load changes on-the-fly.

Let's access the /api/persons RESTful web service using a curl GET request:

curl --request GET --url //localhost:9080/api/persons

Then, we'll get a JSON array in response:

[{"id":1, "username":"normanlewis", "email":"[email protected]"}]

Similarly, we can add the POST mapping by creating the addPerson method:

@POST @Consumes(MediaType.APPLICATION_JSON) public Response addPerson(Person person) { String respMessage = "Person " + person.getUsername() + " received successfully."; return Response.status(Response.Status.CREATED).entity(respMessage).build(); }

Now, we can invoke the endpoint with a curl POST request:

curl --request POST --url //localhost:9080/api/persons \ --header 'content-type: application/json' \ --data '{"username": "normanlewis", "email": "[email protected]"}'

The response will look like:

Person normanlewis received successfully.

6. Persistence

6.1. Configuration

Let's add persistence support to our RESTful web services.

First, we'll add the derby Maven dependency to the pom.xml:

 org.apache.derby derby 10.14.2.0 

Then, we'll add a few features like jpa-2.2, jsonp-1.1, and cdi-2.0 to the server.xml:

 ... jpa-2.2 jsonp-1.1 cdi-2.0  

Here, the jsonp-1.1 feature provides the Java API for JSON Processing, and the cdi-2.0 feature handles the scopes and dependency injection.

Next, we'll create the persistence.xml in the src/main/resources/META-INF directory:

   jdbc/jpadatasource      

Here, we've used the EclipseLink DDL generation to create our database schema automatically. We can also use other alternatives like Hibernate.

Then, let's add the dataSource configuration to the server.xml:

Note, the jndiName has the same reference to the jta-data-source tag in the persistence.xml.

6.2. Entity and DAO

Then, we'll add the @Entity annotation and an identifier to our Person class:

@Entity public class Person { @GeneratedValue(strategy = GenerationType.AUTO) @Id private int id; private String username; private String email; // getters and setters }

Next, let's create the PersonDao class that will interact with the database using the EntityManager instance:

@RequestScoped public class PersonDao { @PersistenceContext(name = "jpa-unit") private EntityManager em; public Person createPerson(Person person) { em.persist(person); return person; } public Person readPerson(int personId) { return em.find(Person.class, personId); } }

Note that the @PersistenceContext defines the same reference to the persistence-unit tag in the persistence.xml.

Now, we'll inject the PersonDao dependency in the PersonResource class:

@RequestScoped @Path("person") public class PersonResource { @Inject private PersonDao personDao; // ... }

Here, we've used the @Inject annotation provided by the CDI feature.

Last, we'll update the addPerson method of the PersonResource class to persist the Person object:

@POST @Consumes(MediaType.APPLICATION_JSON) @Transactional public Response addPerson(Person person) { personDao.createPerson(person); String respMessage = "Person #" + person.getId() + " created successfully."; return Response.status(Response.Status.CREATED).entity(respMessage).build(); }

Here, the addPerson method is annotated with the @Transactional annotation to control transactions on CDI managed beans.

Let's invoke the endpoint with the already discussed curl POST request:

curl --request POST --url //localhost:9080/api/persons \ --header 'content-type: application/json' \ --data '{"username": "normanlewis", "email": "[email protected]"}'

Then, we'll receive a text response:

Person #1 created successfully.

Similarly, let's add the getPerson method with GET mapping to fetch a Person object:

@GET @Path("{id}") @Produces(MediaType.APPLICATION_JSON) @Transactional public Person getPerson(@PathParam("id") int id) { Person person = personDao.readPerson(id); return person; }

Let's invoke the endpoint using a curl GET request:

curl --request GET --url //localhost:9080/api/persons/1

Then, we'll get the Person object as JSON response:

{"email":"[email protected]","id":1,"username":"normanlewis"}

7. Consume RESTful Web Service Using JSON-B

First, we'll enable the ability to directly serialize and deserialize models by adding the jsonb-1.0 feature to the server.xml:

 ... jsonb-1.0 

Then, let's create the RestConsumer class with the consumeWithJsonb method:

public class RestConsumer { public static String consumeWithJsonb(String targetUrl) { Client client = ClientBuilder.newClient(); Response response = client.target(targetUrl).request().get(); String result = response.readEntity(String.class); response.close(); client.close(); return result; } }

Here, we've used the ClientBuilder class to request the RESTful web service endpoints.

Last, let's write a unit test to consume the /api/person RESTful web service and verify the response:

@Test public void whenConsumeWithJsonb_thenGetPerson() { String url = "//localhost:9080/api/persons/1"; String result = RestConsumer.consumeWithJsonb(url); Person person = JsonbBuilder.create().fromJson(result, Person.class); assertEquals(1, person.getId()); assertEquals("normanlewis", person.getUsername()); assertEquals("[email protected]", person.getEmail()); }

Here, we've used the JsonbBuilder class to parse the String response into the Person object.

Also, we can use MicroProfile Rest Client by adding the mpRestClient-1.3 feature to consume the RESTful web services. It provides the RestClientBuilder interface to request the RESTful web service endpoints.

8. Fazit

In diesem Artikel haben wir das Open Liberty-Framework untersucht - eine schnelle und einfache Java-Laufzeit, die alle Funktionen der Eclipse MicroProfile- und Jakarta EE-Plattformen bietet.

Zunächst haben wir mit JAX-RS einen RESTful-Webdienst erstellt. Anschließend haben wir die Persistenz mithilfe von Funktionen wie JPA und CDI aktiviert.

Zuletzt haben wir den RESTful-Webdienst mit JSON-B verwendet.

Wie üblich sind alle Code-Implementierungen über GitHub verfügbar.