Getting started with the Open Liberty application server

duration 25 minutes

Learn how to deploy and update an application on Open Liberty with Maven and Docker.

What you’ll learn

You will learn how to run and update a simple REST microservice on an Open Liberty server. You will use Maven throughout the guide to build and deploy the microservice as well as to interact with the running server instance.

Open Liberty is an application server designed for the cloud. It’s small, lightweight, and designed with modern cloud-native application development in mind. It supports the full MicroProfile and Java EE APIs and is composable, meaning that you can use only the features that you need, keeping the server lightweight, which is great for microservices. It also deploys to every major cloud platform, including Docker, Kubernetes, and Cloud Foundry.

Maven is an automation build tool that provides an efficient way to develop Java applications. Using Maven, you will build a simple microservice, called system, that collects basic system properties from your laptop and displays them on an endpoint that you can access in your web browser. You will then make server configuration and code changes and see how they are picked up by a running server. You’ll also explore how to package your application with the server runtime so that it can be deployed anywhere in one go.

Finally, you will package the application along with the server configuration into a Docker image and run that image as a container.

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-getting-started.git
cd guide-getting-started

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

The finish directory contains the finished project, which is what you will build.

Building and running the application

Your application is configured to be built with Maven. Every Maven-configured project contains a pom.xml file, which defines the project configuration, dependencies, plug-ins, and so on.

Navigate to the start directory where your pom.xml file is located. Your pom.xml file is configured to include the liberty-maven-plugin Liberty Maven plug-in, which allows you to install applications into Open Liberty as well as manage the server instances.

To begin, build the system microservice that is provided and deploy it to Open Liberty by running the Maven install phase and the Maven liberty:run-server goal from the start directory:

mvn install liberty:run-server

The mvn command initates a Maven build, during which the target directory is created to store all build-related files.

The install argument specifies the Maven install phase. During this phase, the application is built and packaged into a .war file, an Open Liberty server runtime is downloaded and installed into the target/liberty/wlp directory, a server instance is created and configured in the target/liberty/wlp/usr/servers/GettingStartedServer directory, and the application is installed into that server via loose config.

The liberty:run-server argument specifies the Open Liberty run-server goal, which starts an Open Liberty server instance in the foreground.

For more information on the Liberty Maven plug-in, see its GitHub repository.

When the server begins starting up, various messages display in your active shell. Wait for the following message, which indicates that the server startup is complete:

[INFO] [AUDIT] CWWKF0011I: The server GettingStartedServer is ready to run a smarter planet.

To access the system microservice, visit the http://localhost:9080/system/properties URL, and you’ll see a list of the various system properties of your JVM:

{
    "os.name": "Mac OS X",
    "java.version": "1.8.0_151",
    ...
}

Later, when you need to stop the server, simply press CTRL+C in the shell session where you ran the server, or run the liberty:stop-server goal from the start directory in another shell session:

mvn liberty:stop-server

Updating the server configuration without restarting the server

When you update the server configuration files, you can run the mvn package command to invoke the Maven package phase that executes various Maven goals that repackage the server.

Try updating the server configuration while the server is running. If you stopped the server, start it again before you proceed. The system microservice does not currently include health monitoring to report whether the server and the microservice that it runs are healthy. You can add health reports with the MicroProfile Health feature, which adds a /health endpoint to your application. If you try to access this endpoint now at the http://localhost:9080/health/ URL, you see a 404 error because the /health endpoint does not yet exist:

Error 404: java.io.FileNotFoundException: SRVE0190E: File not found: /health

To add the MicroProfile Health feature to the server, add the mpHealth-1.0 feature to the src/main/liberty/config/server.xml server configuration file that is located in the start directory:

<featureManager>
  <feature>jaxrs-2.0</feature>
  <feature>jsonp-1.0</feature>
  <feature>cdi-1.2</feature>
  <feature>mpMetrics-1.0</feature>
  <feature>mpHealth-1.0</feature>
</featureManager>

Next, open a new shell session, navigate to the start directory, and repackage the server:

mvn package

When enabled, the mpHealth-1.0 feature automatically adds a /health endpoint to the application. You can see the server being updated in the server log that’s displayed in your first shell session:

[INFO] [AUDIT] CWWKG0016I: Starting server configuration update.
[INFO] [AUDIT] CWWKT0017I: Web application removed (default_host): http://foo:9080/
[INFO] [AUDIT] CWWKZ0009I: The application io.openliberty.guides.getting-started has stopped successfully.
[INFO] [AUDIT] CWWKG0017I: The server configuration was successfully updated in 0.284 seconds.
[INFO] [AUDIT] CWWKT0016I: Web application available (default_host): http://foo:9080/health/
[INFO] [AUDIT] CWWKF0012I: The server installed the following features: [mpHealth-1.0].
[INFO] [AUDIT] CWWKF0008I: Feature update completed in 0.285 seconds.
[INFO] [AUDIT] CWWKT0016I: Web application available (default_host): http://foo:9080/
[INFO] [AUDIT] CWWKZ0003I: The application io.openliberty.guides.getting-started updated in 0.173 seconds.

