Skip to content

Commit

Permalink
WildFly mini series: REST Client
Browse files Browse the repository at this point in the history
  • Loading branch information
tommaso-borgato committed Nov 28, 2024
1 parent 57bef13 commit ffb745e
Show file tree
Hide file tree
Showing 7 changed files with 1,363 additions and 11 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 16 additions & 8 deletions guides/get-started-microservices-on-kubernetes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,22 @@ We will start building a link:https://docs.docker.com/[Docker Image, window="_bl

=== Guides in this series

* link:/guides/get-started-microservices-on-kubernetes/simple-microservice-part1[{simple-microservice-part1}]
* link:/guides/get-started-microservices-on-kubernetes/simple-microservice-part2[{simple-microservice-part2}]
* link:/guides/get-started-microservices-on-kubernetes/simple-microservice-database-part1[{simple-microservice-database-part1}]
* link:/guides/get-started-microservices-on-kubernetes/simple-microservice-database-part2[{simple-microservice-database-part2}]
* link:/guides/get-started-microservices-on-kubernetes/simple-microservice-infinispan-part1[{simple-microservice-infinispan-part1}]
* link:/guides/get-started-microservices-on-kubernetes/simple-microservice-infinispan-part2[{simple-microservice-infinispan-part2}]
* link:/guides/get-started-microservices-on-kubernetes/simple-microservice-jms-part1[{simple-microservice-jms-part1}]
* link:/guides/get-started-microservices-on-kubernetes/simple-microservice-jms-part2[{simple-microservice-jms-part2}]
* **{simple-microservice-header}**
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-part1[{simple-microservice-part1}]
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-part2[{simple-microservice-part2}]
* **{simple-microservice-database-header}**
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-database-part1[{simple-microservice-database-part1}]
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-database-part2[{simple-microservice-database-part2}]
* **{simple-microservice-infinispan-header}**
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-infinispan-part1[{simple-microservice-infinispan-part1}]
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-infinispan-part2[{simple-microservice-infinispan-part2}]
* **{simple-microservice-jms-header}**
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-jms-part1[{simple-microservice-jms-part1}]
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-jms-part2[{simple-microservice-jms-part2}]
* **{simple-microservice-client-header}**
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-client-part1[{simple-microservice-client-part1}]
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-client-part2[{simple-microservice-client-part2}]
** link:/guides/get-started-microservices-on-kubernetes/simple-microservice-client-part3[{simple-microservice-client-part3}]
//* link:get-enterprise-ready[{get-enterprise-ready}]

