back to all blogsSee all blog posts

Jakarta EE 10 Core Profile debuts in Open Liberty 22.0.0.9-beta

image of author
Reece Nana on Aug 4, 2022

Open Liberty 22.0.0.9-beta brings you the hot-off-the-press Jakarta EE 10 Core Profile. Jakarta EE 10 will be the first release to provide updates to the specifications since Java EE 8 in 2017. Jakarta EE 10 Core Profile is a subset of the specifications. The Core Profile is specifically aimed at lightweight runtimes, like Open Liberty, that are optimised for running cloud-native Java microservices. While the whole Jakarta EE 10 release is just around the corner, Open Liberty 22.0.0.9-beta provides a preview of the Core Profile subset of features for you to start exploring now.

As well as Jakarta EE 10 Core Profile, we’ve included in this beta two other Jakarta EE features: Jakarta EE 10 Expression Language 5.0, which means you can access any annotations present on a particular method using the getAnnotations() method, and more; and Jakarta Concurrency 3.0, which enhances the set of parallel and reactive programming models available to applications, and more.

But it’s not only Jakarta EE features in this release: MicroProfile OpenAPI 3.1 provides the ability to specify optional authentication for operations and multiple annotation enhancements, and Password Utilities 1.1 no longer forcefully federates stand-alone user registries.

The Open Liberty 22.0.0.9-beta includes the following beta features (along with all GA features):

Support for multipart/form-data content type (RESTful Web Services 3.1)

Jakarta RESTful Web Services 3.1 (also known as Jakarta Rest 3.1 and formerly known as JAX-RS) is now available in the Open Liberty 22.0.0.9 beta. The 3.1 implementation is based on RESTEasy and is an EE10 technology, which uses the jakarta.* package name. For more information on the changes in this release, see the Changes Since 3.0 Release section of the Jakarta RESTful Web Services Spec.

Give it a try - and if you encounter any issues, please let us know!

You can enable RESTful Web Services 3.1 by using the restfulWS-3.1 feature in your server.xml file:

<featureManager>
  <feature>restfulWS-3.1</feature>
</featureManager>

If you only need a RESTful client, use the restfulWSClient-3.1 feature instead:

<featureManager>
  <feature>restfulWSClient-3.1</feature>
</featureManager>

To learn more about RESTful Web Services or see what is coming in future releases, visit the EE4J community page.

Enhanced JSON string parsing and new serialization/deserialization options (JSON Processing 2.1 and JSON Binding 3.0)

The Jakarta JSON Processing specification enables you to parse and generate JSON strings. The Jakarta JSON Binding specification is built on top of JSON Processing and enables you to serialize and deserialize Java objects into JSON.

The Jakarta JSON Processing specification has been updated with enhancements for handling duplicate keys when parsing JSON, and better handling of the java.lang.Number superclass when generating JSON strings. The Jakarta JSON Binding specification has been updated to support polymorphism.

Open Liberty provides default implementations for both Jakarta JSON Processing and Binding. For JSON Processing, we provide the Parsson implementation. For JSON Binding, we provide the Yasson implementation. To get these default implementations you can enable the jsonp-2.1 and jsonb-3.0 features.

<featureManager>
    <feature>jsonb-3.0</feature>
    <feature>jsonp-2.1</feature>
</featureManager>

If you want to use a third-party Jakarta JSON Processing 2.1 or Binding 3.0 implementation, you can enable the jsonpContainer-2.1 or jsonbContainer-3.0 features. The JSON Container features require you to configure a Basic Extensions using Liberty Libraries (BELLs) element that points to your third-party implementation(s).

<featureManager>
    <feature>jsonbContainer-3.0</feature>
    <feature>jsonpContainer-2.1</feature>
</featureManager>

<library id="myJsonBindingProvider">
  <file name="${path.to.json.binding.provider}"/>
</library>

<bell libraryRef="myJsonBindingProvider"/>

<library id="myJsonProcessingProvider">
  <file name="${path.to.json.processing.provider}"/>
</library>

<bell libraryRef="myJsonProcessingProvider"/>

Note that enabling either the JSON-B 3.0 feature (jsonb-3.0) or the JSON-B Container 3.0 (jsonbContainer-3.0) feature automatically enables the JSON-P 2.1 feature (jsonp-2.1), unless you have enabled the JSON-P Container 2.1 feature (jsonpContainer-2.1) in order to provide a third-party implementation of JSON-P.

You can find out more about this specific update and the wider technology with the following links:

Support for build compatible extensions and observable container state events (CDI 4.0)

CDI allows objects to be bound to lifecycle contexts, to be injected, to be associated with interceptors and decorators, and to interact in a loosely coupled fashion by firing and observing events. Highlights of CDI 4.0 include support for build compatible extensions and observable container state events. This update also brings in new Jakarta EE 10 versions of the Jakarta Annotations and Jakarta Interceptors APIs.

Build compatible extensions

