back to all blogsSee all blog posts

Enhanced concurrency capabilities with MicroProfile Context Propagation on Open Liberty 19.0.0.8

image of author
Yasmin Aumeeruddy on Aug 16, 2019

MicroProfile Context Propagation enhances the concurrency capabilities of Java SE and Java EE by allowing you to create pipelines of dependent stages that run with predictable thread context regardless of which thread the completion stage action ends up running on. Also in 19.0.0.8, Oracle users can now encrypt SSL passwords in connection properties configuration before they are sent to the Oracle JDBC driver.

Give it a try in Open Liberty 19.0.0.8.

In Open Liberty 19.0.0.8:

If you’re curious about what’s coming in future Open Liberty releases, take a look at our previews in the latest development builds. In particular, get an early insight into MicroProfile Reactive Messaging.

Run your apps using 19.0.0.8

If you’re using Maven, here are the coordinates:

<dependency>
    <groupId>io.openliberty</groupId>
    <artifactId>openliberty-runtime</artifactId>
    <version>19.0.0.8</version>
    <type>zip</type>
</dependency>

Or for Gradle:

dependencies {
    libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '[19.0.0.8,)'
}

Or if you’re using Docker:

docker pull open-liberty

Or take a look at our Downloads page.

Ask a question on Stack Overflow

Enhancing concurrency capabilities (MicroProfile Context Propagation 1.0)

MicroProfile Context Propagation enhances the concurrency capabilities of Java SE and Java EE by allowing you to create pipelines of dependent stages that run with predictable thread context regardless of which thread the completion stage action ends up running on.

Example in server.xml:

  <featureManager>
    <feature>mpContextPropagation-1.0</feature>
    <feature>cdi-2.0</feature> <!-- used in example -->
    <feature>jndi-1.0</feature> <!-- used in example -->
    ... other features
  </featureManager>

Example usage of programmatic builders:

import org.eclipse.microprofile.context.ManagedExecutor;
import org.eclipse.microprofile.context.ThreadContext;
...

ManagedExecutor executor = ManagedExecutor.builder()
    .maxAsync(5)
    .propagated(ThreadContext.APPLICATION, ThreadContext.SECURITY)
    .build();

