Creating a RESTful web service

duration 30 minutes

Prerequisites:

Learn how to create a REST service with JAX-RS, JSON-B, and Open Liberty.

What you’ll learn

You will learn how to build and test a simple REST service with JAX-RS and JSON-B, which will expose the JVM’s system properties. The REST service will respond to GET requests made to the http://localhost:9080/LibertyProject/System/properties URL.

The service responds to a GET request with a JSON representation of the system properties, where each property is a field in a JSON object like this:

{
  "os.name":"Mac",
  "java.version": "1.8"
}

When you create a new REST application, the design of the API is important. The JAX-RS APIs could be used to create JSON-RPC, or XML-RPC APIs, but it wouldn’t be a RESTful service. A good RESTful service is designed around the resources that are exposed, and on how to create, read, update, and delete the resources.

The service responds to GET requests to the /System/properties path. The GET request should return a 200 OK response that contains all of the JVM’s system properties.

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-rest-intro.git
cd guide-rest-intro

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

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

Try what you’ll build

The finish directory in the root of this guide contains the finished application. Give it a try before you proceed.

To try out the application, first go to the finish directory and run the following Maven goal to build the application inside Open Liberty:

mvn install

Next, run the Maven liberty:start-server goal to start the application inside Open Liberty:

mvn liberty:start-server

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

mvn liberty:stop-server

Creating a JAX-RS application

Navigate to the start directory to begin.

JAX-RS has two key concepts for creating REST APIs. The most obvious one is the resource itself, which is modelled as a class. The second is a JAX-RS application, which groups all exposed resources under a common path. You can think of the JAX-RS application as a wrapper for all of your resources.

Create the SystemApplication class.
src/main/java/io/openliberty/guides/rest/SystemApplication.java

The SystemApplication class extends the Application class, which in turn associates all JAX-RS resource classes in the WAR file with this JAX-RS application, making them available under the common path specified in the SystemApplication class. The @ApplicationPath annotation has a value that indicates the path within the WAR that the JAX-RS application accepts requests from.

SystemApplication.java

 1// tag::comment[]
 2/*******************************************************************************
 3 * Copyright (c) 2017, 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 API and implementation
11 *******************************************************************************/
12// end::comment[]
13package io.openliberty.guides.rest;
14
15import javax.ws.rs.core.Application;
16import javax.ws.rs.ApplicationPath;
17
18// tag::applicationPath[]
19@ApplicationPath("System")
20// end::applicationPath[]
21// tag::systemApplication[]
22public class SystemApplication extends Application {
23
24}
25// end::systemApplication[]

Creating the JAX-RS resource

In JAX-RS, a single class should represent a single resource, or a group of resources of the same type. In this application, a resource might be a system property, or a set of system properties. It is easy to have a single class handle multiple different resources, but keeping a clean separation between types of resources helps with maintainability in the long run.

Create the PropertiesResource class.
src/main/java/io/openliberty/guides/rest/PropertiesResource.java

This resource class has quite a bit of code in it, so let’s break it down into manageable chunks.

The @Path annotation on the class indicates that this resource responds to the properties path in the JAX-RS application. The @ApplicationPath annotation in the SystemApplication class together with the @Path annotation in this class indicates that the resource is available at the System/properties path.

JAX-RS maps the HTTP methods on the URL to the methods on the class. The method to call is determined by the annotations specified on the methods. In the application you are building, an HTTP GET request to the System/properties path results in the system properties being returned.

The @GET annotation on the method indicates that this method is to be called for the HTTP GET method. The @Produces annotation indicates the format of the content that will be returned. The value of the @Produces annotation will be specified in the HTTP Content-Type response header. For this application, a JSON structure is to be returned. The desired Content-Type for a JSON response is application/json with MediaType.APPLICATION_JSON instead of the String content type. Using a constant such as MediaType.APPLICATION_JSON is better because in the event of a spelling error, a compile failure occurs.

JAX-RS supports a number of ways to marshal JSON. The JAX-RS 2.1 specification mandates JSON-Binding (JSON-B) and JAX-B.

The method body returns the result of System.getProperties() which is of type java.util.Properties. Since the method is annotated with @Produces(MediaType.APPLICATION_JSON), JAX-RS uses JSON-B to automatically convert the returned object to JSON data in the HTTP response.

