1. What is Open Liberty?

OpenLiberty is a lightweight open framework for building fast and efficient cloud-native Java microservices. It supports some of the most popular Java standards today, including:

  • Java EE 7 and 8

  • Microprofile 1.X, 2.X, and 3.X

  • Spring Boot 1.5 and 2.0

2. TL;DR info

  • Get OpenLiberty using Maven/Gradle/Docker here: https://openliberty.io/downloads/

  • Create server: <liberty-root>/bin/server create myServer

  • Start server: <liberty-root>/bin/server start myServer

  • Main config file: <liberty-root>/usr/servers/myServer/server.xml

  • Default app folder: <liberty-root>/usr/servers/myServer/dropins/

  • Default ports: http=9080, https=9443

  • Enable only the features you need for smaller disk/memory footprint and faster start time

  • Develop apps using "dev mode" using the Liberty Maven Plugin mvn liberty:dev goal

  • Lots of useful guides here: https://openliberty.io/guides/

3. Getting Started

Generate a basic Liberty project using the MicroProfile Starter website:

  1. Select "MicroProfile 3.0" for MicroProfile version

  2. Select "OpenLiberty" for MicroProfile Runtime

  3. Select any example specifications you want to be included

  4. Download and extract the project, then import into your preferred IDE

This creates a Maven project with a simple JAX-RS resource class in it:

public class HelloController {