[[references]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
:jaxrs-example-project-groupId: org.wildfly.examples
:jaxrs-example-project-artifactId: jaxrs
:jaxrs-example-project-version: 11.0.0.Final-SNAPSHOT
:version-bootable-jar: 11.0.0.Beta1
:version-wildfly-galleon-pack: 32.0.0.Final
:version-wildfly: 34.0.1.Final
:version-wildfly-galleon-pack: 34.0.1.Final
:jakarta-jakartaee-api-version: 10.0.0
:version-junit-jupiter-api: 5.10.2
:version-arquillian-junit5-container: 1.8.0.Final
:version-org-wildfly-arquillian-wildfly-arquillian: 5.1.0.Beta1
:version-resteasy-client: 6.2.7.Final
:version-wildfly-cloud-galleon-pack: 7.0.0.Final
:version-wildfly-cloud-galleon-pack: 7.0.2.Final
:version-wildfly-maven-plugin: 5.0.0.Final
:my-jaxrs-app-docker-image-name: my-jaxrs-app
:my-jaxrs-app-db-docker-image-name: my-jaxrs-app-db
Expand Down Expand Up @@ -46,3 +46,19 @@
:artemis-console-port-name: artemis-console-port
:my-jms-app-docker-image-name: my-jms-app
:podman-network-name: demo-network
:my-jaxrs-app-docker-image-name-client: my-jaxrs-app-client
:my-jaxrs-app-docker-image-name-server: my-jaxrs-app-server
:simple-microservice-client-secured: simple-microservice-client-secured
:simple-microservice-server-secured: simple-microservice-server-secured
:keycloak-external: keycloak-external
:keycloak-internal: keycloak-internal
:keycloak-realm: keycloak-realm
:keycloak-data-import: keycloak-data-import
:keycloak-admin-user: admin
:keycloak-admin-pws: admin
:keycloak-user1: alice
:keycloak-user1-pws: 123
:keycloak-user2: bob
:keycloak-user2-pws: 123
:keycloak-role1: user
:keycloak-role2: admin
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
:simple-microservice-header: WildFly Java Microservice
:simple-microservice-part1: WildFly Java Microservice - PART 1: Docker Image
:simple-microservice-part2: WildFly Java Microservice - PART 2: Kubernetes
:simple-microservice-database-header: Connecting to a DB
:simple-microservice-database-part1: Connecting to a DB - PART 1: Docker Image
:simple-microservice-database-part2: Connecting to a DB - PART 2: Kubernetes
:simple-microservice-jms-header: Using a Message Broker
:simple-microservice-jms-part1: Using a Message Broker - PART 1: Docker Image
:simple-microservice-jms-part2: Using a Message Broker - PART 2: Kubernetes
:simple-microservice-infinispan-header: Using Infinispan remote cache
:simple-microservice-infinispan-part1: Using Infinispan remote cache - PART 1: Docker Image
:simple-microservice-infinispan-part2: Using Infinispan remote cache - PART 2: Kubernetes
:simple-microservice-client-header: Invoke one Microservices from another
:simple-microservice-client-part1: Invoke one Microservices from another - PART 1: Docker Images
:simple-microservice-client-part2: Invoke one Microservices from another - PART 2: Kubernetes
:simple-microservice-client-part3: Invoke one Microservices from another - PART 3: Propagate Authentication
:get-enterprise-ready: Get “Enterprise” ready
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
= {simple-microservice-client-part1}
:summary: Invoke one microservice from another
:includedir: ../_includes
include::{includedir}/_attributes.adoc[]
include::./_includes/_titles.adoc[]
include::_includes/_constants.adoc[]
// you can override any attributes eg to lengthen the
// time to complete the guide
:prerequisites-time: 10

In this guide, you will learn HOW-TO invoke one microservice from another;

[[prerequisites]]
== Prerequisites

To complete this guide, you need:

* Complete link:simple-microservice-part1[{simple-microservice-part1}]

== Introduction

This guide is the first in a series of three:

1. In link:simple-microservice-client-part1[{simple-microservice-client-part1}] (this guide), we explain HOW-TO invoke one microservice from another;
2. In link:simple-microservice-client-part2[{simple-microservice-client-part2}], as usual, we explain HOW-TO run the whole thing on Kubernetes
3. In link:simple-microservice-client-part3[{simple-microservice-client-part3}] we explain HOW-TO propagate user authentication and authorization data from the calling microservice to the invoked microservice; this is most useful in a scenario where you have a "chain" of microservices ("**A -> B -> C -> etc.**") and you want the user's authentication and authorization data to be propagated from one microservice to the next;

== This Guide

In these guides, we work with a simple invocation chain composed by +++<u>two</u>+++ microservices:

* **Microservice A**: acting as **client**
* **Microservice B**: acting as **server**

Our invocation chain is then: "**Microservice A -> Microservice B**": when working with https://microprofile.io/[Microprofile], this is achieved by using the https://github.com/eclipse/microprofile-rest-client[microprofile-rest-client];

Specifically, **Microservice A** will use the https://github.com/eclipse/microprofile-rest-client[microprofile-rest-client] to invoke the Jakarta REST service exposed by **Microservice B**;

For both services, we will start from the microservice we built in link:simple-microservice-part1[{simple-microservice-part1}] (complete code in {source-code-git-repository}/simple-microservice);

== Microservice B - the server

We start from the server because we need the server's API for the client later on;

=== Maven Project

Copy {source-code-git-repository}/simple-microservice into a new folder named *simple-microservice-server* and:

* remove folder *src/test*
* remove all test scope dependencies

NOTE: we remove tests because, since we are going to introduce service to service invocation, they wouldn't be much useful anymore

==== pom.xml

Update the `artifactId` to `<artifactId>simple-microservice-server</artifactId>`;

NOTE: **Microservice B** is basically unchanged, we will modify it in link:simple-microservice-client-part3[{simple-microservice-client-part3}]

==== Build the application

[source,bash]
----
mvn clean package
----

=== Docker Image

==== Dockerfile

Since you copied {source-code-git-repository}/simple-microservice[simple-microservice], the Dockerfile from link:https://github.com/wildfly/wildfly-s2i/blob/main/examples/docker-build/Dockerfile[examples/docker-build/Dockerfile, window="_blank"] should already be at the root of your project;

==== Build the Docker Image

[source,bash,subs="normal"]
----
podman build -t {my-jaxrs-app-docker-image-name-server}:latest .
----

NOTE: you can use link:https://docs.wildfly.org/wildfly-maven-plugin/releases/5.1/image-mojo.html[`wildfly-maven-plugin`, window="_blank"] to automate the image build and, also, to automate the image push to an image registry

==== Run the Docker Image

First we create a network for our containers:

[source,bash,subs="normal"]
----
podman network create {podman-network-name}
----

Then we run our container using this network:

[source,bash,subs="normal"]
----
podman run --rm -p 8180:8080 -p 10090:9990 \
--network={podman-network-name} \
--name={my-jaxrs-app-docker-image-name-server} \
{my-jaxrs-app-docker-image-name-server}
----

== Microservice A - the client

=== Maven Project

Copy {source-code-git-repository}/simple-microservice into a new folder named *simple-microservice-client* and:

* remove folder *src/test*
* remove all test scope dependencies

NOTE: we remove tests because, since we are going to introduce service to service invocation, they wouldn't be much useful anymore

==== pom.xml

Set `<artifactId>simple-microservice-client</artifactId>`;

Add the following to `dependencyManagement`:

[source,xml,subs="normal"]
----
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>wildfly-microprofile</artifactId>
<version>${version.wildfly.bom}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
----

Add the following to `dependencies`:

[source,xml,subs="normal"]
----
<dependency>
<groupId>org.eclipse.microprofile.rest.client</groupId>
<artifactId>microprofile-rest-client-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.microprofile.config</groupId>
<artifactId>microprofile-config-api</artifactId>
<scope>provided</scope>
</dependency>
----

Add the following `layers` in the `wildfly-maven-plugin`:

[source,xml,subs="normal"]
----
<layer>microprofile-config</layer>
<layer>microprofile-rest-client</layer>
----

Later on, we will use:

* **microprofile-config** to make the URL to **Microservice B** configurable
* **microprofile-rest-client** to actually invoke **Microservice B**

==== microprofile-config.properties

As anticipated, we use **microprofile-config** to make the URL to **Microservice B** configurable;

Add file `src/main/resources/META-INF/microprofile-config.properties` with the following content:

.microprofile-config.properties:
[source,properties]
----
simple-microservice-server/mp-rest/uri=${simple-microservice-server-uri:http://127.0.0.1:8080}
simple-microservice-server/mp-rest/connectTimeout=3000
----

NOTE: `simple-microservice-server-uri` would pick up its value, whenever set, from the environment variable named `SIMPLE_MICROSERVICE_SERVER_URI` (see https://download.eclipse.org/microprofile/microprofile-config-3.0/microprofile-config-spec-3.0.html#default_configsources.env.mapping[env.mapping])

==== Java code

Add the following interface:

.GettingStartedEndpointInterface.java:
[source,java]
----
package org.wildfly.examples;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
@RegisterRestClient(configKey="simple-microservice-server")
@Path("/hello")
public interface GettingStartedEndpointInterface {
@GET
@Path("/{name}")
@Produces(MediaType.TEXT_PLAIN)
public Response sayHello(final @PathParam("name") String name);
}
----

NOTE: this class is used to define the API to be invoked by the Rest Client; the actual URL where the remote service is
located, comes from the `microprofile-config.properties` file we just added;

Remove the `src/main/java/org/wildfly/examples/GettingStartedService.java` file and replace the content of
`src/main/java/org/wildfly/examples/GettingStartedEndpoint.java` with the following:

.GettingStartedEndpoint.java:
[source,java]
----
package org.wildfly.examples;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.rest.client.inject.RestClient;
@Path("/")
public class GettingStartedEndpoint {
@Inject
@RestClient
private GettingStartedEndpointInterface service;
@GET
@Path("/{name}")
@Produces(MediaType.TEXT_PLAIN)
public Response sayHello(final @PathParam("name") String name) {
return service.sayHello(name);
}
}
----

NOTE: as anticipated, we use **microprofile-rest-client** to actually invoke **Microservice B**

==== Build the application

[source,bash]
----
mvn clean package
----

=== Docker Image

==== Dockerfile

Since you copied {source-code-git-repository}/simple-microservice[simple-microservice], the Dockerfile from link:https://github.com/wildfly/wildfly-s2i/blob/main/examples/docker-build/Dockerfile[examples/docker-build/Dockerfile, window="_blank"] should already be at the root of your project;

==== Build the Docker Image `{my-jaxrs-app-docker-image-name-client}:latest` with the following command:

[source,bash,subs="normal"]
----
podman build -t {my-jaxrs-app-docker-image-name-client}:latest .
----

==== Run the Docker Image

[source,bash,subs="normal"]
----
podman run --rm -p 8080:8080 -p 9990:9990 \
--network={podman-network-name} \
--env "SIMPLE_MICROSERVICE_SERVER_URI=http://{my-jaxrs-app-docker-image-name-server}:8080/hello" \
--name={my-jaxrs-app-docker-image-name-client} \
{my-jaxrs-app-docker-image-name-client}
----

NOTE: The **{my-jaxrs-app-docker-image-name-server}** container can be reached, inside the **{podman-network-name}** network, using the DNS name **{my-jaxrs-app-docker-image-name-server}**

== Test

Open http://localhost:8080[http://localhost:8080] in your browser: this web page is served by the **{my-jaxrs-app-docker-image-name-client}** container;

Write something in the "Name" input box and then press "Say Hello": the response you'll see will come from **{my-jaxrs-app-docker-image-name-server}** container!

The complete invocation chain is "**web browser** -> **{my-jaxrs-app-docker-image-name-client}** -> **{my-jaxrs-app-docker-image-name-server}**"

== What's next?

link:simple-microservice-client-part2[{simple-microservice-client-part2}]

[[references]]
== References

* https://microprofile.io/specifications/microprofile-rest-client[microprofile-rest-client]
* https://microprofile.io/specifications/microprofile-config[microprofile-config]
* Source code for this guide:
** {source-code-git-repository}/simple-microservice-rest-client/simple-microservice-client
** {source-code-git-repository}/simple-microservice-rest-client/simple-microservice-server


Loading

0 comments on commit ffb745e

Please sign in to comment.