PropertiesResource.java

 1// tag::comment[]
 2/*******************************************************************************
 3 * Copyright (c) 2017, 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 API and implementation
11 *******************************************************************************/
12 // end::comment[]
13package io.openliberty.guides.rest;
14
15import java.util.Properties;
16
17import javax.ws.rs.GET;
18import javax.ws.rs.Path;
19import javax.ws.rs.Produces;
20import javax.ws.rs.core.MediaType;
21
22// tag::path[]
23@Path("properties")
24// end::path[]
25public class PropertiesResource {
26
27    // tag::get[]
28    @GET
29    // end::get[]
30    // tag::produces[]
31    @Produces(MediaType.APPLICATION_JSON)
32    // end::produces[]
33    public Properties getProperties() {
34        return System.getProperties();
35    }
36
37}

SystemApplication.java

 1// tag::comment[]
 2/*******************************************************************************
 3 * Copyright (c) 2017, 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 API and implementation
11 *******************************************************************************/
12// end::comment[]
13package io.openliberty.guides.rest;
14
15import javax.ws.rs.core.Application;
16import javax.ws.rs.ApplicationPath;
17
18// tag::applicationPath[]
19@ApplicationPath("System")
20// end::applicationPath[]
21// tag::systemApplication[]
22public class SystemApplication extends Application {
23
24}
25// end::systemApplication[]

Configuring the server

To get the service running, the Liberty server needs to be correctly configured.

Create the server configuration file.
src/main/liberty/config/server.xml

server.xml

 1<server description="Intro REST Guide Liberty server">
 2
 3  <!-- tag::featureManager[] -->
 4  <featureManager>
 5      <feature>jaxrs-2.1</feature>
 6  </featureManager>
 7  <!-- end::featureManager[] -->
 8
 9  <!-- tag::httpEndpoint[] -->
10  <httpEndpoint httpPort="${default.http.port}" httpsPort="${default.https.port}"
11                id="defaultHttpEndpoint" host="*" />
12  <!-- end::httpEndpoint[] -->
13
14  <!-- tag::webApplication[] -->
15  <webApplication location="rest.war" contextRoot="${app.context.root}"/>
16  <!-- end::webApplication[] -->
17</server>

The configuration does the following actions:

  1. Configures the server to enable JAX-RS. This is specified in the featureManager element.

  2. Configures the server to resolve the HTTP port numbers from variables, which are then specified in the Maven pom.xml file. This is specified in the <httpEndpoint/> element. Variables use the syntax ${variableName}.

  3. Configures the server to run the produced Web application on a context root specified in the Maven pom.xml file. This is specified in the <webApplication/> element.

pom.xml

  1<?xml version='1.0' encoding='utf-8'?>
  2<project xmlns="http://maven.apache.org/POM/4.0.0"
  3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4         xsi:schemaLocation=
  5         "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6    <modelVersion>4.0.0</modelVersion>
  7    <parent>
  8        <groupId>net.wasdev.wlp.maven.parent</groupId>
  9        <artifactId>liberty-maven-app-parent</artifactId>
 10        <version>RELEASE</version>
 11    </parent>
 12    <groupId>io.openliberty.guides</groupId>
 13    <artifactId>rest</artifactId>
 14    <version>1.0-SNAPSHOT</version>
 15    <packaging>war</packaging>
 16
 17    <properties>
 18        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 19        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 20        <maven.compiler.source>1.8</maven.compiler.source>
 21        <maven.compiler.target>1.8</maven.compiler.target>
 22        <!-- tag::appname[] -->
 23        <app.name>LibertyProject</app.name>
 24        <!-- end::appname[] -->
 25        <!-- tag::httpport[] -->
 26        <testServerHttpPort>9080</testServerHttpPort>
 27        <!-- end::httpport[] -->
 28        <!-- tag::httpsport[] -->
 29        <testServerHttpsPort>9443</testServerHttpsPort>
 30        <!-- end::httpsport[] -->
 31        <warContext>${app.name}</warContext>
 32        <package.file>${project.build.directory}/${app.name}.zip</package.file>
 33        <packaging.type>usr</packaging.type>
 34    </properties>
 35
 36    <dependencyManagement>
 37        <dependencies>
 38            <dependency>
 39                <groupId>io.openliberty.features</groupId>
 40                <artifactId>features-bom</artifactId>
 41                <version>RELEASE</version>
 42                <type>pom</type>
 43                <scope>import</scope>
 44            </dependency>
 45        </dependencies>
 46    </dependencyManagement>
 47
 48    <dependencies>
 49        <!-- Open Liberty features -->
 50        <dependency>
 51            <groupId>io.openliberty.features</groupId>
 52            <artifactId>jaxrs-2.1</artifactId>
 53            <type>esa</type>
 54            <scope>provided</scope>
 55        </dependency>
 56        <!-- For tests -->
 57        <dependency>
 58            <groupId>junit</groupId>
 59            <artifactId>junit</artifactId>
 60            <version>4.12</version>
 61            <scope>test</scope>
 62        </dependency>
 63        <dependency>
 64            <groupId>org.apache.cxf</groupId>
 65            <artifactId>cxf-rt-rs-client</artifactId>
 66            <version>3.2.6</version>
 67            <scope>test</scope>
 68        </dependency>
 69        <dependency>
 70            <groupId>org.apache.cxf</groupId>
 71            <artifactId>cxf-rt-rs-extension-providers</artifactId>
 72            <version>3.2.6</version>
 73            <scope>test</scope>
 74        </dependency>
 75                <dependency>
 76                  <groupId>org.eclipse</groupId>
 77                  <artifactId>yasson</artifactId>
 78                  <version>1.0.4</version>
 79                  <scope>test</scope>
 80                </dependency>
 81        <!-- For JDK 11 Support -->
 82        <dependency>
 83            <groupId>javax.xml.bind</groupId>
 84            <artifactId>jaxb-api</artifactId>
 85            <version>2.3.1</version>
 86        </dependency>
 87    </dependencies>
 88
 89    <build>
 90        <plugins>
 91            <plugin>
 92                <groupId>org.apache.maven.plugins</groupId>
 93                <artifactId>maven-war-plugin</artifactId>
 94                <version>3.2.2</version>
 95                <configuration>
 96                    <failOnMissingWebXml>false</failOnMissingWebXml>
 97                    <packagingExcludes>pom.xml</packagingExcludes>
 98                </configuration>
 99            </plugin>
