Invoke one Microservices from another - PART 1: Container Images
In this guide, you will learn HOW-TO invoke one microservice from another;
Prerequisites
To complete this guide, you need:
Introduction
This guide is the first in a series of three:
- 
In Invoke one Microservices from another - PART 1: Container Images (this guide), we explain HOW-TO invoke one microservice from another; 
- 
In Invoke one Microservices from another - PART 2: Kubernetes, as usual, we explain HOW-TO run the whole thing on Kubernetes 
- 
In Invoke one Microservices from another - PART 3: Propagate Authentication 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 two microservices:
- 
Microservice A: acting as client 
- 
Microservice B: acting as server 
Our invocation chain is then: "Microservice A → Microservice B": when working with Microprofile, this is achieved by using the microprofile-rest-client;
Specifically, Microservice A will use the 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 WildFly Java Microservice - PART 1: Container Image (complete code in https://github.com/wildfly-extras/guides/tree/main/get-started-microservices-on-kubernetes/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 https://github.com/wildfly-extras/guides/tree/main/get-started-microservices-on-kubernetes/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 Invoke one Microservices from another - PART 3: Propagate Authentication | 
Build the application
mvn clean packageDocker Image
Dockerfile
Since you copied simple-microservice, the Dockerfile from examples/docker-build/Dockerfile should already be at the root of your project;
Build the Docker Image
podman build -t simple-microservice-server:latest .| Note | You can use wildfly-maven-pluginto automate the image build | 
Run the Docker Image
First we create a network for our containers:
podman network create demo-networkThen we run our container using this network:
podman run --rm -p 8180:8080 -p 10090:9990 \
  --network=demo-network \
  --name=simple-microservice-server \
  simple-microservice-serverMicroservice A - the client
Maven Project
Copy https://github.com/wildfly-extras/guides/tree/main/get-started-microservices-on-kubernetes/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
Update the artifactId to <artifactId>simple-microservice-client</artifactId>;
Add the following to dependencyManagement:
<dependency>
    <groupId>org.wildfly.bom</groupId>
    <artifactId>wildfly-expansion</artifactId>
    <version>${version.wildfly.bom}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>Add the following to dependencies:
    <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:
    <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:
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-uriwould pick up its value, whenever set, from the environment variable namedSIMPLE_MICROSERVICE_SERVER_URI(see env.mapping) | 
Java code
Add the following interface:
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 GettingStartedEndpointClient {
	@GET
	@Path("/{name}")
	@Produces(MediaType.TEXT_PLAIN)
	Response sayHello(@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.propertiesfile 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:
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 GettingStartedEndpointClient client;
    @GET
    @Path("/{name}")
    @Produces(MediaType.TEXT_PLAIN)
    public Response sayHello(final @PathParam("name") String name) {
        return client.sayHello(name);
    }
}| Note | as anticipated, we use microprofile-rest-client to actually invoke Microservice B | 
Build the application
mvn clean packageDocker Image
Dockerfile
Since you copied simple-microservice, the Dockerfile from examples/docker-build/Dockerfile should already be at the root of your project;
Build the Docker Image
Build the Docker Image simple-microservice-client:latest with the following command:
podman build -t simple-microservice-client:latest .| Note | You can use wildfly-maven-pluginto automate the image build | 
Run the Docker Image
podman run --rm -p 8080:8080 -p 9990:9990 \
  --network=demo-network \
  --env "SIMPLE_MICROSERVICE_SERVER_URI=http://simple-microservice-server:8080" \
  --name=simple-microservice-client \
  simple-microservice-client| Note | The simple-microservice-server container can be reached, inside the demo-network network, using the DNS name simple-microservice-server | 
Test
Open http://localhost:8080 in your browser: this web page is served by the simple-microservice-client container;
Write something in the "Name" input box and then press "Say Hello": the response you’ll see will come from simple-microservice-server container!
The complete invocation chain is "web browser → simple-microservice-client → simple-microservice-server"
References
- 
Source code for this guide: 