CompletableFuture<Integer> stage1 = executor.newIncompleteFuture();
stage1.thenApply(function1).thenAccept(value -> {
    try {
        // access resource reference in application's java:comp namespace,
        DataSource ds = InitialContext.doLookup("java:comp/env/jdbc/ds1");
        ...
    } catch (Exception x) {
        throw new CompletionException(x);
    }
};
...
stage1.complete(result);

...
// Shut down managed executor once the application no longer needs it
executor.shutdown();

Example usage in a CDI bean:

// CDI qualifier which is used to identify the executor instance
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
public @interface AppContext {}

// Example producer field, defined in a CDI bean,
@Produces @ApplicationScoped @AppContext
ManagedExecutor appContextExecutor = ManagedExecutor.builder()
    .propagated(ThreadContext.APPLICATION)
    .build();

// Example disposer method, also defined in the CDI bean,
void disposeExecutor(@Disposes @AppContext exec) {
    exec.shutdownNow();
}

// Example injection point, defined in a CDI bean,
@Inject @AppContext
ManagedExecutor executor;

...

CompletableFuture<Integer> stage = executor
    .supplyAsync(supplier1)
    .thenApply(function1)
    .thenApplyAsync(value -> {
        try {
            // access resource reference in application's java:comp namespace,
            DataSource ds = InitialContext.doLookup("java:comp/env/jdbc/ds1");
            ...
            return result;
        } catch (Exception x) {
            throw new CompletionException(x);
        }
    });

For more information:

Oracle SSL properties encryption support

Oracle users can set JDBC driver connection properties in the connectionProperties configuration element of server.xml. Those connection properties include javax.net.sslKeyStorePassword and javax.net.sslTrustStorePassword whose values are passwords. Until now, unlike many other config elements containing passwords, you could not encrypt these values and they had to be in clear text. From 19.0.0.8, you can encrypt those values and Open Liberty decrypts them before sending them to the Oracle JDBC driver. Passwords can be encrypted using the encode option of the Open Liberty securityUtility script in the ${wlp.install.dir}/bin directory.

Example prior to 19.0.0.8:

<properties.oracle URL="jdbc:oracle:thin:@//...” connectionProperties="oracle.net.ssl_version=1.2;javax.net.ssl.keyStore=path-to-keystore/keystore.p12;javax.net.ssl.keyStorePassword=WooHoo; javax.net.ssl.trustStore= path-to-keystore/keystore.p12;javax.net.ssl.trustStorePassword=password”/>

Example after 19.0.0.8:

<properties.oracle URL="jdbc:oracle:thin:@//...” connectionProperties="oracle.net.ssl_version=1.2;javax.net.ssl.keyStore=path-to-keystore/keystore.p12;javax.net.ssl.keyStorePassword={xor}CDAwFzAw; javax.net.ssl.trustStore= path-to-keystore/keystore.p12;javax.net.ssl.trustStorePassword={aes}AAbk9iEIjV06JSZMTpsW+6B+TjN+XjB2bs8hii2uZuMu"/>

No more clear text SSL keystore passwords!

For more details about encrypting passwords for Liberty, see this Knowledge Center doc.


Previews of early implementations available in development builds

You can now also try out early implementations of some new capabilities in the latest Open Liberty development builds:

These early implementations are not available in 19.0.0.8 but you can try them out in our daily Docker image by running docker pull openliberty/daily. Let us know what you think!

Reactive messaging in microservices (MicroProfile Reactive Messaging)

An application using reactive messaging is composed of CDI beans consuming, producing, and processing messages passing along reactive streams. These messages can be internal to the application or can be sent and received via different message brokers.

Reactive Messaging provides a very easy to use way to send, receive, and process messages. With MicroProfile Reactive Messaging, you can annotate application beans' methods to have messages on a particular channel (@Incoming, @Outgoing, or both) and Liberty drives those methods appropriately as reactive streams publishers, subscribers, or processors.

To enable the feature include it in your server.xml feature list:

<featureManager>
  <feature>mpReactiveMessaging-1.0</feature>
  ...
</featureManager>

With this feature in the OpenLiberty runtime, an application CDI bean can have one of its methods annotated as being message driven. In the example below, the method processes messages from the "greetings" channel:

@Incoming("greetings")
publicCompletionStage <Void> consume(Message<String> greeting ){
   return greeting.ack();
}

A channel represents a stream of messages of a given type and, usually, the same topic. Channels can operate locally within the process or use message brokers to send messages between services.

For example, with no code changes we could change the consume method above to subscribe to messages from the Kafka greetings topic using a Kafka connector like so:

mp.messaging.incoming.greetings.connector=io.openliberty.kafka

The io.openliberty.kafka connector operates according to the reactive messaging specification. For example the consume method above is, by default, set to consume messages from a Kafka topic queue. Further Kafka client properties can be set for the channel by setting properties that are picked up by the MicroProfile Config specification. For example, System properties via OpenLiberty’s bootstrap.properties file or environment variables from OpenLiberty’s server.env file. As per the reactive messaging specification the following configuration properties are passed to the Kafka client:

mp.messaging.incoming.greetings.[PROPERTY-NAME]=value1
mp.messaging.connector.io.openliberty.kafka.[PROPERTY-NAME]=value2

These are passed to the Kafka Consumer factory method as:

PROPERTY-NAME=value

So, for example, a full set of properties to access IBM Public Cloud Event Streams could look like:

mp.messaging.connector.io.openliberty.kafka.bootstrap.servers=broker-1-eventstreams.cloud.ibm.com:9093,broker-2-eventstreams.cloud.ibm.com:9093
mp.messaging.connector.io.openliberty.kafka.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="token" password="my-apikey";
mp.messaging.connector.io.openliberty.kafka.sasl.mechanism=PLAIN
mp.messaging.connector.io.openliberty.kafka.security.protocol=SASL_SSL
mp.messaging.connector.io.openliberty.kafka.ssl.protocol=TLSv1.2

When using Kafka-based channels, Open Liberty Reactive Messaging 1.0 loads the Kafka client classes using the application classloader. If you are using the io.openliberty.kafka connector to read or write Kafka messages, include in your application a Kafka client API jar that is compatible with your Kafka server. For example, the /WEB-INF/lib/ folder would be a suitable place to place a Kafka client JAR when building the application’s .war file.

This is an early release of the Open Liberty Reactive Messaging Kafka connector. We will look to provide more support for sensible defaults and cloud binding information such as Cloud Foundry’s VCAP_SERVICES environment variable in the 1.0 release.

Testing database connections in Liberty apps with REST APIs

How many times have you had to write a server-side test that gets a connection just to check if your configuration is valid and your app can connect to your database? Now by utilizing the REST API provided by the configValidator-1.0 beta feature, you can validate supported elements of your configuration via REST endpoints.

To enable these REST endpoints, add the configValidator-1.0 beta feature to any server using JDBC, JCA, or JMS technologies. For more information checkout this blog post.

<featureManager>
    <feature>configValidator-1.0</feature>
</featureManager>

Tags