100            <!-- Plugin to run unit tests -->
101            <plugin>
102                <groupId>org.apache.maven.plugins</groupId>
103                <artifactId>maven-surefire-plugin</artifactId>
104                <version>3.0.0-M1</version>
105                <executions>
106                    <execution>
107                        <phase>test</phase>
108                        <id>default-test</id>
109                        <configuration>
110                            <excludes>
111                                <exclude>**/it/**</exclude>
112                            </excludes>
113                            <reportsDirectory>${project.build.directory}/test-reports/unit
114                                             </reportsDirectory>
115                        </configuration>
116                    </execution>
117                </executions>
118            </plugin>
119            <!-- Enable liberty-maven plugin -->
120            <plugin>
121                <groupId>net.wasdev.wlp.maven.plugins</groupId>
122                <artifactId>liberty-maven-plugin</artifactId>
123                <configuration>
124                    <assemblyArtifact>
125                         <groupId>io.openliberty</groupId>
126                         <artifactId>openliberty-runtime</artifactId>
127                         <version>RELEASE</version>
128                        <type>zip</type>
129                    </assemblyArtifact>
130                    <configFile>src/main/liberty/config/server.xml</configFile>
131                    <packageFile>${package.file}</packageFile>
132                    <include>${packaging.type}</include>
133                    <!-- tag::bootstrap[] -->
134                    <bootstrapProperties>
135                        <default.http.port>${testServerHttpPort}</default.http.port>
136                        <default.https.port>${testServerHttpsPort}</default.https.port>
137                        <app.context.root>${warContext}</app.context.root>
138                    </bootstrapProperties>
139                    <!-- end::bootstrap[] -->
140                </configuration>
141                <executions>
142                    <execution>
143                        <id>install-apps</id>
144                        <configuration>
145                            <looseApplication>true</looseApplication>
146                            <stripVersion>true</stripVersion>
147                            <installAppPackages>project</installAppPackages>
148                        </configuration>
149                    </execution>
150                    <execution>
151                        <id>package-app</id>
152                        <configuration>
153                            <outputDirectory>target/wlp-package</outputDirectory>
154                        </configuration>
155                    </execution>
156                </executions>
157            </plugin>
158            <!-- Plugin to run functional tests -->
159            <plugin>
160                <groupId>org.apache.maven.plugins</groupId>
161                <artifactId>maven-failsafe-plugin</artifactId>
162                <version>3.0.0-M1</version>
163                <executions>
164                    <execution>
165                        <phase>integration-test</phase>
166                        <id>integration-test</id>
167                        <goals>
168                            <goal>integration-test</goal>
169                        </goals>
170                        <configuration>
171                            <includes>
172                                <include>**/it/**/*.java</include>
173                            </includes>
174                            <!-- tag::testsysprops[] -->
175                            <systemPropertyVariables>
176                                <liberty.test.port>${testServerHttpPort}
177                                </liberty.test.port>
178                                <war.name>${warContext}</war.name>
179                            </systemPropertyVariables>
180                            <!-- end::testsysprops[] -->
181                        </configuration>
182                    </execution>
183                    <execution>
184                        <id>verify-results</id>
185                        <goals>
186                            <goal>verify</goal>
187                        </goals>
188                    </execution>
189                </executions>
190                <configuration>
191                    <summaryFile>
192                        ${project.build.directory}/test-reports/it/failsafe-summary.xml
193                    </summaryFile>
194                    <reportsDirectory>
195                        ${project.build.directory}/test-reports/it
196                    </reportsDirectory>
197                </configuration>
198            </plugin>
199        </plugins>
200    </build>
201</project>

