Introduzione a Open Liberty

1. Panoramica

Con la popolarità dell'architettura di microservizi e lo sviluppo di applicazioni native per il cloud, c'è una crescente necessità di un server di applicazioni veloce e leggero.

In questo tutorial introduttivo, esploreremo il framework Open Liberty per creare e utilizzare un servizio Web RESTful. Esamineremo anche alcune delle funzionalità essenziali che fornisce.

2. Apri Liberty

Open Liberty è un framework aperto per l'ecosistema Java che consente lo sviluppo di microservizi utilizzando le funzionalità delle piattaforme Eclipse MicroProfile e Jakarta EE .

È un runtime Java flessibile, veloce e leggero che sembra promettente per lo sviluppo di microservizi cloud-native.

Il framework ci consente di configurare solo le funzionalità di cui la nostra app ha bisogno, con un conseguente minore impatto di memoria durante l'avvio. Inoltre, è distribuibile su qualsiasi piattaforma cloud utilizzando contenitori come Docker e Kubernetes.

Supporta lo sviluppo rapido ricaricando in tempo reale il codice per una rapida iterazione.

3. Crea ed esegui

Per prima cosa, creeremo un semplice progetto basato su Maven chiamato open-liberty e poi aggiungeremo l'ultimo plugin liberty-maven- plugin al pom.xml :

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

Oppure, possiamo aggiungere l'ultima dipendenza Maven openliberty-runtime come alternativa al plugin liberty-maven :

 io.openliberty openliberty-runtime 20.0.0.1 zip 

Allo stesso modo, possiamo aggiungere l'ultima dipendenza Gradle a build.gradle :

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

Quindi, aggiungeremo le ultime dipendenze jakarta.jakartaee-web-api e microprofile Maven:

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

Quindi, aggiungiamo le proprietà della porta HTTP predefinita al pom.xml :

 9080 9443 

Successivamente, creeremo il file server.xml nella directory src / main / liberty / config :

  mpHealth-2.0    

Qui abbiamo aggiunto la funzione mpHealth-2.0 per controllare lo stato di salute dell'applicazione.

È tutto con tutte le impostazioni di base. Eseguiamo il comando Maven per compilare i file per la prima volta:

mvn clean package

Infine, eseguiamo il server utilizzando un comando Maven fornito da Liberty:

mvn liberty:dev

Ecco! La nostra applicazione viene avviata e sarà accessibile da localhost: 9080 :

Inoltre, possiamo accedere allo stato di salute dell'app su localhost: 9080 / health :

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

Il comando liberty: dev avvia il server Open Liberty in modalità di sviluppo , che ricarica a caldo tutte le modifiche apportate al codice o alla configurazione senza riavviare il server.

Allo stesso modo, il comando liberty: run è disponibile per avviare il server in modalità di produzione.

Inoltre, possiamo usare liberty: start-server e liberty: stop-server per avviare / arrestare il server in background .

4. Servlet

Per utilizzare i servlet nell'app, aggiungeremo la funzionalità servlet-4.0 a server.xml :

 ... servlet-4.0 

Aggiungi l'ultima dipendenza Maven servlet-4.0 se si utilizza la dipendenza Maven openliberty-runtime nel pom.xml :

 io.openliberty.features servlet-4.0 20.0.0.1 esa 

Tuttavia, se stiamo usando il plugin liberty-maven- plugin, questo non è necessario.

Quindi, creeremo la classe AppServlet estendendo 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); } }

Qui, abbiamo aggiunto l' annotazione @WebServlet che renderà l' AppServlet disponibile al pattern URL specificato.

Accediamo al servlet su localhost: 9080 / app :

5. Creare un servizio Web RESTful

Innanzitutto, aggiungiamo la funzionalità jaxrs-2.1 a 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. Conclusione

In questo articolo, abbiamo esplorato il framework Open Liberty, un runtime Java veloce e leggero che fornisce funzionalità complete delle piattaforme Eclipse MicroProfile e Jakarta EE.

Per cominciare, abbiamo creato un servizio web RESTful utilizzando JAX-RS. Quindi, abbiamo abilitato la persistenza utilizzando funzionalità come JPA e CDI.

Infine, abbiamo utilizzato il servizio Web RESTful utilizzando JSON-B.

Come al solito, tutte le implementazioni del codice sono disponibili su GitHub.