Containerizing microservices

duration 15 minutes

Prerequisites:

Learn how to containerize and run your microservices with Open Liberty using Docker.

What you’ll learn

You can easily deploy your microservices in different environments in a lightweight and portable manner by using containers. From development to production and across your DevOps environments, you can deploy your microservices consistently and efficiently with containers. You can run a container from a container image. Each container image is a package of what you need to run your microservice or application, from the code to its dependencies and configuration.

You’ll learn how to build container images and run containers using Docker for your microservices. You’ll construct Dockerfile files, create Docker images by using the docker build command, and run the image as Docker containers by using docker run command.

The two microservices that you’ll be working with are called system and inventory. The system microservice returns the JVM system properties of the running container. The inventory microservice adds the properties from the system microservice to the inventory. This guide demonstrates how both microservices can run and communicate with each other in different Docker containers.

Getting started

The fastest way to work through this guide is to clone the Git repository and use the projects that are provided inside:

git clone https://github.com/openliberty/guide-containerize.git
cd guide-containerize

The start directory contains the starting project that you will build upon.

The finish directory contains the finished project that you will build.

Packaging your microservices

Navigate to the start directory to begin. You can find the starting Java project in the start directory. It is a multi-module Maven project that is made up of the system and inventory microservices. Each microservice lives in its own corresponding directory, system and inventory.

To try out the application by using Maven, run the following Maven goals to build the application and run it inside Open Liberty:

mvn install
mvn liberty:start-server

Notice that the <packageFile> tag in the pom.xml file configures the microservices to be packaged in an archive form. The system and inventory microservices including the application WAR and server configuration files are archived into system/target/system.tar.gz and inventory/target/inventory.tar.gz.

To access the inventory service, which displays the current contents of the inventory, see http://localhost:9081/inventory/systems.

The system service shows the system properties of the running JVM and can be found at http://localhost:9080/system/properties.

The system properties of your localhost can be added to the inventory at http://localhost:9081/inventory/systems/localhost.

After you are done checking out the application, stop the Open Liberty server:

mvn liberty:stop-server