Previous versions of CDI allowed users to provide Portable Extensions to customize the CDI application initialization lifecycle. These Build Compatible Extensions make implementing extensions amenable to build-time processing. To implement a Build Compatible Extension, provide an implementation of the BuildCompatibleExtension interface, declared via META-INF/services. The implementation can provide methods annotated with one of the extension annotations, each of which corresponds to the extension execution phases:

  • @Discovery

  • @Enhancement

  • @Registration

  • @Synthesis

  • @Validation

For example, as part of the Enhancement phase, this implementation adds an additional MyQualifier annotation to the MyService type:

public class MyExtension implements BuildCompatibleExtension {
    @Enhancement(type=MyService.class)
    public void addMyQualifier(ClassConfig clazz) {
        clazz.addAnnotation(MyQualifier.class)
    }
}

Startup and Shutdown events

Two new observable container state events are now available: Startup and Shutdown. Applications can listen for these events to be notified when the CDI container is starting up and being shut down.

@ApplicationScoped
public class MyObserver {
    public void observeStartup(@Observes Startup startupEvent) { {
        System.out.println("CDI Container is starting");
    }

    public void observeShutdown(@Observes Shutdown shutdownEvent) { {
        System.out.println("CDI Container is stopping");
    }
}

You can control the order of multiple observer methods by using the @Priority annotation.

Empty beans.xml files

In previous versions of CDI, an empty beans.xml file indicated that an archive should be treated as an explicit bean archive (the equivalent of bean-discovery-mode="all"). In CDI 4.0, an empty beans.xml now causes an archive to be treated as an implicit bean archive (the equivalent of bean-discovery-mode="annotated"). If necessary, you can set the emptyBeansXmlCDI3Compatibility configuration option to enable compatibility with previous versions.

Unversioned beans.xml files

In previous versions of CDI, a non-empty beans.xml file that did not include a version attribute defaulted to bean-discovery-mode="all". In CDI 4.0, it defaults to bean-discovery-mode="annotated". However, you should properly version all beans.xml files, as shown in the following configuration example:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="https://jakarta.ee/xml/ns/jakartaee"
    xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
    version="4.0"
    bean-discovery-mode="annotated">
</beans>

Programmatic lookup of beans and instances

A new Handle API is now available to make programmatic inspection of Bean metadata easier. This avoids the need to create instances before they are actually required. You can obtain a Handle using the Instance API:

public interface Handle<T> extends AutoCloseable {
        T get();
        Bean<T> getBean();
        void destroy();
        void close();
}

Removed APIs

The following previously deprecated CDI APIs have been removed:

  • @New qualifier - replaced by @Dependent beans.

  • Bean#isNullable() - has not been used by the implementation since CDI 1.1.

  • BeanManager#fireEvent() - Use BeanManager.getEvent() instead.

  • BeanManager#createInjectionTarget(AnnotatedType) - replaced by BeanManager#getInjectionTargetFactory(AnnotatedType)

  • BeforeBeanDiscovery#addAnnotatedType(AnnotatedType) - replaced by BeforeBeanDiscovery#addAnnotatedType(AnnotatedType, String)

Configuration

The Liberty <cdi12> server.xml configuration element has been superseded by a new <cdi> element, which applies to CDI versions 1.2 and later. For example:

<cdi enableImplicitBeanArchives="false" emptyBeansXmlCDI3Compatibility="true"/>
  • The enableImplicitBeanArchives attribute is the same as it was in previous versions.

    • If set to true, which is the default, then archives that do not contain a beans.xml file are treated as Implicit Bean Archives and scanned for classes that have bean defining annotations.

    • If set to false, then archives that do not contain a beans.xml file are not scanned for annotated classes.

  • The emptyBeansXmlCDI3Compatibility attribute applies only to CDI 4.0.

    • If set to true, then an archive that contains an empty beans.xml file is treated as an explicit bean archive, as it was in CDI 3.0 and earlier.

    • If set to false, which is the default, then an archive that contains an empty beans.xml file is treated as an implicit bean archive. This is equivalent to setting bean-discovery-mode="annotated"..

To use the CDI 4.0 feature, add cdi-4.0 to your server.xml:

<featureManager>
  <feature>cdi-4.0</feature>
</featureManager>

Access any available annotations using getAnnotations() (Expression Language 5.0)

Jakarta EE 10 Expression Language 5.0 includes a number of new features, deprecations, and specification clarifications. One of the new features is the addition of the MethodReference, a new class that allows developers to access any annotations present on a particular method using the getAnnotations() method.

To enable Expression Language 5.0, add the expressionLanguage-5.0 feature to the list of features in your server.xml file:

<featureManager>
  <feature>expressionLanguage-5.0</feature>
</featureManager>

More information about Expression Language 5.0 can be found in:

Enhanced parallel and reactive programming models available to applications (Concurrency 3.0)

The Jakarta Concurrency specification enhances the set of parallel and reactive programming models available to applications, enabling tasks and completion stage actions to run with the thread context of the submitter.

Concurrency 3.0 includes the following enhancements:

  • Resource definition annotations that put applications in control of defining the concurrency constraints and thread context types that the application requires

  • Context-aware completion stages that are managed by the container

  • Asynchronous methods that are backed by context-aware completion stages

  • Improvements to Triggers for customizing the scheduling of business logic according to dates and times within one’s own time zone

  • Standardized integration for third-party providers of thread context

Enable the concurrent-3.0 feature in server.xml, along with other Jakarta EE 10 beta features that you wish to use in combination with it, for example:

<featureManager>
  <feature>concurrent-3.0</feature>
  <!-- other features that are used in the examples: -->
  <feature>cdi-4.0</feature>
  <feature>jdbc-4.2</feature>
  <feature>jndi-1.0</feature>
  <feature>restfulWS-3.1</feature>
</featureManager>

You can still configure <managedExecutorService> and other Concurrency resource types in your server.xml file as you did for previous versions of the feature. However, In Concurrency 3.0 you can define those resources within application components. With the CDI feature enabled, methods that return a CompletionStage or CompletableFuture can be designated to run asynchronously by annotating them with @Asynchronous. For example:

import jakarta.enterprise.concurrent.Asynchronous;
import jakarta.inject.Singleton;

import java.sql.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

@Singleton
public class AccountsBean {

    @Asynchronous(executor = "java:module/concurrent/MyExecutor")
    CompletableFuture<List<Account>> findOverdue(int minDaysLate) {
        List<Account> overdueAccounts = new ArrayList<Account>();
        try {
            // Resource reference lookup requires context of the application component,
            DataSource db = InitialContext.doLookup("java:comp/env/jdbc/account-db-ref");
            ...
            return Asynchronous.Result.complete(overdueAccounts);
        } catch (NamingException | SQLException x) {
            throw new CompletionException(x);
        }
    }

    ...

When the application invokes the asynchronous method, the container intercepts the invocation and hands back a completion stage representing its eventual completion, which is arranged by the ManagedExecutorService. For example:

    @GET
    public Response remindAboutOverdueAccounts () {
        ...
        accounts.findOverdue(60).thenAccept(this::sendReminder);
        ...
    }

    void sendReminder(List<Account> overdue) {
        try {
            // Resource reference lookup requires context of the application component,
            DataSource db = InitialContext.doLookup("java:comp/env/jdbc/customer-db-ref");
            ...
        } catch (NamingException | SQLException x) {
            throw new CompletionException(x);
        }
    }

The Maven coordinates for Concurrency 3.0 are as follows:

<dependency>
    <groupId>jakarta.enterprise.concurrent</groupId>
    <artifactId>jakarta.enterprise.concurrent-api</artifactId>
    <version>3.0.0</version>
</dependency>

For more resources regarding Concurrency 3.0, reference the following links:

Document APIs where authentication is optional or complex (MicroProfile OpenAPI 3.1)

The OpenAPI specification standardizes a way of documenting REST APIs in a JSON or YAML format. The MicroProfile OpenAPI specification helps you generate and serve OpenAPI documentation for your REST applications that are built by using JAX-RS or Jakarta RESTful Web Services. This can be useful for developers to test out the API during development, or for people using the API in production.

MicroProfile OpenAPI 3.1 is a minor release that includes the following updates:

  • Some Jakarta Bean Validation annotations will now be read and their restrictions will be added to object schemas.

  • Most annotations now include an extension attribute.

  • @SecurityRequirementsSet can now be used to document operations where authentication is optional or where more than one authentication mechanism is required.

To use MicroProfile OpenAPI 3.1, add the mpOpenAPI-3.1 feature to your server.xml:

<featureManager>
    <feature>mpOpenAPI-3.1</feature>
</featureManager>

Next, deploy your rest application and then visit the /openapi endpoint to view the OpenAPI documentation, or visit /openapi/ui for a user interface where you can browse through it. You can enhance the documentation by using annotations to add things like textual descriptions to each method. The annotations are available as a Maven dependency:

<dependency>
    <groupId>org.eclipse.microprofile.openapi</groupId>
    <artifactId>microprofile-openapi-api</artifactId>
    <version>3.1-RC2</version>
</dependency>

For more information about MicroProfile OpenAPI, see the following links:

Stand-alone user registries no longer forcefully federated (Password Utilities 1.1)

The new passwordUtilities-1.1 feature no longer starts the federatedRegistry-1.0 feature or the Jakarta Connectors feature. Stand-alone user registries are no longer forcefully federated, which sometimes results in slightly different behavior.

To enable Password Utilities 1.1, add the passwordUtilities-1.1 feature to the list of features in your server.xml file:

<featureManager>
    <feature>passwordUtilities-1.1</feature>
</featureManager>

For more information about the Password Utilities, check out the feature documentation.

Try it now

To try out these features, just update your build tools to pull the Open Liberty All Beta Features package instead of the main release. The beta works with Java SE 18, Java SE 17, Java SE 11, and Java SE 8, however, the Jakarta EE 10 features are only compatible with Java SE 11 and later.

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

<dependency>
  <groupId>io.openliberty.beta</groupId>
  <artifactId>openliberty-runtime</artifactId>
  <version>22.0.0.9-beta</version>
  <type>pom</type>
</dependency>

Or for Gradle:

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

Or take a look at our Downloads page.

We welcome your feedback

Let us know what you think on our mailing list. If you hit a problem, post a question on StackOverflow. If you hit a bug, please raise an issue.

Tags