Get full Java EE 8 in Open Liberty 18.0.0.2

Yes, it’s here! Open Liberty is the first app server (to our knowledge) with full Java EE 8 support. What does that mean? Well, we’ve got the goodness of JAX-RS 2.1 reactive client and server-sent events, CDI event-ordering and asynchonous events, HTTP/2 support in servlets, JSF 2.3 (for the JSF fans, you know who you are), JPA 2.2, JWT cookies (yum!), security improvements,…​oh, and you can now deploy Spring Boot applications to Liberty #justsayin'

What are you waiting for? Download Open Liberty 18.0.0.2:

Download Open Liberty
Ask a question on Stack Overflow

Alternatively, if you’re using Maven, here are the coordinates:

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

Or for Gradle:

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

Or if you’re using Docker:

docker pull open-liberty

In Open Liberty 18.0.0.2, you’ll find:

As we don’t have a full set of documentation implemented for Open Liberty yet, the items below point to the official documentation for WebSphere Liberty so you can find out more about them (WebSphere Liberty is built on Open Liberty).

Full support for Java EE 8

Download Liberty with either the Java EE 8 Web Profile runtime or the Java EE 8 Full Platform runtime.

You can enable all of the Java EE 8 features (or the more lightweight set of Web Profile features) with a single feature in your server.xml.

Java EE 8 Web Profile

The features included when you enable the webProfile-8.0 feature (Java EE 8 Web Profile) and are new in Java EE 8 are:

  • appSecurity-3.0

  • beanValidation-2.0

  • cdi-2.0

  • jaxrs-2.1

  • jaxrsClient-2.1

  • jpa-2.2

  • jpaContainer-2.2

  • jsf-2.3

  • jsonb-1.0

  • jsonp-1.1

  • servlet-4.0

The webProfile-8.0 feature also contains the following features which are unchanged from Java EE 7: distributedMap01.0, ejbLite-3.2, el-3.0, jaspic-1.1, jdbc-4.2, jndi-1.0, jsp-2.3, managedBeans-1.0, ssl-1.0, websocket-1.1.

To enable the whole of the webProfile-8.0 feature, add the feature definition to your server.xml:

<featureManager>
    <feature>webProfile-8.0</feature>
</featureManager>

Java EE 8 Full Profile

The features included when you enable the javaee-8.0 feature (Java EE 8 Full Platform) and are new in Java EE 8 are:

  • webProfile-8.0 (see above)

  • javaMail-1.6

The javaee-8.0 feature also contains the following features which are unchanged from Java EE 7: appClientSupport-1.0, batch-1.0, concurrent-1.0, ejb-3.2, ejbHome-3.2, ejbPersistentTimer-3.2, jacc-1.5, jaspic-1.1, jaxws-2.2, jca-1.7, jcaInboundSecurity-1.0, jms-2.0, mdb-3.2, wasJmsClient-2.0, wasJmsSecurity-1.0, wasJmsServer-1.0.

To enable the whole of the javaee-8.0, add the feature definition to your server.xml:

<featureManager>
    <feature>javaee-8.0</feature>
</featureManager>

For more info:

Reactive client and server-sent events with JAX-RS 2.1

JAX-RS 2.1 enables two exciting new technologies: reactive client and server-sent events. The reactive client takes full advantage of Java 8 lambda expressions to enable highly scalable multi-threaded clients. Server-sent events allow developers to send data asynchronously to multiple clients, either individually or by broadcasting to all in an efficient manner.

Coding an asynchronous JAX-RS client was possible in JAX-RS 2.0 but the reactive client in 2.1 enables much more parallelism with much less code. Users can now kick off multiple client requests having each one react to the response from the server, potentially by making new asynchronous requests.

Server-sent events was not possible using JAX-RS APIs prior to 2.1. Users wishing to send updates to remote clients using JAX-RS would need to rely on polling which is inefficient. Otherwise, they would need to rely on third-party implementations to provide SSE or SSE-like functionality. Now a JAX-RS resource can allow multiple clients to register for events - then send them on a schedule, randomly, at the request of other clients, with very little code.

To enable JAX-RS 2.1, add the definition to your server.xml:

<featureManager>
    <feature>jaxrs-2.1</feature>
</featureManager>

For more info:

Asynchronous events, event ordering, and more with CDI 2.0