pom.xml

  1<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  2    <modelVersion>4.0.0</modelVersion>
  3
  4    <parent>
  5        <groupId>net.wasdev.wlp.maven.parent</groupId>
  6        <artifactId>liberty-maven-app-parent</artifactId>
  7        <version>RELEASE</version>
  8    </parent>
  9
 10    <groupId>io.openliberty.guides</groupId>
 11    <artifactId>containerize</artifactId>
 12    <version>1.0-SNAPSHOT</version>
 13    <packaging>pom</packaging>
 14
 15    <properties>
 16        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 17        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 18        <maven.compiler.source>1.8</maven.compiler.source>
 19        <maven.compiler.target>1.8</maven.compiler.target>
 20
 21        <!-- Plugins -->
 22        <version.maven-war-plugin>3.2.2</version.maven-war-plugin>
 23        <version.download-maven-plugin>1.4.0</version.download-maven-plugin>
 24        <version.maven-surefire-plugin>3.0.0-M1</version.maven-surefire-plugin>
 25        <version.maven-failsafe-plugin>3.0.0-M1</version.maven-failsafe-plugin>
 26        <!-- OpenLiberty runtime -->
 27        <version.openliberty-runtime>RELEASE</version.openliberty-runtime>
 28        <sys.service.http.port>9080</sys.service.http.port>
 29        <sys.service.https.port>9443</sys.service.https.port>
 30        <inv.service.http.port>9081</inv.service.http.port>
 31        <inv.service.https.port>9444</inv.service.https.port>
 32    </properties>
 33
 34    <!-- Shared dependencies. -->
 35    <dependencyManagement>
 36        <dependencies>
 37            <dependency>
 38                <groupId>io.openliberty.features</groupId>
 39                <artifactId>features-bom</artifactId>
 40                <version>RELEASE</version>
 41                <type>pom</type>
 42                <scope>import</scope>
 43            </dependency>
 44            <!-- For tests -->
 45            <dependency>
 46                <groupId>junit</groupId>
 47                <artifactId>junit</artifactId>
 48                <version>4.12</version>
 49                <scope>test</scope>
 50            </dependency>
 51            <dependency>
 52                <groupId>org.apache.cxf</groupId>
 53                <artifactId>cxf-rt-rs-client</artifactId>
 54                <version>3.2.6</version>
 55                <scope>test</scope>
 56            </dependency>
 57            <dependency>
 58                <groupId>org.apache.cxf</groupId>
 59                <artifactId>cxf-rt-rs-extension-providers</artifactId>
 60                <version>3.2.6</version>
 61                <scope>test</scope>
 62            </dependency>
 63            <dependency>
 64                <groupId>org.glassfish</groupId>
 65                <artifactId>javax.json</artifactId>
 66                <version>1.0.4</version>
 67                <scope>test</scope>
 68            </dependency>
 69            <dependency>
 70                <groupId>org.apache.commons</groupId>
 71                <artifactId>commons-lang3</artifactId>
 72                <version>3.0</version>
 73                <scope>compile</scope>
 74            </dependency>
 75            <!-- Support for JDK 9 and above -->
 76            <dependency>
 77                <groupId>javax.xml.bind</groupId>
 78                <artifactId>jaxb-api</artifactId>
 79                <version>2.3.1</version>
 80                <scope>provided</scope>
 81            </dependency>
 82            <dependency>
 83                <groupId>com.sun.xml.bind</groupId>
 84                <artifactId>jaxb-core</artifactId>
 85                <version>2.3.0.1</version>
 86                <scope>provided</scope>
 87            </dependency>
 88            <dependency>
 89                <groupId>com.sun.xml.bind</groupId>
 90                <artifactId>jaxb-impl</artifactId>
 91                <version>2.3.2</version>
 92                <scope>provided</scope>
 93            </dependency>
 94            <dependency>
 95                <groupId>javax.activation</groupId>
 96                <artifactId>activation</artifactId>
 97                <version>1.1.1</version>
 98                <scope>provided</scope>
 99            </dependency>