The variables being used in the server.xml file are provided by the <bootstrapProperties/> section of the Maven pom.xml.

Building and running the application

To build the application, run the Maven install phase from the command line in the start directory:

mvn install

This command builds the application and creates a .war file in the target directory. It also configures and installs Open Liberty into the target/liberty/wlp directory.

Next, run the Maven liberty:start-server goal:

mvn liberty:start-server

This goal starts an Open Liberty server instance. Your Maven pom.xml is already configured to start the application in this server instance.

Check out the service you created at the http://localhost:9080/LibertyProject/System/properties URL.

When you are done checking out the services, stop the Open Liberty server by running the following command:

mvn liberty:stop-server

Testing the service

You could test this service manually by starting a server and pointing a web browser at the http://localhost:9080/LibertyProject/System/properties URL. Automated tests are a much better approach because they will trigger a failure if a change introduces a bug. JUnit and the JAX-RS Client API provide a very simple environment to test the application.

You can write tests for the individual units of code outside of a running application server, or they can be written to call the application server directly. In this example, you will create a test that does the latter.

Create the EndpointTest class.
src/test/java/it/io/openliberty/guides/rest/EndpointTest.java

EndpointTest.java

 1// tag::comment[]
 2/*******************************************************************************
 3 * Copyright (c) 2017, 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 API and implementation
11 *******************************************************************************/
12 // end::comment[]
13package it.io.openliberty.guides.rest;
14
15import static org.junit.Assert.assertEquals;
16
17import java.util.Properties;
18
19import javax.json.bind.Jsonb;
20import javax.json.bind.JsonbBuilder;
21import javax.ws.rs.client.Client;
22import javax.ws.rs.client.ClientBuilder;
23import javax.ws.rs.client.WebTarget;
24import javax.ws.rs.core.Response;
25
26import org.junit.Test;
27
28public class EndpointTest {
29
30    private static final Jsonb jsonb = JsonbBuilder.create();
31
32    // tag::test[]
33    @Test
34    // end::test[]
35    public void testGetProperties() {
36        // tag::systemProperties[]
37        String port = System.getProperty("liberty.test.port");
38        String war = System.getProperty("war.name");
39        // end::systemProperties[]
40        String url = "http://localhost:" + port + "/" + war + "/";
41
42        // tag::clientSetup[]
43        Client client = ClientBuilder.newClient();
44        // end::clientSetup[]
45
46        // tag::target[]
47        WebTarget target = client.target(url + "System/properties");
48        // end::target[]
49        // tag::requestget[]
50        Response response = target.request().get();
51        // end::requestget[]
52
53        // tag::assertequals[]
54        assertEquals("Incorrect response code from " + url,
55                     Response.Status.OK.getStatusCode(), response.getStatus());
56        // end::assertequals[]
57
58        // tag::body[]
59        String json = response.readEntity(String.class);
60        Properties sysProps = jsonb.fromJson(json, Properties.class);
61
62        // tag::assertosname[]
63        assertEquals("The system property for the local and remote JVM should match",
64                     System.getProperty("os.name"),
65                     sysProps.getProperty("os.name"));
66        // end::assertosname[]
67        // end::body[]
68        response.close();
69    }
70}

This test class has more lines of code than the resource implementation. This situation is common. The test method is indicated with the @Test annotation.