    public String sayHello() {
        return "Hello World";

You can start the application in "dev mode" using the command:

mvn liberty:dev

Then open a web browser to http://localhost:8181/data/hello to access the JAX-RS endpoint. You will see the text Hello World.

If you make code changes the application will automatically be updated.

If you add tests to the project, you can run them from dev mode by pressing the Enter key. To exit dev mode press Ctrl+C.

A more detailed Getting Started walkthrough can be found in the OpenLiberty Maven guide.

4. Configuration

The primary source of configuration for a Liberty server is the server.xml file. In most projects it is located at src/main/liberty/config/server.xml and might look like this:


    <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443"/>

    <webApplication location="test.war" name="test"/>

4.1. Dynamic Configuration

All configuration in server.xml is dynamic by default, meaning that if you modify it while the server is running, the server will automatically update to account for the change — typically in a few milliseconds.

4.2. Variable Substitution

Server configuration can be parameterized using variables. When resolving variable names the following sources are consulted in decreasing order of precedence:

  1. The value in the <variable value="…​"/> attribute

  2. Java system properties (i.e. jvm.options)

  3. bootstrap.properties

  4. environment variables

  5. The value in the <variable defaultValue="…​"/> attribute

Variables are referenced using ${variableName} syntax. In server config, specify variables using the variable element:

<variable name="variableName" value="some.value" />

Default values, specified in server config, are only used if no other value can be found. They are specified using the variable element and the defaultValue attribute:

<variable name="DB_SERVER" defaultValue="localhost"/>

4.3. Predefined Variables

  • ${wlp.install.dir} - the location where the Liberty runtime is installed.

  • ${wlp.server.name} - the name of the server.

  • ${wlp.user.dir} - the location of the usr folder. Defaults to ${wlp.install.dir}/usr.

  • ${shared.app.dir} - the location of shared applications. Defaults to ${wlp.user.dir}/shared/apps.

  • ${shared.config.dir} - the directory that contains the server config. Defaults to ${wlp.user.dir}/shared/config.

  • ${shared.resource.dir} - the location of shared resource files. Defaults to ${wlp.user.dir}/shared/resources.

  • ${server.config.dir} - the directory that server config is stored in. Defaults to ${wlp.user.dir}/servers/${wlp.server.name}.

  • ${server.output.dir} - the directory that the server writes the workarea, logs and other runtime generated files to. Defaults to ${server.config.dir}.

4.4. MicroProfile Config

MicroProfile Configuration is a simple yet powerful way to externalize configuration in any application.

In OpenLiberty, there are 5 builtin configuration sources:

  1. A <variable name="…​" value="…​"/> element in server.xml (ordinal = 500)

  2. System Properties, jvm.options, or bootstrap.properties (ordinal = 400)

  3. Environment variables or server.env (ordinal = 300)

  4. Inside application at /META-INF/microprofile-config.properties (ordinal = 100)

  5. Annotation @ConfigProperty with defaultValue (no ordinal)

To inject a config property into your application (regardless of the configuration source) you can use the following code:

public class MyService {

    @ConfigProperty(name = "foo", defaultValue = "bar")
    String fooProperty;

For more info, see this OpenLiberty guide: Separating configuration from code in microservices

4.5. Configuration Secrets

If you are running your application in Kubernetes, you don’t want to have credentials exposed as simple environment variables, and you certainly don’t want them checked in with the rest of your application source code!

First, configure a Kubernetes secret, for example database-credentials with the contents:


Then, you can inject the Kubernetes secret contents into a a boostrap.properties file that contains sensitive information as follows:

kind: Deployment
apiVersion: apps/v1beta1
  name: my-app
# ...
      - name: my-app
        image: ...
        - name: database-credentials-volume
          mountPath: /opt/wlp/usr/servers/defaultServer/bootstrap.properties
          subPath: bootstrap.properties
          readOnly: true
      - name: database-credentials-volume
          secretName: database-credentials

Finally, the secrets can then be referenced in server configuration using variables:

<dataSource ...>
    <properties ...

5. Features

The features enabled for a Liberty server are listed in the <featureManager> element. A Liberty feature may include other Liberty features. For example, the jsp-2.3 feature pulls in the servlet-4.0 feature, and the webProfile-8.0 feature pulls in all of the features for Java EE 8 Web Profile.

Only enable the features that you need! While it may be convenient to enable "convenience" features like javaee-8.0 initially, over time you should only enable features that your application actually needs. Less features = faster startup and lower disk/memory footprint

Some of the most common Liberty features are:

5.1. Java EE 8

  • webProfile-8.0: Enables all features in Java EE 8 Web profile: Bean Validation 2.0, CDI 2.0, EJB Lite 3.2, EL 3.0, JAX-RS 2.1, JNDI 1.0, JPA 2.2, JSF 2.3, JSON-B 1.0, JSON-P 1.1, JSP 2.3, Servlet 4.0, WebSocket 1.1

  • javaee-8.0: Enables all features in Java EE 8 Full Profile: webProfile-8.0 plus Java Batch 1.0, EE Concurrency 1.0, EJB 3.2, JavaMail 1.6, JAX-WS 2.2, JCA 1.7, JMS 2.0

  • jaxrs-2.1: Java XML RESTful Web Services (JAX-RS) 2.1

  • cdi-2.0: Context Dependency Injection (CDI) 2.0

  • jpa-2.2: Java Persistence Architecture (JPA) 2.2

  • jsf-2.3: Java Server Faces (JSF) 2.3

  • jsonb-1.0: JSON Binding (JSON-B) 1.0

  • servlet-4.0: Servlet 4.0

5.2. Java EE 7

  • webProfile-7.0: Enables all features in Java EE 7 Web Profile

  • javaee-7.0: Enables all features in Java EE 7 Full Profile

You cannot mix Java EE 7 and 8 features in the same server.xml!

5.3. MicroProfile 3.2

  • microProfile-3.2: Enables all features in MicroProfile 3.2 platform

  • cdi-2.0

  • jaxrs-2.1

  • jsonb-1.0

  • mpConfig-1.4: MicroProfile Config 1.4

  • mpHealth-2.1: MicroProfile Health 2.1

  • mpMetrics-2.2: MicroProfile Metrics 2.2

  • mpRestClient-1.3: MicroProfile REST Client 1.3

A complete list of all Liberty features can be found here: OpenLiberty Server Features

6. Maven

Add the maven plugin to your pom.xml file:


Some of the essential maven commands are:

  • mvn liberty:dev: Starts your Liberty server in "dev mode" which runs the application and automatically updates it whenever you save changes to the source code or configuration

  • mvn liberty:run: Starts your Liberty server in the foreground. Stop it with Ctrl+C

  • mvn liberty:start: Starts your Liberty server in the background

  • mvn liberty:stop: Stops your Liberty server that was started using liberty:start

Create an application using an OpenLiberty Maven archetype:

  • Servlet/JSP web application: mvn archetype:generate -DarchetypeGroupId=io.openliberty.tools -DarchetypeArtifactId=liberty-archetype-webapp -DarchetypeVersion=3.2.2 -DgroupId=com.example -DartifactId=myapp -Dversion=1.0-SNAPSHOT -B

Also see:

7. Gradle

Add the following snippet to your build.gradle file:

buildscript {
    repositories {
    dependencies {
        classpath 'net.wasdev.wlp.gradle.plugins:liberty-gradle-plugin:2.7'

apply plugin: 'war'
apply plugin: 'liberty'

dependencies {
    libertyRuntime group:'io.openliberty', name:'openliberty-runtime', version:''

Some of the essential gradle tasks are:

  • ./gradlew libertyRun: Starts your Liberty server in the foreground. Stop it with Ctrl+C

  • ./gradlew libertyStart: Starts your Liberty server in the background

  • ./gradlew libertyStop: Stops your Liberty server that was started using liberty:start

Also see:

8. Docker

The basic Liberty Dockerfile looks like this:

FROM openliberty/open-liberty:full-java8-openj9-ubi
COPY src/main/liberty/config /config/
ADD target/myApp.war /config/dropins

# Running configure.sh takes ~20s at docker build time but will greatly reduce
# container start time. You may not want to run this for local development if
# you are constantly changing the app layer, but should used for production
RUN configure.sh

There are also base layers using Java 11 and 13 which can be found here: OpenLiberty Docker Hub

For complete documentation on OpenLiberty Docker containers, see: OpenLiberty/ci.docker Github

9. Supported Java versions

OpenLiberty is currently supported on Java SE 8, 11, and 13. Official documentation can be found here: JavaSE support

10. Databases

This is the most common base configuration for using a JDBC DataSource (or JPA) with Liberty:


<library id="driver-library">
    <fileset dir="/path/to/driver/dir" includes="*.jar"/>

10.1. Validating Connections

OpenLiberty has a REST API to test database connections. To use it, add this config:


<!-- Any security mechanism can be used, <quickStartSecurity> is the simplest -->
<quickStartSecurity userName="admin" userPassword="admin"/>

<dataSource id="DefaultDataSource">
    <!-- the rest of your datasource config... -->

For a complete walkthrough, see this blog post: Testing database connections with REST

10.2. PostgreSQL

JDBC driver available at: PostgreSQL

<dataSource id="DefaultDataSource" jndiName="jdbc/myDB">
    <jdbcDriver libraryRef="driver-library"/>
    <properties.postgresql serverName="localhost" portNumber="5432"


To run a Postgres Docker container locally:

docker run -it --rm=true --memory-swappiness=0 --ulimit memlock=-1:-1 \
           --name postgres-liberty \
           -e POSTGRES_USER=exampleUser \
           -e POSTGRES_PASSWORD=examplePassword \
           -e POSTGRES_DB=myDB \
           -p 5432:5432 postgres:10.5

10.3. IBM DB2

JDBC driver available at: DB2

<dataSource id="DefaultDataSource" jndiName="jdbc/myDB">
    <jdbcDriver libraryRef="driver-library"/>
    <properties.db2.jcc serverName="localhost" portNumber="50000"


To run a DB2 Docker container locally:

docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 \
           --name db2-liberty \
           -e AUTOCONFIG=false -e ARCHIVE_LOGS=false -e LICENSE=accept \
           -e DBNAME=myDB \
           -e DB2INSTANCE=exampleUser \
           -e DB2INST1_PASSWORD=examplePassword \
           -p 50000:50000 \
           --privileged \

10.4. Microsoft SQL Server

JDBC driver available at: SQLServer

<dataSource id="DefaultDataSource" jndiName="jdbc/myDB">
    <jdbcDriver libraryRef="driver-library"/>
    <properties.microsoft.sqlserver serverName="localhost" portNumber="1433"


To run a SQL Server Docker container locally:

docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 \
           --name mssql-liberty \
           -e ACCEPT_EULA=Y \
           -e SA_PASSWORD=examplePass0ord \
           -p 1433:1433 \

10.5. MySQL

JDBC driver available at: MySQL

<dataSource id="DefaultDataSource" jndiName="jdbc/myDB">
    <jdbcDriver libraryRef="driver-library"/>
    <properties serverName="localhost" portNumber="3306"

To run a MySQL Docker container locally:

docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 \
           --name mysql-liberty \
           -e MYSQL_DATABASE=myDB \
           -e MYSQL_USER=exampleUser \
           -e MYSQL_PASSWORD=examplePassword \
           -p 3306:3306 \

10.6. Oracle

JDBC driver available at: Oracle

<dataSource id="DefaultDataSource" jndiName="jdbc/myDB">
    <jdbcDriver libraryRef="driver-library"/>
    <properties.oracle URL="jdbc:oracle:thin:@//localhost:1521/myDB"/>

10.7. Derby (in-memory DB)

<dataSource id="DefaultDataSource" jndiName="jdbc/myDB">
    <jdbcDriver libraryRef="driver-library"/>
    <properties.derby.embedded databaseName="memory:myDB" createDatabase="create"/>

11. Messaging

Applications can pass messages among themselves with the Java Message Service (JMS) APIs. These APIs allow applications to produce messages that are placed on a destination and/or consuming messages from a destination. Liberty can act as a server of JMS destinations or it can connect to another server to access those destinations. JMS defines two core types of destinations: queues, and topics.

Some terms commonly used in JMS:

  • Message: Information that is being sent via JMS. Payload can be any kind of data, from plain text and numbers to serialized Java objects.

  • Destination: A specific place for messages to be stored and retrieved by name. Common types are queues and topics.

  • Queue: A destination where each message is delivered to the first consumer to receive a message.

  • Topic: A destination where each message is delivered to all consumers subscribed to it.

  • Producer: Any code that produces a message onto a JMS destination.

  • Consumer: Any code that subscribes to a destination and receives messages from it.

11.1. JMS Server

Liberty can act as a JMS server whether or not it is serving any applications using the wasJmsServer-1.0 feature.


    <queue id="myQueue" />
    <topicSpace id="myTopicSpace" />

The messagingEngine element defines all JMS destinations served by Liberty. Note that topics are organized into topic spaces here—​the individual topics are created and subscribed to by the applications or by defining administered objects representing them in the JMS client.

If you want applications on other servers to connect to your JMS server, create a <wasJmsEndpoint>. Without this, only applications served by the same Liberty server can acccess the JMS destinations.

<wasJmsEndpoint host="*"  wasJmsPort="7276" wasJmsSSLPort="7286" />

11.2. JMS Client

Liberty allows applications to connect to both local and remote JMS destinations. Local connections will also need the JMS server config from the previous section. To connect to either Liberty JMS servers or traditional WebSphere Service Integration Bus, use the wasJmsClient feature. The feature has two versions, 1.1 and 2.0, that correspond to the matching versions of the jms feature.


<jmsConnectionFactory jndiName="jms/localCF">
    <properties.wasJms />

<jmsConnectionFactory jndiName="jms/remoteCF">
    <properties.wasJms remoteServerAddress="example.com:7276:BootstrapBasicMessaging" />

The format for remoteServerAddress is hostname:port:transportChain, where transportChain is either BootstrapBasicMessaging for non-secure JMS endpoints or BootstrapSecureMessaging for secure JMS endpoints. You can optionally omit the :transportChain portion of the address if you are using BootstrapBasicMessaging.

Liberty can provide administered objects for queues and topics that applications can use. This is where a topic can be subscribed to within a specific topic space on the JMS server. Applications can use these objects both to produce messages on the destination and consume messages from the destination.

<jmsTopic jndiName="jms/jmsLocalTopic">
    <properties.wasJms topicName="myTopic" topicSpace="myTopicSpace" />

<jmsQueue jndiName="jms/jmsRemoteQueue">
    <properties.wasJms queueName="myQueue" />

11.3. IBM MQ Client

Liberty can connect to IBM MQ servers and other messaging servers (e.g. ActiveMQ or RabbitMQ) with the appropriate resource adapter. You don’t need the wasJmsClient feature to connect to these servers. Be sure to read the documentation for your resource adapter and ensure it is configured properly to connect to the server. The following example will use IBM MQ.


<!-- The IBM MQ resource adapter is available here:  -->
<resourceAdapter id="mqJmsRa" location="/path/to/wmq.jmsra.rar">
    <classloader apiTypeVisibility="+third-party"/>

<jmsQueueConnectionFactory id="myRemoteQueueConnectionFactory" jndiName="jms/mqRemoteQCF">
    <properties.mqJmsRa channel="DEV.APP.SVRCONN" hostName="localhost" port="1414" queueManager="mqtest"/>

<jmsQueue id="myMQQueue" jndiName="jms/mqRemoteQueue">
    <properties.mqJmsRa baseQueueManagerName="mqtest" baseQueueName="DEV.QUEUE.1"/>

<jmsTopicConnectionFactory id="myRemoteTopicConnectionFactory" jndiName="jms/mqRemoteTCF">
    <properties.mqJmsRa channel="DEV.APP.SVRCONN" hostName="localhost" port="1414" queueManager="mqtest" clientId="myClientId"/>

<jmsTopic id="myMQTopic" jndiName="jms/mqRemoteTopic">
    <properties.mqJmsRa baseQueueManagerName="mqtest" baseTopicName="dev1/"/>

The MQ resource adapter is available at: MQ

To run an MQ Docker container locally:

docker run -it --rm=true --name mq-liberty \
           -e LICENSE=accept \
           -e MQ_QMGR_NAME=mqtest \
           -e MQ_ADMIN_PASSWORD=testpassword \
           -p 1414:1414 \
           -p 9443:9443 \

11.4. Exchanging JMS Messages

Regardless of how you configure your administered objects and what server they connect to, you will access them within your application in the same way. Obtain the destination and connection factory using JNDI, then use the connection factory to create a connection, use the connection to create a session, and use the session to create a producer and/or consumer that can interact with the destination.

import javax.jms.*;

// Note: In managed components (CDI beans, servlets, EJBs, etc) lookups can be replaced with @Resource annotations
QueueConnectionFactory factory = InitialContext.doLookup("jms/mqRemoteQCF");
Queue queue = InitialContext.doLookup("jms/mqRemoteQueue");

QueueConnection connection = factory.createQueueConnection();
QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

// Send a message to the queue
TextMessage message = session.createTextMessage("Your Message Here");
MessageProducer producer = session.createProducer(queue);


// Receive a message from the queue
MessageConsumer consumer = session.createConsumer(queue);
TextMessage result = (TextMessage) consumer.receieve(5000L);
System.out.println("Got " + result);



11.5. Reactive Messaging

MicroProfile Reactive Messaging (mpReactiveMessaging-1.0) provides a very easy-to-use way to send, receive, and process messages and is well-suited to writing applications that process streams of events.

MP Reactive Messaging is a different messaging API than the traditional JMS API. However, many of the same messaging engines (such as Kafka) can be used.

This blog post provides an excellent overview of the feature: Sending and receiving messages between microservices with MicroProfile Reactive Messaging

12. Security

To enable security for your application, enable the appSecurity-3.0 feature. This will cause all application endpoints requiring a role to go through HTTPS and some form of authentication.

12.1. Basic authentication

A simple form of authentication is the <basicRegistry> element, which allows you to directly configure user/password pairs.


<basicRegistry id="basic">
    <user name="bob" password="bobpwd"/>

<webApplication location="myApp.war">
        <!-- this can also be defined in web.xml instead -->
        <security-role name="admin">
            <user name="bob"/>

Then, managed resources (JAX-RS endpoints, servlets, etc) can be secured with @RolesAllowed:

public class HelloEndpoint {

    public String sayHello() {
        return "Hello World";

Accessing any endpoints in the HelloEndpoint (on http or https) will then then restrict access to a user in the admin role (in this case bob).

For more details see this guide: Security a web application

12.2. Secure Communication

Enabling SSL/TLS communication requires the transportSecurity-1.0 or ssl-1.0 feature. The transportSecurity-1.0 feature is newer and therefore preferred over the ssl-1.0 feature.

By default, the server will generate a default keystore at ${server.config.dir}/resources/security/key.p12.

The password for this keystore will be either:

  1. The password defined in <keyStore id="defaultKeyStore" password="…​" />

  2. Otherwise, it will use a randomly generated password which can be found in the ${server.config.dir}/server.env file.

The default SSL configuration will use the defaultKeyStore as both keystore and truststore. All TLS protocols are enabled by default: TLSv1, TLSv1.1, and TLSv1.2. If you are using Java 11 or newer, TLSv1.3 is also enabled.

By default, a Liberty server uses a self-signed certificate so that the default SSL configuration only trusts itself. To establish trust with other servers, trusted certificates should be added to the defaultKeyStore using a keystore tool like $JAVA_HOME/bin/keytool.

If manually adding trusted certificates is not desireded, then the default SSL configuration can be set to use the JDK’s default truststore like so:

<ssl id="defaultSSLConfig"  trustDefaultCerts="true" />

12.3. MicroProfile JWT

JSON Web Token (JWT) is a token-based authentication mechanism that offers a lightweight way for security controls and tokens to propagate user identities across different services. Because of these characteristics, it has become a popular security mechanism for microservice applications.

To use it, enable the mpJwt feature:


Then, configure the JWT issuer and public key with MicroProfile Config:

# If you set/override these values using environment variables,
# convert all '.' chars to '_' chars in property key names
mp.jwt.verify.publickey=<the JWT issuer's public key>

Lastly, resources can be secured using the @RolesAllowed annotation:

@RolesAllowed("users") // Requires jwts to have "group=users" claim
public class SecuredServiceEndpoint {

For more details see this guide: Securing microservices with JWTs

13. Integration Testing

There are two primary frameworks available to help make testing your Liberty applications easier:

13.1. MicroShed Testing

  • Ideal for testing apps that run in Docker containers

  • Ideal for testing REST endpoints

  • Ideal for testing apps that depend on other services (e.g. database or another HTTP-based service)

  • Ideal for black-box testing

  • OpenLiberty guide available here: Testing a MicroProfile or Jakarta EE application

See the MicroShed Testing website for full documentation

13.2. Arquillian

See arquillian.org for full documentation

14. Included OSS Components

Liberty Feature OSS Component


Apache BVal 1.1


Weld 2.4.X


Weld 3.X


Sun ref impl


Sun ref impl


Sun ref impl


Sun ref impl


Apache CXF 2.6


Apache CXF 3.2


Apache CXF 2.6


Apache CXF 3.2


EclipseLink 2.6


EclipseLink 2.7


Apache MyFaces 2.2


Apache MyFaces 2.3


Eclipse Yasson 1.0


Glassfish ref impl


Glassfish ref impl


SmallRye Reactive Messaging

15. Replaceable Components

  • JPA implementation can be changed (typically to Hibernate) using the jpaContainer-2.1 or 2.2 features

  • JSF implementation can be changed (typically to Mojarra) using the jsfContainer-2.2 or 2.3 features

  • JSON-B implementation can be changed using the jsonbContainer-1.0 feature

  • JSON-P implementation can be changed using the jsonpContainer-1.0 or 1.1 feature

16. Contribute

Find some incorrect information or want to contribute an additional section?

Fork this document on github and raise a PR: GitHub - openliberty-cheat-sheet