Try to access the /health endpoint again by visiting the http://localhost:9080/health URL. This time you’ll see the following JSON:

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

You now have a means of verifying if your server is up and running.

Updating the source code without restarting the server

The JAX-RS application that contains your system microservice is configured as a loose application, meaning that it runs in a server from its .class file and other artifacts. Open Liberty automatically monitors these artifacts, and whenever they are updated, it updates the running server without the need for the server to be restarted.

Take a look at your pom.xml file. The loose application support is enabled with the <looseApplication> element in the liberty-maven-plugin plug-in:

                    <looseApplication>true</looseApplication>

Try updating the source code while the server is running. At the moment, the /health endpoint reports whether or not the server is running, but the endpoint doesn’t provide any details on the microservices that are running inside of the server. To report on the health status of the system microservice, create a src/main/java/io/openliberty/sample/system/SystemHealth.java file:

package io.openliberty.sample.system;

import javax.enterprise.context.ApplicationScoped;

import org.eclipse.microprofile.health.Health;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.HealthCheckResponseBuilder;

@Health
@ApplicationScoped
public class SystemHealth implements HealthCheck {

    @Override
    public HealthCheckResponse call() {
        HealthCheckResponseBuilder builder = HealthCheckResponse.named(
                SystemResource.class.getSimpleName());
        if (!System.getProperty("wlp.server.name").equals("GettingStartedServer")) {
            return builder.withData("services", "not available").down().build();
        }
        return builder.withData("services", "available").up().build();
    }

}

Next, recompile the application:

mvn compile

The following messages display in your first shell session:

[INFO] [AUDIT] CWWKT0017I: Web application removed (default_host): http://foo:9080/
[INFO] [AUDIT] CWWKZ0009I: The application io.openliberty.guides.getting-started has stopped successfully.
[INFO] [AUDIT] CWWKT0016I: Web application available (default_host): http://foo:9080/
[INFO] [AUDIT] CWWKZ0003I: The application io.openliberty.guides.getting-started updated in 0.136 seconds.

Access the /health endpoint again by visiting the http://localhost:9080/health URL. This time you see the overall status of your server as well as the system microservice that the server runs:

{
    "checks":[
        {
            "data":
            {
                "services": "available"
            },
            "name": "SystemResource",
            "state": "UP"
        }
    ],
    "outcome": "UP"
}

Making code changes and recompiling is fast and straightforward. Maven only rebuilds the .class files and artifacts that changed, and the server picks these up automatically without needing to be restarted.

Checking the Open Liberty server logs

While the server is running in the foreground, it displays various console messages in the shell. These messages are also logged to the target/liberty/wlp/usr/servers/GettingStartedServer/logs/console.log file. You can find the complete server logs in the target/liberty/wlp/usr/servers/GettingStartedServer/logs directory. The console.log and messages.log files are the primary log files that contain console output of the running application and the server. More logs are created when run time errors occur or whenever tracing is enabled. You can find the error logs in the ffdc directory and the tracing logs in the trace.log file.

In addition to the log files that are generated automatically, you can enable logging of specific Java packages or classes by using the logging element:

<logging traceSpecification="<component_1>=<level>:<component_2>=<level>:..."/>

The component element is a Java package or class, and the level element is one of the following logging levels: off, fatal, severe, warning, audit, info, config, detail, fine, finer, finest, all.

Try enabling detailed logging of the MicroProfile Health feature by adding the logging element to your src/main/liberty/config/server.xml configuration file:

<server description="Sample Liberty server">
  <featureManager>
    <feature>jaxrs-2.0</feature>
    <feature>jsonp-1.0</feature>
    <feature>cdi-1.2</feature>
    <feature>mpMetrics-1.0</feature>
    <feature>mpHealth-1.0</feature>
  </featureManager>

  <applicationManager autoExpand="true" />
  <quickStartSecurity userName="admin" userPassword="adminpwd"/>
  <keyStore id="defaultKeyStore" password="mpKeystore"/>

  <logging traceSpecification="com.ibm.ws.microprofile.health.*=all"/>

  <httpEndpoint host="*" httpPort="${default.http.port}" httpsPort="${default.https.port}" id="defaultHttpEndpoint"/>

  <webApplication location="getting-started.war" contextRoot="/"/>
</server>

Next, repackage the server:

mvn package

Now, when you visit the /health endpoint, additional traces are logged into the trace.log file.

Starting and stopping the Open Liberty server in the background

Although you can start and stop the server in the foreground by using the Maven liberty:run-server goal, you can also start and stop the server in the background with the Maven liberty:start-server and liberty:stop-server goals:

mvn liberty:start-server
mvn liberty:stop-server

Running the application from a minimal runnable JAR

So far, Open Liberty has been running out of the target/liberty/wlp directory, which effectively contains an Open Liberty server installation and the deployed application. The final product of the Maven build is a server package for use in a continuous integration pipeline and, ultimately, a production deployment.

Open Liberty supports a number of different server packages. The sample application currently generates a usr package that contains the servers and application to be extracted onto an Open Liberty installation. The type of server package is configured in your pom.xml file in the following two lines:

<packaging.type>usr</packaging.type>
<include>${packaging.type}</include>

Instead of creating a server package, you can generate a runnable JAR file that contains the application along with a server runtime. This JAR can then be run anywhere and deploy your application and server at the same time. To generate a runnable JAR, invoke the runnable-package profile by using the -P flag:

mvn install -P runnable-package

The -P flag specifies the Maven profile to be run during the build. In this case, the runnable-package profile is invoked, which temporarily overrides the packaging.type property from the usr package to the runnable package. This property then propagates to the liberty-maven-plugin plug-in, which generates the server package that you want:

<profile>
    <id>runnable-package</id>
    <properties>
        <packaging.type>runnable</packaging.type>
    </properties>
</profile>

When the build completes, you can find the runnable getting-started.jar file in the target directory. By default, this JAR file comes with all the features available in Open Liberty, including the entirety of Java EE and MicroProfile. As a result, this JAR is over 100 MB. To omit the features that you don’t need and package the JAR with only the features that you defined in the server.xml file, use minifiy,runnable as the packaging type. To build a minimal runnable JAR, invoke the minify-runnable-package profile by using the -P flag:

mvn install -P minify-runnable-package

The minify-runnable-package profile overrides the package.type property from the usr package to the minify,runnable package and generates a runnable JAR file that contains only the features that you explicitly enabled in your server.xml file. As a result, the generated JAR is only about 37 MB.

To run the JAR, first stop the server if it’s running. Then, navigate to the target directory and run the java -jar command:

java -jar getting-started.jar

When the server starts, visit the http://localhost:9080/system/properties URL to access your application that is now running out of the minimal runnable JAR.

At this point, you can stop the server by pressing CTRL+C in the shell session that the server runs in.

Running the application in a Docker container

To run the application in a container, you need to have Docker installed. For installation instructions, see https://docs.docker.com/install/.

To containerize the application, you need a Dockerfile. This file contains a collection of instructions that define how a Docker image is built, what files are packaged into it, what commands run when the image runs as a container, and so on. You can find a complete Dockerfile in the start directory. This Dockerfile packages the usr server package into a Docker image that contains a preconfigured Open Liberty server.

The docker-image profile uses the dockerfile-maven plug-in, which automatically builds a Docker image from a Dockerfile that is located in the same directory as the pom.xml file:

<profile>
    <id>docker-image</id>
    <build>
        <plugins>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>${version.dockerfile-maven-plugin}</version>
                <executions>
                    <execution>
                        <id>build-docker-image</id>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <repository>openliberty-${project.artifactId}</repository>
                    <tag>${project.version}</tag>
                </configuration>
            </plugin>
        </plugins>
    </build>
</profile>

To build and containerize the application, start your Docker daemon and then invoke the profile by using the -P flag:

mvn clean package -P docker-image

During the Maven package phase, a usr server package is generated into the target directory. The Docker openliberty-getting-started:1.0-SNAPSHOT image is also built from the Dockerfile. To verify that the image is built, run the docker images command to list all local Docker images:

docker images

Your image should appear in the list of all Docker images:

REPOSITORY                     TAG             IMAGE ID        CREATED         SIZE
openliberty-getting-started    1.0-SNAPSHOT    85085141269b    21 hours ago    487MB

Next, run the image as a container:

docker run -d --name gettingstarted-app -p 9080:9080 openliberty-getting-started:1.0-SNAPSHOT

There is a bit going on here, so let’s break down the command:

FlagDescription

-d

Runs the container in the background.

--name

Specifies a name for the container.

-p

Maps the container ports to the host ports.

The final argument in the docker run command is the Docker image name.

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

docker ps

Make sure that your container is running and does not have Exited as its status:

CONTAINER ID    IMAGE                         CREATED          STATUS           NAMES
4294a6bdf41b    openliberty-getting-started   9 seconds ago    Up 11 seconds    gettingstarted-app

To access the application, visit the http://localhost:9080/system/properties URL.

To stop and remove the container, run the following commands:

docker stop gettingstarted-app && docker rm gettingstarted-app

To remove the image, run the following command:

docker rmi openliberty-getting-started:1.0-SNAPSHOT

Great work! You’re done!

You’ve learned the basics of deploying and updating an application on an Open Liberty server.

Contribute to this guide

Is something missing or broken? Raise an issue, or send us a pull request.