pom.xml

  1<?xml version='1.0' encoding='utf-8'?>
  2<project xmlns="http://maven.apache.org/POM/4.0.0"
  3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4         xsi:schemaLocation=
  5         "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6    <modelVersion>4.0.0</modelVersion>
  7    <parent>
  8        <groupId>net.wasdev.wlp.maven.parent</groupId>
  9        <artifactId>liberty-maven-app-parent</artifactId>
 10        <version>RELEASE</version>
 11    </parent>
 12    <groupId>io.openliberty.guides</groupId>
 13    <artifactId>rest</artifactId>
 14    <version>1.0-SNAPSHOT</version>
 15    <packaging>war</packaging>
 16
 17    <properties>
 18        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 19        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 20        <maven.compiler.source>1.8</maven.compiler.source>
 21        <maven.compiler.target>1.8</maven.compiler.target>
 22        <!-- tag::appname[] -->
 23        <app.name>LibertyProject</app.name>
 24        <!-- end::appname[] -->
 25        <!-- tag::httpport[] -->
 26        <testServerHttpPort>9080</testServerHttpPort>
 27        <!-- end::httpport[] -->
 28        <!-- tag::httpsport[] -->
 29        <testServerHttpsPort>9443</testServerHttpsPort>
 30        <!-- end::httpsport[] -->
 31        <warContext>${app.name}</warContext>
 32        <package.file>${project.build.directory}/${app.name}.zip</package.file>
 33        <packaging.type>usr</packaging.type>
 34    </properties>
 35
 36    <dependencyManagement>
 37        <dependencies>
 38            <dependency>
 39                <groupId>io.openliberty.features</groupId>
 40                <artifactId>features-bom</artifactId>
 41                <version>RELEASE</version>
 42                <type>pom</type>
 43                <scope>import</scope>
 44            </dependency>
 45        </dependencies>
 46    </dependencyManagement>
 47
 48    <dependencies>
 49        <!-- Open Liberty features -->
 50        <dependency>
 51            <groupId>io.openliberty.features</groupId>
 52            <artifactId>jaxrs-2.1</artifactId>
 53            <type>esa</type>
 54            <scope>provided</scope>
 55        </dependency>
 56        <!-- For tests -->
 57        <dependency>
 58            <groupId>junit</groupId>
 59            <artifactId>junit</artifactId>
 60            <version>4.12</version>
 61            <scope>test</scope>
 62        </dependency>
 63        <dependency>
 64            <groupId>org.apache.cxf</groupId>
 65            <artifactId>cxf-rt-rs-client</artifactId>
 66            <version>3.2.6</version>
 67            <scope>test</scope>
 68        </dependency>
 69        <dependency>
 70            <groupId>org.apache.cxf</groupId>
 71            <artifactId>cxf-rt-rs-extension-providers</artifactId>
 72            <version>3.2.6</version>
 73            <scope>test</scope>
 74        </dependency>
 75                <dependency>
 76                  <groupId>org.eclipse</groupId>
 77                  <artifactId>yasson</artifactId>
 78                  <version>1.0.4</version>
 79                  <scope>test</scope>
 80                </dependency>
 81        <!-- For JDK 11 Support -->
 82        <dependency>
 83            <groupId>javax.xml.bind</groupId>
 84            <artifactId>jaxb-api</artifactId>
 85            <version>2.3.1</version>
 86        </dependency>
 87    </dependencies>
 88
 89    <build>
 90        <plugins>
 91            <plugin>
 92                <groupId>org.apache.maven.plugins</groupId>
 93                <artifactId>maven-war-plugin</artifactId>
 94                <version>3.2.2</version>
 95                <configuration>
 96                    <failOnMissingWebXml>false</failOnMissingWebXml>
 97                    <packagingExcludes>pom.xml</packagingExcludes>
 98                </configuration>
 99            </plugin>
