Introduction à Open Liberty

1. Vue d'ensemble

Avec la popularité de l'architecture de microservices et du développement d'applications natives dans le cloud, il existe un besoin croissant d'un serveur d'applications rapide et léger.

Dans ce didacticiel d'introduction, nous explorerons le framework Open Liberty pour créer et utiliser un service Web RESTful. Nous examinerons également quelques-unes des fonctionnalités essentielles qu'il fournit.

2. Ouvrez Liberty

Open Liberty est un framework ouvert pour l'écosystème Java qui permet de développer des microservices à l'aide des fonctionnalités des plates-formes Eclipse MicroProfile et Jakarta EE .

Il s'agit d'un environnement d'exécution Java flexible, rapide et léger qui semble prometteur pour le développement de microservices cloud natifs.

Le framework nous permet de configurer uniquement les fonctionnalités dont notre application a besoin, ce qui réduit l'empreinte mémoire au démarrage. En outre, il est déployable sur n'importe quelle plate-forme cloud à l'aide de conteneurs tels que Docker et Kubernetes.

Il prend en charge le développement rapide en rechargeant en direct le code pour une itération rapide.

3. Construire et exécuter

Tout d'abord, nous allons créer un projet simple basé sur Maven nommé open-liberty , puis ajouter le dernier plugin liberty-maven- plugin au pom.xml :

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

Ou, nous pouvons ajouter la dernière dépendance Maven openliberty-runtime comme alternative à liberty-maven-plugin :

 io.openliberty openliberty-runtime 20.0.0.1 zip 

De même, nous pouvons ajouter la dernière dépendance Gradle à build.gradle :

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

Ensuite, nous ajouterons les dernières dépendances jakarta.jakartaee-web-api et microprofile Maven:

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

Ensuite, ajoutons les propriétés de port HTTP par défaut au pom.xml :

 9080 9443 

Ensuite, nous allons créer le fichier server.xml dans le répertoire src / main / liberty / config :

  mpHealth-2.0    

Ici, nous avons ajouté la fonctionnalité mpHealth-2.0 pour vérifier l'état de santé de l'application.

C'est tout avec toute la configuration de base. Exécutons la commande Maven pour compiler les fichiers pour la première fois:

mvn clean package

Enfin, exécutons le serveur à l'aide d'une commande Maven fournie par Liberty:

mvn liberty:dev

Voila! Notre application est lancée et sera accessible sur localhost: 9080 :

En outre, nous pouvons accéder à la santé de l'application sur localhost: 9080 / health :

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

La commande liberty: dev démarre le serveur Open Liberty en mode développement , qui recharge à chaud toutes les modifications apportées au code ou à la configuration sans redémarrer le serveur.

De même, la commande liberty: run est disponible pour démarrer le serveur en mode production.

De plus, nous pouvons utiliser liberty: start-server et liberty: stop-server pour démarrer / arrêter le serveur en arrière-plan .

4. Servlet

Pour utiliser les servlets dans l'application, nous ajouterons la fonctionnalité servlet-4.0 au server.xml :

 ... servlet-4.0 

Ajoutez la dernière dépendance Maven servlet-4.0 si vous utilisez la dépendance Maven openliberty-runtime dans le fichier pom.xml :

 io.openliberty.features servlet-4.0 20.0.0.1 esa 

Cependant, si nous utilisons le plugin liberty-maven- plugin, ce n'est pas nécessaire.

Ensuite, nous allons créer la classe AppServlet étendant la classe HttpServlet :

@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); } }

Ici, nous avons ajouté l' annotation @WebServlet qui rendra l' AppServlet disponible au modèle d'URL spécifié.

Accédons au servlet sur localhost: 9080 / app :

5. Créez un service Web RESTful

Tout d'abord, ajoutons la fonctionnalité jaxrs-2.1 au server.xml :

 ... 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. Conclusion

Dans cet article, nous avons exploré le framework Open Liberty - un runtime Java rapide et léger qui fournit toutes les fonctionnalités des plates-formes Eclipse MicroProfile et Jakarta EE.

Pour commencer, nous avons créé un service Web RESTful à l'aide de JAX-RS. Ensuite, nous avons activé la persistance à l'aide de fonctionnalités telles que JPA et CDI.

Enfin, nous avons utilisé le service Web RESTful en utilisant JSON-B.

Comme d'habitude, toutes les implémentations de code sont disponibles sur sur GitHub.