100        </dependencies>
101    </dependencyManagement>
102
103    <profiles>
104        <!-- mvn.cmd for windows systems -->
105        <profile>
106            <id>windowsExtension</id>
107            <activation>
108                <os><family>Windows</family></os>
109            </activation>
110            <properties>
111                <mvn.extension>.cmd</mvn.extension>
112            </properties>
113        </profile>
114        <!-- just mvn for other systems -->
115        <profile>
116            <id>nonWindowsExtension</id>
117            <activation>
118                <os><family>!Windows</family></os>
119            </activation>
120            <properties>
121                <mvn.extension></mvn.extension>
122            </properties>
123        </profile>
124    </profiles>
125
126    <build>
127        <pluginManagement>
128            <plugins>
129                <plugin>
130                    <groupId>org.apache.maven.plugins</groupId>
131                    <artifactId>maven-war-plugin</artifactId>
132                    <version>${version.maven-war-plugin}</version>
133                    <configuration>
134                        <failOnMissingWebXml>false</failOnMissingWebXml>
135                        <packagingExcludes>pom.xml</packagingExcludes>
136                    </configuration>
137                </plugin>
138                <!-- Liberty Maven plugin -->
139                <plugin>
140                    <groupId>net.wasdev.wlp.maven.plugins</groupId>
141                    <artifactId>liberty-maven-plugin</artifactId>
142                    <configuration>
143                        <assemblyArtifact>
144                            <groupId>io.openliberty</groupId>
145                            <artifactId>openliberty-runtime</artifactId>
146                            <version>RELEASE</version>
147                            <type>zip</type>
148                        </assemblyArtifact>
149                        <skip>true</skip>
150                        <!-- tag::packageFile[] -->
151                        <packageFile>
152                            ${project.build.directory}/${app.name}.tar.gz
153                        </packageFile>
154                        <!-- end::packageFile[] -->
155                    </configuration>
156                </plugin>
157                <!-- Plugin to run unit tests -->
158                <plugin>
159                    <groupId>org.apache.maven.plugins</groupId>
160                    <artifactId>maven-surefire-plugin</artifactId>
161                    <version>${version.maven-surefire-plugin}</version>
162                    <executions>
163                        <execution>
164                            <phase>test</phase>
165                            <id>default-test</id>
166                            <configuration>
167                                <excludes>
168                                    <exclude>**/it/**</exclude>
169                                </excludes>
170                                <reportsDirectory>
171                                    ${project.build.directory}/test-reports/unit
172                                </reportsDirectory>
173                            </configuration>
174                        </execution>
175                    </executions>
176                </plugin>
177                <!-- Plugin to run functional tests -->
178                <plugin>
179                    <groupId>org.apache.maven.plugins</groupId>
180                    <artifactId>maven-failsafe-plugin</artifactId>
181                    <version>${version.maven-failsafe-plugin}</version>
182                    <executions>
183                        <execution>
184                            <phase>integration-test</phase>
185                            <id>integration-test</id>
186                            <goals>
187                                <goal>integration-test</goal>
188                            </goals>
189                            <configuration>
190                                <includes>
191                                    <include>**/it/**</include>
192                                </includes>
193                                <systemPropertyVariables>
194                                    <system.ip>${system.ip}</system.ip>
195                                    <sys.http.port>
196                                        ${sys.service.http.port}
197                                    </sys.http.port>
198                                    <inv.http.port>
199                                        ${inv.service.http.port}
200                                    </inv.http.port>
201                                </systemPropertyVariables>
202                            </configuration>
203                        </execution>
204                        <execution>
205                            <id>verify-results</id>
206                            <goals>
207                                <goal>verify</goal>
208                            </goals>
209                        </execution>
210                    </executions>
211                    <configuration>
212                        <summaryFile>
213                        ${project.build.directory}/test-reports/it/failsafe-summary.xml
214                        </summaryFile>
215                        <reportsDirectory>
216                            ${project.build.directory}/test-reports/it
217                        </reportsDirectory>
218                    </configuration>
219                </plugin>
220            </plugins>
221        </pluginManagement>
222    </build>
223
224    <modules>
225        <module>system</module>
226        <module>inventory</module>
227    </modules>
228
229</project>

To learn more about RESTful web services and how to build them, see Creating a RESTful web service for details about how to build the system service. The inventory service is built in a similar way.

Building your Docker images

A Docker image is a binary file. It is made up of multiple layers and is used to run code in a Docker container. Images are built from instructions in Dockerfiles to create a containerized version of the application.

A Dockerfile is a collection of instructions for building a Docker image that can then be run as a container. As each instruction is run in a Dockerfile, a new Docker layer is created. These layers, which are known as intermediate images, are created when a change is made to your Docker image.

Every Dockerfile begins with a parent or base image over which various commands are run. For example, you can start your image from scratch and run commands that download and install a Java runtime, or you can start from an image that already contains a Java installation.

Learn more about Docker on the official Docker page.

Install Docker by following the instructions on the official page.

Creating your Dockerfiles

You will be creating two Docker images to run the inventory service and system service. The first step is to create Dockerfiles for both services.

Create the Dockerfile for the inventory service.
inventory/Dockerfile

inventory/Dockerfile

1# tag::from[]
2FROM open-liberty
3# end::from[]
4# tag::add[]
5ADD --chown=1001:0 \
6    target/inventory.tar.gz \
7    /opt/ol
8# end::add[]

The FROM instruction initializes a new build stage, which indicates the parent image of the built image. If you don’t need a parent image, then you can use FROM scratch, which makes your image a base image.

In this case, you’re using the open-liberty image as your parent image, which comes with the Open Liberty runtime by default. You can find all different official images at open-liberty Docker Hub. To pull a different open-liberty image, like kernel, define the FROM instruction as FROM open-liberty: kernel.

During the build, use a single ADD command instead of using multiple COPY commands to transfer configuration files and the application because the application is packaged into an archive. It eliminates multiple layers as the Docker image is created.

The ADD instruction is structured as ADD [--chown=<user>:<group>] <source> <destination>. It copies local files and directories into the specified destination within your Docker image. If the source is an archive, the ADD instruction unpacks it into the destination directory. In this case, the inventory application archive inventory.tar.gz, created from running mvn install previously, is extracted to the destination directory /opt/ol.

The ADD instruction needs to use the user ID 1001 and group 0 because the open-liberty image runs by default with the USER 1001 (non-root) user for security purposes. Otherwise, the files and directories that are copied over are owned by the root user.

The Dockerfile for the system service follows the same instructions as the inventory service, except that the system.tar.gz archive is copied over into /opt/ol.

Create the Dockerfile for the system service.
system/Dockerfile

system/Dockerfile

1FROM open-liberty
2# tag::add[]
3ADD --chown=1001:0 target/system.tar.gz /opt/ol
4# end::add[]

Building your Docker image

Now that your microservices are packaged and you have written your Dockerfiles, you will build your Docker images by using the docker build command. To build your image, you need to have Docker installed and your Docker daemon started.

Run the following commands to build container images for your application:

docker build -t system:1.0-SNAPSHOT system/.
docker build -t inventory:1.0-SNAPSHOT inventory/.

The -t flag in the docker build command allows the Docker image to be labeled (tagged) in the name[:tag] format. The tag for an image describes the specific image version. If the optional [:tag] tag is not specified, the latest tag is created by default.

To verify that the images are built, run the docker images command to list all local Docker images:

docker images

Your two images, inventory and system, should appear in the list of all Docker images:

REPOSITORY    TAG             IMAGE ID        CREATED          SIZE
inventory     1.0-SNAPSHOT    08fef024e986    4 minutes ago    471MB
system        1.0-SNAPSHOT    1dff6d0b4f31    5 minutes ago    470MB

Running your microservices in Docker containers

Now that you have your two images built, you will run your microservices in Docker containers:

docker run -d --name system -p 9080:9080 system:1.0-SNAPSHOT
docker run -d --name inventory -p 9081:9081 inventory:1.0-SNAPSHOT

The flags are described in the table below:

FlagDescription

-d

Runs the container in the background.

--name

Specifies a name for the container.

-p

Maps the host ports to the container ports. For example: -p <HOST_PORT>:<CONTAINER_PORT>

Next, run the docker ps command to verify that your containers are started:

docker ps

Make sure that your containers are running and show Up as their status:

CONTAINER ID    IMAGE                   COMMAND                  CREATED          STATUS          PORTS                                        NAMES
2b584282e0f5    inventory:1.0-SNAPSHOT  "/opt/ol/helpers/run…"   2 seconds ago    Up 1 second     9080/tcp, 9443/tcp, 0.0.0.0:9081->9081/tcp   inventory
99a98313705f    system:1.0-SNAPSHOT     "/opt/ol/helpers/run…"   3 seconds ago    Up 2 seconds    0.0.0.0:9080->9080/tcp, 9443/tcp             system

If a problem occurs and your containers exit prematurely, the containers don’t appear in the container list that the docker ps command displays. Instead, your containers appear with an Exited status when they run the docker ps -a command. Run the docker logs system and docker logs inventory commands to view the container logs for any potential problems. Run the docker stats system and docker stats inventory commands to display a live stream of usage statistics for your containers. You can also double-check that your Dockerfiles are correct. When you find the cause of the issues, remove the faulty containers with the docker rm system and docker rm inventory commands. Rebuild your images, and start the containers again.

To access the application, point your browser to the http://localhost:9081/inventory/systems URL. An empty list is expected because no system properties are stored in the inventory yet.

Next, retrieve the system container’s IP address by using the system container’s name that is defined when it ran the Docker containers. Run the following command to retrieve the system IP address:

docker inspect -f "{{.NetworkSettings.IPAddress }}" system

You find the system container’s IP address:

172.17.0.2

In this case, the IP address for the system service is 172.17.0.2. Take note of this IP address to add the system properties to the inventory service.

Point your browser to http://localhost:9081/inventory/systems/[system-ip-address] by replacing [system-ip-address] with the IP address you obtained earlier. You see a result in JSON format with the system properties of your local JVM. When you visit this URL, these system properties are automatically stored in the inventory. Go back to http://localhost:9081/inventory/systems and you see a new entry for [system-ip-address].

Testing the microservices

You can test your microservices manually by hitting the endpoints or with automated tests that check your running Docker containers.

Create the SystemEndpointTest class.
system/src/test/java/it/io/openliberty/guides/system/SystemEndpointTest.java

SystemEndpointTest.java

 1// tag::copyright[]
 2/*******************************************************************************
 3 * Copyright (c) 2018, 2019 IBM Corporation and others.
 4 * All rights reserved. This program and the accompanying materials
 5 * are made available under the terms of the Eclipse Public License v1.0
 6 * which accompanies this distribution, and is available at
 7 * http://www.eclipse.org/legal/epl-v10.html
 8 *
 9 * Contributors:
10 *     IBM Corporation - Initial implementation
11 *******************************************************************************/
12// end::copyright[]
13package it.io.openliberty.guides.system;
14
15import static org.junit.Assert.assertEquals;
16
17import javax.net.ssl.HostnameVerifier;
18import javax.net.ssl.SSLSession;
19import javax.ws.rs.client.Client;
20import javax.ws.rs.client.ClientBuilder;
21import javax.ws.rs.core.Response;
22
23import org.junit.After;
24import org.junit.Before;
25import org.junit.BeforeClass;
26import org.junit.Test;
27
28import javax.ws.rs.client.WebTarget;
29import org.apache.cxf.jaxrs.provider.jsrjsonp.JsrJsonpProvider;
30
31public class SystemEndpointTest {
32
33    private static String url;
34
35    private Client client;
36    private Response response;
37
38    @BeforeClass
39    public static void oneTimeSetup() {
40        String port = System.getProperty("sys.http.port");
41        url = "http://localhost:" + port + "/system/properties/";
42    }
43
44    @Before
45    public void setup() {
46        response = null;
47        client = ClientBuilder.newBuilder()
48                    .hostnameVerifier(new HostnameVerifier() {
49                        public boolean verify(String hostname, SSLSession session) {
50                            return true;
51                        }
52                    })
53                    .build();
54    }
55
56    @After
57    public void teardown() {
58        client.close();
59    }
60
61    @Test
62    // tag::testGetProperties[]
63    public void testGetProperties() {
64        Client client = ClientBuilder.newClient();
65        client.register(JsrJsonpProvider.class);
66
67        WebTarget target = client.target(url);
68        Response response = target.request().get();
69
70        assertEquals("Incorrect response code from " + url, 200, response.getStatus());
71        response.close();
72    }
73    // end::testGetProperties[]
74
75}