CDI 2.0 provides the following support:

  • Activate Request Context - Some third-party framework developers might want to have their own request lifecycle and have a tight control of it without creating a custom context. Previously, it was not possible for application developers to activate Request Context. CDI 2.0 added this support so that some unnecessary custom Request Scoped creation can be avoided.

  • Event ordering and asynchronous events - Prior to CDI 2.0, it was not possible to order the event notification. In CDI 2.0, use @Priority to order the synchronous event notifications. In CDI 2.0, you can fire and observe asynchronous events.

  • Add Interceptor support to produced beans - CDI 2.0 adds interceptor support on a producer using InterceptionFactory so that the produced beans have interceptors applied.

  • Provide a number of annotation literals - CDI uses annotation literals in various places. Previously, you needed to create annotation literal classes for some built-in scopes or qualifiers. In CDI 2.0, the APIs have the annotation literal provided so that the annotation literal for some useful scopes or qualifiers are provided by the CDI APIs.

For example, in order to find a Foo bean with the Default qualifier, before CDI 2.0 you needed to do the following:

@Inject Instance<Foo> foo;

public Foo getFoo() {

return instance.select(DefaultLiteral.INSTANCE).get();

}

public class DefaultLiteral extends AnnotationLiteral<Default> implements Default {

    public static final DefaultLiteral INSTANCE = new DefaultLiteral();

    private DefaultLiteral() {}

}

In CDI 2.0, you can do the following:

@Inject Instance<Foo> foo;

public Foo getFoo() {

return instance.select(Default.Literal.INSTANCE).get();

}