100            <!-- Plugin to run unit tests -->
101            <plugin>
102                <groupId>org.apache.maven.plugins</groupId>
103                <artifactId>maven-surefire-plugin</artifactId>
104                <version>3.0.0-M1</version>
105                <executions>
106                    <execution>
107                        <phase>test</phase>
108                        <id>default-test</id>
109                        <configuration>
110                            <excludes>
111                                <exclude>**/it/**</exclude>
112                            </excludes>
113                            <reportsDirectory>${project.build.directory}/test-reports/unit
114                                             </reportsDirectory>
115                        </configuration>
116                    </execution>
117                </executions>
118            </plugin>
119            <!-- Enable liberty-maven plugin -->
120            <plugin>
121                <groupId>net.wasdev.wlp.maven.plugins</groupId>
122                <artifactId>liberty-maven-plugin</artifactId>
123                <configuration>
124                    <assemblyArtifact>
125                         <groupId>io.openliberty</groupId>
126                         <artifactId>openliberty-runtime</artifactId>
127                         <version>RELEASE</version>
128                        <type>zip</type>
129                    </assemblyArtifact>
130                    <configFile>src/main/liberty/config/server.xml</configFile>
131                    <packageFile>${package.file}</packageFile>
132                    <include>${packaging.type}</include>
133                    <!-- tag::bootstrap[] -->
134                    <bootstrapProperties>
135                        <default.http.port>${testServerHttpPort}</default.http.port>
136                        <default.https.port>${testServerHttpsPort}</default.https.port>
137                        <app.context.root>${warContext}</app.context.root>
138                    </bootstrapProperties>
139                    <!-- end::bootstrap[] -->
140                </configuration>
141                <executions>
142                    <execution>
143                        <id>install-apps</id>
144                        <configuration>
145                            <looseApplication>true</looseApplication>
146                            <stripVersion>true</stripVersion>
147                            <installAppPackages>project</installAppPackages>
148                        </configuration>
149                    </execution>
150                    <execution>
151                        <id>package-app</id>
152                        <configuration>
153                            <outputDirectory>target/wlp-package</outputDirectory>
154                        </configuration>
155                    </execution>
156                </executions>
157            </plugin>
158            <!-- Plugin to run functional tests -->
159            <plugin>
160                <groupId>org.apache.maven.plugins</groupId>
161                <artifactId>maven-failsafe-plugin</artifactId>
162                <version>3.0.0-M1</version>
163                <executions>
164                    <execution>
165                        <phase>integration-test</phase>
166                        <id>integration-test</id>
167                        <goals>
168                            <goal>integration-test</goal>
169                        </goals>
170                        <configuration>
171                            <includes>
172                                <include>**/it/**/*.java</include>
173                            </includes>
174                            <!-- tag::testsysprops[] -->
175                            <systemPropertyVariables>
176                                <liberty.test.port>${testServerHttpPort}
177                                </liberty.test.port>
178                                <war.name>${warContext}</war.name>
179                            </systemPropertyVariables>
180                            <!-- end::testsysprops[] -->
181                        </configuration>
182                    </execution>
183                    <execution>
184                        <id>verify-results</id>
185                        <goals>
186                            <goal>verify</goal>
187                        </goals>
188                    </execution>
189                </executions>
190                <configuration>
191                    <summaryFile>
192                        ${project.build.directory}/test-reports/it/failsafe-summary.xml
193                    </summaryFile>
194                    <reportsDirectory>
195                        ${project.build.directory}/test-reports/it
196                    </reportsDirectory>
197                </configuration>
198            </plugin>
199        </plugins>
200    </build>
201</project>

The test code needs to know some information about the application in order to make requests. The server port and the application context root are key, and are dictated by the server configuration. While this information can be hardcoded, it is better to specify it in a single place like the Maven pom.xml file. Refer to the pom.xml file to see how the application information such as the <app.name/>, <testServerHttpPort/> and <testServerHttpsPort/> elements are provided in the file.

These Maven properties are then passed to the Java test program as the <systemPropertyVariables/> element in the pom.xml file.

Getting the values to create a representation of the URL is simple. The test class uses the getProperty method to get the application details.

To call the JAX-RS service using the JAX-RS client, first create a WebTarget object by calling the target method providing the URL. To cause the HTTP request to occur request().get() is invoked on the WebTarget. The get method call is a synchronous call that blocks until a response is received. This call returns a Response object, which can be inspected to determine whether the request was successful.

The first thing to check is that a 200 response was received. The JUnit assertEquals method can be used for this.

Check the response body to ensure it returned the right information. Since the client and the server are running on the same machine, it is reasonable to expect that the system properties for the local and remote JVM would be the same. In this case, an assertion assertEquals is made that the os.name system property for both JVMs is the same. You could write additional assertions to check for more values.

Running the tests

If the server is still running from the previous steps, stop it using the Maven liberty:stop-server goal from command line in the start directory:

mvn liberty:stop-server

To rebuild, run the tests, and see that the test passes, run the Maven install command:

mvn install

The Maven build takes a little longer than before the test existed, but expect to see the following information in the output:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.rest.EndpointTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.884 sec - in it.io.openliberty.guides.rest.EndpointTest

Results :

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

To see whether the tests detect a failure, add an assertion that you know fails, or change the existing assertion to a constant value that doesn’t match the os.name system property.

Great work! You’re done!

You developed a REST service in Open Liberty by using JAX-RS and JSON-P.

Guide Attribution

Creating a RESTful web service 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