The testGetProperties() method checks for a 200 response code from the system service endpoint.

Create the InventoryEndpointTest class.
inventory/src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointTest.java

InventoryEndpointTest.java

  1// tag::copyright[]
  2/*******************************************************************************
  3 * Copyright (c) 2018, 2019 IBM Corporation and others.
  4 * All rights reserved. This program and the accompanying materials
  5 * are made available under the terms of the Eclipse Public License v1.0
  6 * which accompanies this distribution, and is available at
  7 * http://www.eclipse.org/legal/epl-v10.html
  8 *
  9 * Contributors:
 10 *     IBM Corporation - Initial implementation
 11 *******************************************************************************/
 12// end::copyright[]
 13package it.io.openliberty.guides.inventory;
 14
 15import static org.junit.Assert.assertEquals;
 16import static org.junit.Assert.assertTrue;
 17
 18import javax.net.ssl.HostnameVerifier;
 19import javax.net.ssl.SSLSession;
 20import javax.ws.rs.client.Client;
 21import javax.ws.rs.client.ClientBuilder;
 22import javax.ws.rs.core.Response;
 23import javax.json.JsonObject;
 24import javax.ws.rs.core.MediaType;
 25
 26import org.apache.cxf.jaxrs.provider.jsrjsonp.JsrJsonpProvider;
 27import org.junit.After;
 28import org.junit.Before;
 29import org.junit.BeforeClass;
 30import org.junit.Test;
 31
 32public class InventoryEndpointTest {
 33
 34    private static String invUrl;
 35    private static String sysUrl;
 36    private static String systemServiceIp;
 37
 38    private Client client;
 39    private Response response;
 40
 41    @BeforeClass
 42    public static void oneTimeSetup() {
 43        String invServPort = System.getProperty("inv.http.port");
 44        String sysServPort = System.getProperty("sys.http.port");
 45
 46        // tag::systemServiceIp[]
 47        systemServiceIp = System.getProperty("system.ip");
 48        // end::systemServiceIp[]
 49
 50        invUrl = "http://localhost" + ":" + invServPort + "/inventory/systems/";
 51        sysUrl = "http://localhost" + ":" + sysServPort + "/system/properties/";
 52    }
 53
 54    @Before
 55    public void setup() {
 56        response = null;
 57        client = ClientBuilder.newBuilder()
 58                    .hostnameVerifier(new HostnameVerifier() {
 59                        public boolean verify(String hostname, SSLSession session) {
 60                            return true;
 61                        }
 62                    })
 63                    .build();
 64
 65        client.register(JsrJsonpProvider.class);
 66        client.target(invUrl + "reset").request().post(null);
 67    }
 68
 69    @After
 70    public void teardown() {
 71        client.close();
 72    }
 73
 74    @Test
 75    public void testSuite() {
 76        this.testEmptyInventory();
 77        this.testHostRegistration();
 78        this.testSystemPropertiesMatch();
 79        this.testUnknownHost();
 80    }
 81
 82    // tag::testEmptyInventory[]
 83    public void testEmptyInventory() {
 84        Response response = this.getResponse(invUrl);
 85        this.assertResponse(invUrl, response);
 86
 87        JsonObject obj = response.readEntity(JsonObject.class);
 88
 89        int expected = 0;
 90        int actual = obj.getInt("total");
 91        assertEquals("The inventory should be empty on application start but it wasn't",
 92                    expected, actual);
 93
 94        response.close();
 95    }
 96    // end::testEmptyInventory[]
 97
 98    // tag::testHostRegistration[]
 99    public void testHostRegistration() {
100        this.visitSystemService();
101
102        Response response = this.getResponse(invUrl);
103        this.assertResponse(invUrl, response);
104
105        JsonObject obj = response.readEntity(JsonObject.class);
106
107        int expected = 1;
108        int actual = obj.getInt("total");
109        assertEquals("The inventory should have one entry for the system service:"
110                                             + systemServiceIp, expected, actual);
111
112        boolean serviceExists = obj.getJsonArray("systems").getJsonObject(0)
113                                    .get("hostname").toString()
114                                    .contains(systemServiceIp);
115        assertTrue("A host was registered, but it was not " + systemServiceIp,
116                serviceExists);
117
118        response.close();
119    }
120    // end::testHostRegistration[]
121
122    // tag::testSystemPropertiesMatch[]
123    public void testSystemPropertiesMatch() {
124        Response invResponse = this.getResponse(invUrl);
125        Response sysResponse = this.getResponse(sysUrl);
126
127        this.assertResponse(invUrl, invResponse);
128        this.assertResponse(sysUrl, sysResponse);
129
130        JsonObject jsonFromInventory = (JsonObject) invResponse
131                                                            .readEntity(JsonObject.class)
132                                                            .getJsonArray("systems")
133                                                            .getJsonObject(0)
134                                                            .get("properties");
135
136        JsonObject jsonFromSystem = sysResponse.readEntity(JsonObject.class);
137
138        String osNameFromInventory = jsonFromInventory.getString("os.name");
139        String osNameFromSystem = jsonFromSystem.getString("os.name");
140        this.assertProperty("os.name", systemServiceIp, osNameFromSystem,
141                            osNameFromInventory);
142
143        String userNameFromInventory = jsonFromInventory.getString("user.name");
144        String userNameFromSystem = jsonFromSystem.getString("user.name");
145        this.assertProperty("user.name", systemServiceIp, userNameFromSystem,
146                            userNameFromInventory);
147
148        invResponse.close();
149        sysResponse.close();
150    }
151    // end::testSystemPropertiesMatch[]
152
153    // tag::testUnknownHost[]
154    public void testUnknownHost() {
155        Response response = this.getResponse(invUrl);
156        this.assertResponse(invUrl, response);
157
158        Response badResponse = client.target(invUrl + "badhostname")
159            .request(MediaType.APPLICATION_JSON)
160            .get();
161
162        String obj = badResponse.readEntity(String.class);
163
164        boolean isError = obj.contains("ERROR");
165        assertTrue("badhostname is not a valid host but it didn't raise an error",
166                isError);
167
168        response.close();
169        badResponse.close();
170    }
171    // end::testUnknownHost[]
172
173    // Returns response information from the specified URL.
174    private Response getResponse(String url) {
175        return client.target(url).request().get();
176    }
177
178    // Asserts that the given URL has the correct response code of 200.
179    private void assertResponse(String url, Response response) {
180        assertEquals("Incorrect response code from " + url, 200,
181                    response.getStatus());
182    }
183
184    // Asserts that the specified JVM system property is equivalent in both the
185    // system and inventory services.
186    private void assertProperty(String propertyName, String hostname,
187        String expected, String actual) {
188        assertEquals("JVM system property [" + propertyName + "] "
189            + "in the system service does not match the one stored in "
190            + "the inventory service for " + hostname, expected, actual);
191    }
192
193    // Makes a simple GET request to inventory/localhost.
194    private void visitSystemService() {
195        Response response = this.getResponse(sysUrl);
196        this.assertResponse(sysUrl, response);
197        response.close();
198
199        Response targetResponse = client
200            .target(invUrl + systemServiceIp)
201            .request()
202            .get();
203
204        targetResponse.close();
205    }
206
207}
  • The testEmptyInventory() method checks that the inventory service has a total of 0 systems before anything is added to it.

  • The testHostRegistration() method checks that the system service was added to inventory properly.

  • The testSystemPropertiesMatch() checks that the system properties match what was added into the inventory service.

  • The testUnknownHost() method checks that an error is raised if an unknown host name is being added into the inventory service.

  • The systemServiceIp variable has the same value as what you retrieved in the previous section when manually adding the system service into the inventory service. This value of the IP address is passed in when you run the tests.

Running the tests

Run the Maven verify goal to test the services running in the Docker containers by replacing the [system-ip-address] with the IP address determined in the previous section.

mvn verify -Ddockerfile.skip=true -Dsystem.ip=[system-ip-address]

If the tests pass, you see a similar output as the following:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.system.SystemEndpointTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.653 s - in it.io.openliberty.guides.system.SystemEndpointTest

Results:

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.inventory.InventoryEndpointTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.935 s - in it.io.openliberty.guides.inventory.InventoryEndpointTest

Results:

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

When you are finished with the services, run the following commands to stop and remove your containers:

docker stop inventory system
docker rm inventory system

Great work! You’re done!

You have just built Docker images and run two microservices on Open Liberty in containers.

Guide Attribution

Containerizing microservices by Open Liberty is licensed under CC BY-ND 4.0

Copied to clipboard
Copy code block
Copy file contents

Prerequisites:

Nice work! Where to next?

What did you think of this guide?

Extreme Dislike Dislike Like Extreme Like

What could make this guide better?

Raise an issue to share feedback

Create a pull request to contribute to this guide

Need help?

Ask a question on Stack Overflow

Like Open Liberty? Star our repo on GitHub.

Star