As you can see, in CDI 2.0, you can use Default.Literal.INSTANCE` to get the annotation of Default, which is a lot simpler.

  • CDI SPI configurators - In CDI 1.x, using SPI is used to generate verbose and less elegant code. In CDI 2.0, the configurators solve this. These configurators are accessible in lifecycle container event when writing extensions.

To enable the CDI 2.0 feature, add the feature definition to your server.xml:

           <featureManager>
                  <feature>cdi-2.0</feature>
          </featureManager>

Write dynamic web applications with Servlet 4.0

Servlet 4.0 is the latest Java EE 8 version of the Servlet specification.

The servlet-4.0 feature includes the new Servlet 4.0 features and functions, for example:

  • Support for HTTP/2 push/promise.

  • Support for HTTP trailers.

  • HttpServletRequest.getServletMapping()

  • ServletContext.getSessionTimeout() and setSessionTimeout()

  • ServletContext.addJspFile()

  • Support for new elements in web.xml:

    • default-context-path

    • request-character-encoding

    • response-character-encoding

To enable the Servlet 4.0 feature, add the feature definition to your server.xml:

<featureManager>
    <feature>servlet-4.0</feature>
</featureManager>

For more info:

HTTP/2 protocol support

HTTP/2 is an optimization of the HTTP/1.1 protocol. Use of the HTTP/2 protocol is initiated by the client and accepted by the server. Web applications that involve numerous HTTP/1.1 sessions per webpage can see a significant performance improvement by opting into HTTP/2. Much of the optimization is achieved by allowing multiple HTTP/1.1 sessions to be transacted in parallel over one initial upgraded HTTP/1.1 connection.

Secure HTTP/2 (h2) uses ALPN (Application-Layer Protocol Negotiation) to upgrade the protocol of an HTTP/1.1 session to HTTP/2. Insecure HTTP/2 (h2c) can be negotiated via an HTTP/1.1 Upgrade header. The HTTP/2 protocol then allows for full-duplex communication of HTTP/1.1 traffic between client and server over this one upgraded connection. Both client and server have to opt into the HTTP/2 protocol with the ALPN handshake being initiated by the client.

Servlet 4.0 makes use of the HTTP/2 protocol to implement the Servlet 4.0 Server Push APIs, and HTTP/2 is enabled when the Servlet 4.0 Liberty feature is enabled.

If the Servlet 3.1 Liberty feature is enabled instead of Servlet 4.0, HTTP/2 is off by default but can be enabled by setting the protocolVersion = "http/2" attribute of the httpEndpoint element.

For more info, see:

Build user interfaces for web application with JavaServer Faces (JSF) 2.3

Take advantage of the latest JSF features and enhancements. The jsf-2.3 feature pulls in the Apache MyFaces implementation and integrates it into the Liberty runtime. The new JSF 2.3 capabilities include:

  • <f:importConstants/>

  • Enhanced component search facility

  • DataModel implementions can be registered

  • CDI replacement for @ManagedProperty

  • UIData and <ui:repeat> support for Map and Iterable

  • <ui:repeat> condition check

  • Java Time support

  • WebSocket integration using <f:websocket>

  • Multi-field validation using <f:validateWholeBean>

  • Use CDI for evaluation of JSF-specific Expression Language implicit objects

  • Support @Inject on JSF-specific artifacts

  • Ajax Method Invocation. See vdldoc for <h:commandScript>

  • Add PartialViewContext.getEvalScripts() method which returns a mutable list of scripts

With the delivery of JSF 2.3 you can also use your own JSF 2.3 implementation using the jsfContainer-2.3 feature.

To enable the JSF 2.3 feature, add the feature definition to your server.xml:

           <featureManager>
                  <feature>jsf-2.3</feature>
          </featureManager>

The CDI 2.0 feature is now available (cdi-2.0) and should be used with the jsf-2.3 feature.

For more info:

Interact with databases with Java Persistence API (JPA) 2.2

Java 8 introduced a new Date and Time API, which is more powerful than the old APIs part of java.util for years. Collection streaming, introduced in Java 8, is now formally supported by the JPA 2.2 specification, enabling new ways to process query result sets. Many JPA annotations are now repeatable, eliminating the need to use grouping annotations.

To enable the JPA 2.2 feature, add the feature definition to your server.xml:

           <featureManager>
                  <feature>jpa-2.2</feature>
          </featureManager>

This enables JPA 2.2 and the EclipseLink 2.7 JPA persistence provider that is bundled with the feature. If you prefer to use your own EclipseLink 2.7 binaries, you can instead enable the <feature>jpaContainer-2.2</feature> feature, which provides JPA 2.2 container integration but does not enable the provided EclipseLink JPA provider implementation.

Examples of JPA 2.2 Enhancements:

@Repeatable Annotations

Before JPA 2.2:

@PersistenceContexts(
  @PersistenceContext(name=foo, unitName=bar),
  @PersistenceContext(name=cloud, unitName=sky))
@Stateless
public class SomeEJB {

With JPA 2.2:

@PersistenceContext(name=foo, unitName=bar),
@PersistenceContext(name=cloud, unitName=sky)
@Stateless
public class SomeEJB {

JPA 2.2 Supports java.time Types

@Entity
public class MyEntity {

  // The following map to database time column types natively now
  @Basic private java.time.LocalDate localDate;
  @Basic private java.time.LocalDateTime localDateTime;
  @Basic private java.time.LocalTime localTime;
  @Basic private java.time.OffsetTime offsetTime;
  @Basic private java.time.OffsetDateTime offsetDateTime;

}

Attribute Converter classes now support CDI bean injection

@Converter
public class B2IConverter implements AttributeConverter<Boolean, Integer> {
    final static Integer FALSE = new Integer(0);
    final static Integer TRUE = new Integer(1);

    @Inject
    private MyLogger logger;

    @Override
    public Integer convertToDatabaseColumn(Boolean b) {
        Integer i = b ? TRUE : FALSE;
        logger.log("Convert: " + b + " -> " + i);
        return i;
    }

    @Override
    public Boolean convertToEntityAttribute(Integer i) {
        Boolean b = TRUE.equals(s) ? Boolean.TRUE : Boolean.FALSE;
        logger.log("Convert: " + i + " -> " + b);
        return b;
    }
}

Method Stream getResultStream() added to Query and TypedQuery interfaces

@Stateless public class SBean {
   @PersistenceContext(unitName=Personnel) EntityManager em;

   public int getEmployeeSalaryBudget(int deptId) {
      final AtomicInteger salBudget = 0;

      TypedQuery<Employee> q = em.createQuery(SELECT e FROM Employee e WHERE e.deptId = :deptId, Employee.class);
      q.setParameter(deptId, deptId);

      Stream<Employee> empStream = q.getResultStream();
      empStream.forEach( t -> salBudget.set(salBudget.get() + t.getSalary()));

      return salBudget.get();
   }
}

For more info:

Emit and consume JWT cookies with JWT Single Sign-on 1.0

Java Web Tokens (JWT) single sign-on (SSO) cookies can replace proprietary LTPA cookies in many scenarios. They offer improved interoperability and simplified use compared to LTPA cookies in heterogenous and microservice environments.

In microservice environments, the self-contained nature of JWT means consuming services don’t need to contact an LDAP server or other identity provider in order to complete authentication and authorization. In heterogenous environments, the standards-based JWT is usable across multiple implementations where the proprietary WebSphere LTPA cookie is not. JSON Web Key (JWK) can be used for key retrieval to simplify key management.

To enable JWT SSO so that Liberty emits and consumes JWT cookies instead of LTPA cookies, add the definition to your server.xml:

<featureManager>
    <feature>JwtSso-1.0</feature>
</featureManager>

For more info:

Secure your applications using Security API 1.0 specification

The appSecurity-3.0 feature provides support for the Java EE Security API 1.0 specification. The Java Specification Request (JSR) 375 specifies the requirement.

The specification promotes self-contained application security portability across all Java EE servers, and makes use of modern programming concepts such as expression language and context dependency injection (CDI). It defines annotations specific to various authentication mechanisms, identity stores to handle user authentication, and common programming API to do programmatic Java EE security. It reduces the dependency on the deployment descriptors and application server based configuration for securing Java EE web resources.

Once you configure the appSecurity-3.0 feature, your application can annotate the authentication mechanisms and the identity stores that are needed. The applications can provide their own implementations to replace the application server provided ones. For example, you can create a custom authentication mechanism that you can bundle in your web application without the need to configure the login-config element in the web.xml file with one of the predefined auth-method types. If you also include your own IdentityStore bean in your application, your IdentityStore can be used to verify the user credentials without the need to configure a user registry in the server.xml.

The applications can also use the SecurityContext API defined in the specification to perform programmatic security checks.

To enable the Security API 1.0 feature, add the feature definition to your server.xml:

<featureManager>
    <feature>appSecurity-3.0</feature>
</featureManager>

For more info:

Store JSON with JSON-B 1.0

JSONB provides a structured format for storing JSON. The <code>jsonb-1.0</code> feature provides a preview of the JSON Binding (JSON-B) 1.0 specification interfaces, as well as the reference implementation (Eclipse Yasson).

JSON technology has proven to be a powerful tool in modern Java EE applications, especially when using a microservices-oriented architecture. Traditionally applications had to provide their own JSON binding implementations and package them in a shared library or application. With the <code>jsonb-1.0</code> feature, the specification interfaces and implementation are provided out of the box, ready to be used directly by applications.

To enable the JSON-B 1.0 feature, add the feature definition to your server.xml:

<featureManager>
    <feature>jsonb-1.0</feature>
</featureManager>

For more info:

Validate objects, parameters, and more with Bean Validation 2.0

With the bean validation 2.0 feature, Liberty is using Hibernate Validator as its bean validation implementation. Previously for bean validation 1.0 and 1.1 we used Apache Validator.

To enable the bean validation 2.0 feature, add the feature definition to your server.xml:

<featureManager>
    <feature>beanValidation-2.0</feature>
</featureManager>

For more info:

Deploy Spring Boot applications to Liberty

Liberty now supports deploying Spring Boot application uber (or fat) JARs without requiring them to be repackaged as a WAR. Additional tools are provided to manage and separate the embedded dependencies of a Spring Boot application in order to provide more efficient deployments using Docker. When a Spring Boot application is deployed the Liberty web container is used instead of the embedded server packaged with the Spring Boot application, for example Tomcat, Jetty or Undertow.

To give it a try, add springBoot-1.5 or springBoot-2.0 to the feature list in the server.xml. Most Spring Boot applications also require a Servlet feature to be enabled (either servlet-3.1 or servlet-4.0).

You can also add features for WebSocket support (websocket-1.0 or websocket-1.1), JSP support (jsp-2.3), and HTTPS support (transportSecurity-1.0).

For example:

<featureManager>
    <feature>springBoot-2.0</feature>
    <feature>servlet-4.0</feature>
    <feature>websocket-1.1</feature>
    <feature>jsp-2.3</feature>
    <feature>transportSecurity-1.0</feature>
</featureManager>

Deploy your Spring Boot applications to liberty in one of the following ways:

  • Place the Spring Boot application JAR in the server’s dropins/spring/ folder (e.g. dropins/spring/myapp.jar) or directly in the dropins/ folder and using the .spring extension (e.g. dropins/myapp.jar.spring).

  • Place the Spring Boot application JAR in the server’s apps/ folder and add a <springBootApplication/> element to the server.xml (e.g. <springBootAppilication location="myapp.jar" />).

For more info, see:

Control how custom X.509 certificates map to users in Liberty’s LDAP and basic user registries

You now have complete control over how certificates are mapped to users in the user registry.

The out-of-the-box X.509 certificate mappers for the LDAP user registry did not handle custom OID’s, parsing of certificate fields and included custom filtering of only a subset of the certificate’s fields. For example, there was no support for Subject Alternative Name (SAN). The out-of-the-box X.509 certificate mapper for the basic user registry only supported using the subject’s cn RDN for the user name. With the X509CertificateMapper API, you can now map a X.509 certificate to a user in the user registry in any way that is required.

Enabling the custom mapping using the BELLs feature

Implement the com.ibm.websphere.security.X509CertificateMapper interface and include it in a JAR. Also include in the JAR a Java ServiceLoader provider configuration file (META-INF/com.ibm.websphere.security.X509CertificateMapper) that contains the fully-qualified class names of any X509CertificateMapper implementations to be used in the Liberty server. Each implementation must be preceded by a comment line containing a key-value pair containing the key x509.certificate.mapper.id and a unique ID as the value. Use this ID to reference the implementation from the server.xml configuration file. Load these implementations into Liberty’s classpath using the bells-1.0 feature and a shared library.

Example configuration file entry:

           # x509.certificate.mapper.id=basicMapper
           com.mycompany.BasicMapper
           # x509.certificate.mapper.id=ldapMapper
           com.mycompany.LdapMapper

Example server.xml configuration for two separate X509CertificateMapper implementations to a basic and LDAP user registry:

          <server>
              <featureManager>
                  <feature>basicRegistry-1.0</feature>
                  <feature>ldapRegistry-3.0</feature>
                  <feature>bells-1.0</feature>
              </featureManager>

              <!--
                      The library contains any X509CertificateMapper implementations.
               -->
              <library id="mylibrary">
                  <file name="${shared.resource.dir}/libs/myLibrary.jar" />
              </library>

              <!--
                      Bundle the library using the BELLS feature.
               -->
              <bell libraryRef="mylibrary" />

              <!--
                      Reference the X509CertificateMapper(s) from the user registries by configuring the
                      certificateMapMode attribute to "CUSTOM" and referencing the ID configured in the
                      provider configuration file in the certificateMapperId attribute.
               -->
              <basicRegistry ... certificateMapMode="CUSTOM" certificateMapperId="basicMapper" />
              <ldapRegistry ... certificateMapMode="CUSTOM" certificateMapperId="ldapMapper" />
          </server>

Enabling the custom mapping with a user feature

Implement the com.ibm.websphere.security.X509CertificateMapper interface and include it in the user feature bundle. Define the X509CertificateMapper implementations as Service Components. The Service Component must specify the x509.certificate.mapper.id property which defines a unique ID as the value. The property can either be specified manually in the Service Component XML file or using the property field of the Component annotation. Load these implementations into Liberty’s classpath with the user feature. Use this ID to reference the implementation from the server.xml configuration file.

Example server.xml configuration for configuring two separate X509CertificateMapper implementations to a basic and LDAP user registry:

          <server>
              <featureManager>
                  <feature>basicRegistry-1.0</feature>
                  <feature>ldapRegistry-3.0</feature>
                  <feature>usr:myFeature-1.0</feature>
              </featureManager>

              <!--
                      Reference the X509CertificateMapper(s) from the user registries by configuring the
                      certificateMapMode attribute to "CUSTOM" and referencing the ID configured in the
                      Service Component in the certificateMapperId attribute.
               -->
              <basicRegistry ... certificateMapMode="CUSTOM" certificateMapperId="basicMapper" />
              <ldapRegistry ... certificateMapMode="CUSTOM" certificateMapperId="ldapMapper" />
          </server>

For more info:

Ready to give it a try?

Download Open Liberty
Ask a question on Stack Overflow
Share this post: