Differences between Jakarta EE 10 and 9.1

If you are updating your application from using Jakarta EE 9.1 features to using Jakarta EE 10 features, changes in API behavior might require you to update your application code. These changes apply to several Jakarta EE APIs and the Open Liberty features that support them.

The following sections describe updates for different Jakarta EE 10 features

Global differences between Jakarta EE 10 and 9.1

The following changes apply across the Jakarta EE 10 platform.

Java SE requirement

Jakarta EE 9.1 features can run with Java SE versions 8 and later. All Jakarta EE 10 features require Java 11 or later, as outlined by the Jakarta EE 10 specification.

New Core Profile

Jakarta EE 10 introduces a new profile called Core Profile. The Liberty features that provide the Core Profile function are Jakarta Contexts and Dependency Injection 4.0 (cdi-4.0), Jakarta JSON Binding 3.0 (jsonb-3.0), Jakarta JSON Processing 2.1 (jsonp-2.1), and Jakarta RESTful Web Services 3.1 (restfulWS-3.1). No convenience feature is provided for Core Profile. However, you can easily enable all Jakarta 10 Core Profile features by including both the restfulWS-3.1 (which includes both cdi-4.0 and jsonp-2.1) and jsonb-3.0 Liberty features in your server.xml file.

XML Binding APIs availability

Several Jakarta EE 9.1 Liberty features include a dependency on the Jakarta XML Binding 3.0 (xmlBinding-3.0) feature, even though the specification doesn’t call for those features to depend on or expose XML Binding APIs. Furthermore, many of these features are part of the Jakarta Web Profile subset of features, which does not include the XML Binding feature.

The following Jakarta EE 10 Liberty features do not expose the XML Binding 4.0 APIs where their equivalent Jakarta EE 9.1 features expose the XML Binding 3.0 APIs:

For Open Liberty applications that require the XML Binding APIs, you must now add the Jakarta XML Binding 4.0 (xmlBinding-4.0) Liberty feature to your server.xml file.

Admin REST Connector availability

The Jakarta EE Platform 9.1 (jakartaee-9.1) Liberty convenience feature includes the Admin Rest Connector 2.0 (restConnector-2.0) Liberty feature. The Jakarta EE Platform 10.0 (jakartaee-10.0) Liberty convenience feature does not include this Liberty feature.

If you use the jakartaee-10.0 convenience feature and your application requires the Admin Rest Connector function, you must add the restConnector-2.0 feature to your server.xml file.

Connectors Inbound Security replacement

In Jakarta EE 10, the combination of the Jakarta Connectors 2.1 (connectors-2.1) and Application Security 5.0 (appSecurity-5.0) Liberty features replaces what the Jakarta Connectors Inbound Security 2.0 (connectorsInboundSecurity-2.0) Liberty feature provided in Jakarta EE 9.1.

JSON Web Token (JWT) feature changes

When you enable the JSON Web Token 1.0 (jwt-1.0) Liberty feature with Jakarta EE 10 Liberty features, the Servlet APIs are no longer available by default. For Open Liberty applications that require Servlet APIs, you must add the Jakarta Servlet 6.0 (servlet-6.0) feature to your server.xml file.

Similarly, the com.ibm.wsspi.rest.handler, com.ibm.wsspi.rest.handler.helper, and com.ibm.wsspi.wab.configure SPIs are no longer available to user features when the jwt-1.0 feature is enabled with Jakarta EE 10 Liberty features. For Open Liberty user features that require these SPIs, you must add the com.ibm.websphere.appserver.restHandler-1.0 or com.ibm.wsspi.appserver.webBundle-1.0 feature to your user feature mf file.

Differences between Jakarta Authentication 3.0 and 2.0

The Jakarta Authentication 3.0 feature (appAuthentication-3.0) introduces changes to the jakarta.security.auth.message.config.AuthConfigFactory abstract class. This class implements the following two new methods to register and remove a server authentication module.

  • public abstract String registerServerAuthModule(ServerAuthModule serverAuthModule, Object context);

  • public abstract void removeServerAuthModule(Object context);

In previous versions of the feature, support was available to register and remove only a configuration provider.

For more information, see the Jakarta Authentication 3.0 Javadoc.

Differences between Jakarta Authorization 2.1 and 2.0

The Jakarta Authorization 2.1 feature (appAuthorization-2.1) introduces the following new methods.

New methods for the jakarta.security.jacc.PolicyConfigurationFactory abstract class

The jakarta.security.jacc.PolicyConfigurationFactory abstract class implements the following two new methods to retrieve the Policy Configuration interface (PolicyConfiguration):

  • public abstract PolicyConfiguration getPolicyConfiguration();

  • public abstract PolicyConfiguration getPolicyConfiguration(String contextID);

These methods are available in addition to the following getPolicyConfiguration method that was available in previous versions.

public abstract PolicyConfiguration getPolicyConfiguration(String contextID, boolean remove);

New methods for the jakarta.security.jacc.PolicyConfiguration interface

The jakarta.security.jacc.PolicyConfiguration interface defines three new methods to read permissions:

  • public abstract Map<String, PermissionCollection> getPerRolePermissions();

  • public abstract PermissionCollection getUncheckedPermissions();

  • public abstract PermissionCollection getExcludedPermissions();

For more information, see the Jakarta Authorization 2.1 Javadoc.

Differences between Jakarta Batch 2.1 and 2.0

The updates in Jakarta Batch 2.1 primarily focus on improved integration with Context Dependency Injection (CDI). The discovery of Batch artifacts is now standardized with CDI, which was not fully defined in the specification previously.

Updates for the @BatchProperty annotation

The @BatchProperty annotation is expanded to enable the injection of the following types: Boolean, Short, Integer, Long, Float, and Double. Previously, this annotation could inject only a String value. The following example demonstrates the newly added injection types:

@Inject @BatchProperty(name="b1") Boolean b1;
@Inject @BatchProperty(name="s1") Short s1;
@Inject @BatchProperty(name="i1") Integer i1;
@Inject @BatchProperty(name="l1") Long l1;
@Inject @BatchProperty(name="f1") Float f1;
@Inject @BatchProperty(name="d1") Double d1;

Default injection for the JobOperator interface

Previously, the default JobOperator interface was made available only from the BatchRuntime.getJobOperator() static factory method. In Jakarta Batch 2.1 and later, if an injection point for a JobOperator interface exists and no user-supplied implementation is found, the default JobOperator instance is injected automatically. The following example demonstrates the default injection for the JobOperator interface:

@Inject JobOperator jobOperator;

Differences between Jakarta Contexts and Dependency Injection 4.0 and 3.0

The Jakarta Contexts and Dependency Injection 4.0 feature (cdi-4.0) introduces build compatible extensions and observable container state events. It also changes how empty and unversioned beans.xml files are handled. Several previously deprecated APIs are removed in this release.

Build compatible extensions

CDI provides portable extensions to customize the CDI application initialization lifecycle. In CDI 4.0, build compatible extensions make implementing extensions amenable to build-time processing.

To implement a build compatible extension, provide an implementation of the BuildCompatibleExtension interface that is declared in the META-INF/services directory. The implementation can provide methods that are annotated with one of the following extension annotations, each of which corresponds to an extension execution phase:

  • @Discovery

  • @Enhancement

  • @Registration

  • @Synthesis

  • @Validation

For example, as part of the Enhancement phase, the implementation in the following example adds a 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 available in CDI 4.0: Startup and Shutdown. Applications can listen for these events to be notified when the CDI container is starting up or shutting down. The following example listens for Startup and Shutdown events and prints a notification for each to the console when it receives the event:

@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 among multiple observable container state methods by using the @Priority annotation.

The bean-discovery-mode attribute in empty and non-empty beans.xml files

In CDI 4.0, a beans.xml file that does not specify the bean-discovery-mode attribute is treated as if the attribute is set to bean-discovery-mode="annotated". In CDI 3.0 and earlier, a beans.xml file that does not specify the bean-discovery-mode attribute is treated as if the attribute is set to bean-discovery-mode="all". These settings apply to both empty and non-empty beans.xml files.

For an empty beans.xml file in CDI 4.0, you can set the emptyBeansXmlCDI3Compatibility attribute for the cdi element to enable compatibility with previous versions. If you set this attribute to true in your server.xml file, any archives that contain an empty beans.xml file are treated as explicit beans archives. For more information, see Server.xml configuration element and attribute updates.

The best practice is to always specify a version for non-empty beans.xml files, as shown in the following 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

In CDI 4.0, a new Handle API is available to simplify the programmatic inspection of bean metadata. This API avoids the need to create instances before they are required. You can obtain a Handle instance by using the Instance API, which uses the following syntax:

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

Removed APIs

The following previously deprecated CDI APIs are removed in CDI 4.0:

  • @New qualifier, which replaced by @Dependent beans.

  • Bean#isNullable(), not used by the implementation since CDI 1.1.

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

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

Server.xml configuration element and attribute updates

In the Liberty Jakarta Contexts and Dependency Injection 4.0 feature, the cdi12 configuration element is superseded by the cdi element, which applies to CDI versions 1.2 and later. The following server.xml file example shows the cdi element with two configuration attributes:

<cdi enableImplicitBeanArchives="false" emptyBeansXmlCDI3Compatibility="true"/>

The enableImplicitBeanArchives attribute works the same as it did with the cdi12 element in previous versions. If this attribute is set to true, which is the default, then archives with no beans.xml file are treated as implicit bean archives and scanned for classes that have bean-defining annotations. If this attribute is 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 this attribute is set to true, 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 this attribute set to false, which is the default, then an archive that contains an empty beans.xml file is treated as an implicit bean archive.

Differences between Jakarta Expression Language 5.0 and 4.0

The Jakarta Expression Language 5.0 feature adds support for Java Generics and includes updates to type coercion, the Expression Language resolver, and more.

Support for Java Generics

The 5.0 release adds support for Java Generics throughout the API, wherever they are appropriate. This update removes the need to cast from an Object instance to a specific object type in many API calls.

Type coercion

The 5.0 release implements support for coercing Lambda Expressions to a functional interface method invocation and clarifies the specification for coercing arrays. However, Liberty use of the Tomcat API and implementation of the Expression Language specification already followed these clarifications to the specification for coercing arrays. Therefore, no functional changes for array coercion are added in the Expression Language 5.0 feature.

Expression Language resolver

The BeanELResolver class is updated to also consider default method implementations when it looks for property getters, property setters, and methods. The documented behavior of the StaticFieldELResolver class is updated to explicitly document that the ELResolver.getType() method must return null if either the ELResolver class or the resolved property is read-only.

Method annotation access

A new MethodReference class provides access to details of the method to which a MethodExpression instance resolves, including any annotations that are present on the method.

Deprecations and removals

The ELResolver getFeatureDescriptors() method is deprecated in Expression Language 5.0, with removal planned for Expression Language 6.0. A new default implementation that returns null is added. This update ensures that custom ELResolver implementations do not need to implement the method.

The deprecated and misspelled MethodExpression.isParmetersProvided() method is removed from the API.

For more information, see the Jakarta Expression Language 5.0 Javadoc.

Differences between Jakarta Faces 4.0 and 3.0

The Jakarta Faces 4.0 feature introduces programmatic creation of Facelets, automatic extensionless mapping, and numerous improvements and removals.

Programmatically create Facelets

As of the 4.0 release, Facelets no longer need to exist as XML files and can now be programmatically created with Java. For an example, see this specification issue.

Map to Facelets without specifying an extension

You can now configure Facelets to be reached without any extensions by setting the jakarta.faces.AUTOMATIC_EXTENSIONLESS_MAPPING context parameter to true. For example, when this parameter is set to true, the somePage.xhtml facelet can be reached by specifying <context-root>/somePage because the FacesServlet class maps to the `/somePage`instance automatically.

New attributes

<f:websocket onerror="…">

It was reported that the onclose attribute was sometimes not enough for reporting errors, so this onerror attribute was added to handle any unexpected errors that occur on the WebSocket connection.

<h:inputFile accept="…">

Use this attribute to specify the comma-separated string of mime file types that the client file browser filters through.

<h:inputFile multiple="…">

Use this attribute to upload multiple files with the multiple HTML attribute.

<h:inputText type="…">

This attribute enables HTML5 input types, such as email, date, tel, and many others.

New tags

<f:selectItemGroups>

This tag renders multiple optgroup elements so you can offer a nested collection of option elements. For more information about outgroup elements, see <optgroup>: The Option Group element.

<f:selectItemGroup>

This tag is similar to the <f:selectItemGroups> tag but allows only one optgroup to be rendered.

New methods

FacesContext#getLifecycle()

This method is a convenience method to determine the current phase of the Faces lifecycle.

UIViewRoot#getDoctype()

This method returns the declared DOCTYPE of the Facelet.

New context parameters

jakarta.faces.AUTOMATIC_EXTENSIONLESS_MAPPING

This parameter enables automatic mapping to a Facelet without specifying an extension. The default value is false.

jakarta.faces.NUMBER_OF_CLIENT_WINDOWS

This parameter sets the maximum number of ClientWindows instances, which is used by the ClientWindowScoped annotation. The default value is 10. This parameter can be used only when the jakarta.faces.CLIENT_WINDOW_MODE parameter is enabled.

org.apache.myfaces.USE_LAMBDA_METAFACTORY

Although not specification-defined, this experimental MyFaces parameter allows lambdas to be used for the setting and getting of bean properties, rather than reflection. Lambdas offer significant performance improvement over reflection. If any problems arise, an error is logged and the traditional lookup is used as a fallback to prevent the application from breaking.

Annotation updates

@ClientWindowScoped

A new CDI scope is added that allows classes with this annotation to live for the current ClientWindow, which is enabled by setting the javax.faces.CLIENT_WINDOW_MODE parameter to url mode. In other words, the classes are active when the jfwid request parameter is first used and reused across faces link components.

This annotation is similar to the FlowScope annotation but more flexible, because it is not limited to a subset of pages. Faces limits the number of Client Windows with the jakarta.faces.NUMBER_OF_CLIENT_WINDOWS parameter, which has a default value of 10.

Addition of annotation literals for all @Qualifiers

With this change, you no longer need to create your own annotation literals. Now you can easily retrieve Faces-specific instances with the CDI API, as shown in the following example:

Map<String, Object> requestMap = CDI.current().select(new TypeLiteral<Map<String, Object>>() {}, RequestMap.Literal.INSTANCE).get();

URI updates

The http://xmlns.jcp.org/jsf/* URIs are updated to the jakarta.faces.* URN. For example, any URI in the http://xmlns.jcp.org/jsf/* pattern now uses the jakarta.faces.* URN pattern and any URI in the http://xmlns.jcp.org/jsp/jstl/* pattern now uses the jakarta.tags.* URN pattern. However, Faces 4.0 is still compatible with the older URIs.

Other improvements and updates

  • The term JSF is changed to Faces throughout the code. This change includes renames such as jsf.js to faces.js, window.jsf to window.faces, and xmlns:jsf to xmlns:faces. For more information, see this specification issue.

  • The list layout, layout="list", was added to the <h:selectManyCheckbox> and <h:selectOneRadio> tags. This new layout allows easier CSS control because the HTML is generated with <ul> and <li> elements rather than the outdated <table> and associated elements.

  • The UIComponent#subscribeToEvent() method is now more convenient. The 4.0 spec mandates that listeners can no longer be added twice, and that the UIComponent#getListenersForEventClass() method must not return null.

  • The type attribute is skipped for <link> and <script> elements when the doctype is HTML5 because the type is already implied.

  • The <f:ajax> behavior is improved for composite components when it is used with the @this keyword. The following statement was added to the specification: When nested within a composite component, and the value contains or implies the keyword @this, then the keyword must be remapped to the targets attribute of the associated <composite:clientBehavior> declaration. For more information, see the execute attribute for the ajax tag and this specification issue.

  • The ExternalContext#addResponseCookie() method now supports custom cookie attributes, such as SameSite. This support is provided by the Servlet 6.0 jakarta.servlet.http.Cookie#setAttribute() method.

  • MyFaces updated its JavaScript implementation to the newer ECMAScript 2015 (ES6) standard. Be aware that older browsers, such as Internet Explorer, do not support the newer syntax. Automation tools for testing, such as HTMLUnit, also might encounter errors.

Removals

Although the 4.0 release includes no new deprecations, many previously deprecated methods and classes are removed. Links for the following removals reference the Faces 3.0 API Docs for convenience as these are removed from Faces 4.0.

  • Pages (formerly JSP) support is removed entirely. Pages (JSP) can no longer be used as a view technology. Only Facelets are supported.

  • Native Managed Bean support and the related code is removed. You must now switch to CDI.

  • MethodBinding, ValueBinding, and related fields and classes are removed. You must switch to the Expression Language equivalents, such as MethodBind to MethodExpression and PropertyResolver to ELResolver. See the Faces 3.0 API for migration assistance.

  • The CURRENT_COMPONENT and CURRENT_COMPOSITE_COMPONENT constants are removed from the UIComponent class. Use the UIComponent#getCurrentComponent() and UIComponent#getCurrentCompositeComponent() utility methods instead.

  • The deprecated StateManger methods are removed. See the Faces 3.0 API notes for the StateManger for migration assistance.

  • The ResourceResolver class is removed. Use the ResourceHandler class instead, as it can perform the same functions. See the Faces 3.0 API docs for ResourceResolver for migration assistance.

  • The PreJsf2ExceptionHandlerFactory class is removed.

For all other non-specification changes, see the MyFaces release notes.

Differences between Jakarta Mail 2.1 and 2.0

The Jakarta Mail 2.1 feature introduces the jakarta.mail.util.StreamProvider interface. This new interface from the Mail 2.1 specification makes it possible to obtain a StreamProvider instance, which provides access to the encoders and decoders that are supported by the mail-2.1 runtime. You can obtain instances of the StreamProvider from the jakarta.mail.Session.getStreamProvider() method.

For more information, see the Jakarta Mail 2.1 specification.

Differences between Jakarta RESTful Web Services 3.1 and 3.0

The Jakarta Restful Web Services 3.1 feature introduces default support to send and receive multipart/form-data parts. It also introduces automatic service provider registration, a default exception mapper, and support for array types as parameters in field and bean property annotations, among other changes.

Support for multipart/form-data media types

In previous versions, support for sending and receiving multipart/form-data parts was provided by the Liberty-specific IAttachment and IMultipartBody APIs, which are deprecated in this release. This support is now provided by the EntityPart API that is defined in the RESTful Web Services specification. For more information, see section 3.5.2 of the Jakarta Restful Web Services specification.

Global Handlers

In previous Liberty feature versions of RESTful Web Services (JAXRS) and XML Web Services (JAXWS), the com.ibm.wsspi.webservices.handler Web Services Global Handler SPI package was automatically enabled.

Starting in Jakarta EE 10, Global Handlers are disabled by default. As with previous versions, you must create a user feature to configure a Global Handler. However, as of this release, you must also add the io.openliberty.globalhandler-1.0 protected Liberty feature to your user feature manifest file to enable the SPI package.

Add io.openliberty.globalhandler-1.0; type="osgi.subsystem.feature" to your user feature manifest file, as shown in the following manifest file example:

Manifest-Version: 1.0
Subsystem-Type: osgi.subsystem.feature
IBM-Feature-Version: 2
Subsystem-Version: 1.0.0
Subsystem-Content: MySimpleGlobalHandler.jakarta;version="1.0.0",
io.openliberty.globalhandler-1.0; type="osgi.subsystem.feature"
Subsystem-SymbolicName: MySimpleGlobalHandlerFeature;visibility:=public
Subsystem-ManifestVersion: 1.0
IBM-ShortName: MySimpleGlobalHandlerFeature

If you see an error message in your logs that is similar to the following example, you need to add the io.openliberty.globalhandler-1.0 feature to your user feature manifest file:

CWWKE0702E: Could not resolve module: MySimpleGlobalHandler.jakarta [142]
Unresolved requirement: Import-Package: com.ibm.wsspi.webservices.handler

Servlet APIs availability

When previous Liberty feature versions of RESTful Web Services (JAXRS) and RESTful Web Services Client were enabled, the Servlet APIs were available to any Open Liberty application by default.

Starting with RESTful Web Services 3.1 and RESTful Web Services Client 3.1, the Servlet APIs are no longer available by default when you enable these features. For Open Liberty applications that require Servlet APIs, you must also add the servlet-6.0 feature to the server.xml file.

Concurrency APIs availability

When the restfulWS-3.0 and restfulWSClient-3.0 Liberty features are enabled, the Concurrency APIs are available to any Open Liberty application by default.

Starting with RESTful Web Services 3.1 and RESTful Web Services Client 3.1, the Concurrency APIs are no longer available by default. For Open Liberty applications that require Concurrency APIs, you must also add the concurrent-3.0 feature to the server.xml file.

Automatic service provider registration

With the service loader, Jakarta Rest providers can now be detected and registered automatically, unless the jakarta.ws.rs.loadServices property is set to Boolean.FALSE by using an application subclass getProperties() method. For more information, see section 4.1.2 of the Jakarta Restful Web Services specification.

Default exception mapper

A default exception mapper is added in version 3.1. With this addition, all exceptions that are not mapped to an existing exception mapper are handled. If the exception is a WebApplicationException exception, the response object is returned with whatever status code is set. For all other unmapped exceptions, the response status code is set to 500.

Field and bean property annotations

Support for array types as parameters is added to the following field and bean property annotations:

  • @CookieParam

  • @FormParam

  • @HeaderParam

  • @MatrixParam

  • @QueryParam

Response.created(URI) method

The Response.created(URI) method now resolves relative URIs into an absolute URI against the base URI. In previous releases, the method resolved against the request URI.

Constructors of the Cookie class are deprecated in favor of the Cookie.Builder class. Constructors of the NewCookie class are deprecated in favor of the NewCookie.Builder class.

Differences between Jakarta Security 3.0 and 2.0

In Open Liberty, the Jakarta Security 3.0 specification is supported by the Application Security 5.0 feature. This feature introduces a new @OpenIdAuthenticationMechanismDefinition annotation to configure a built-in OpenID Connect authentication mechanism. This authentication mechanism functions as an OpenID Connect client, or Relying Party (RP), so that you can use an OpenID Connect Provider(OP) as a single sign-on identity provider. It also introduces the OpenIdContext bean and various APIs for handling the access token, identity token, and refresh token.

Differences between Jakarta Server Pages and 3.1 and 3.0

The Jakarta Server Pages 3.1 feature provides support for the Jakarta Server Pages 3.1 and Jakarta Standard Tag Library 3.0 specifications. This release includes updates for Expression Language identifiers and resolvers, new tag URIs, and more.

Finding unknown identifiers

This release adds a new option to find unknown Expression Language identifiers. When this option is enabled, a PropertyNotFoundException occurs if an unknown identifier is found. Previously, unknown identifiers were rendered as empty strings ("") and were difficult to identify. You can enable this option by using page directives, tag directives, or as a JSP Property Group in the web.xml file.

To enable this option by using page or tag directives, set the errorOnELNotFound attribute to true, as shown in the following example:

<%@ page errorOnELNotFound="true" %>

To enable this option by using a JSP Property Group in the web.xml file, set the error-on-el-not-found element to true, as shown in the following example:

<jsp-property-group>
   <url-pattern>*.jsp</url-pattern>
   <error-on-el-not-found>true</error-on-el-not-found>
</jsp-property-group>

For more information, see Unknown EL Identifiers in the Jakarta Server Pages specification.

New Expression Language Resolvers

Expression Language Resolvers are updated to improve handling of imports and unresolved variables. Two new resolvers are available in this release:

ImportELResolver

This new import resolver, which was refactored from the ScopedAttributeELResolver class, makes any class or package imports from the import attribute available to the expression language environment. Previously, imports were available only to the scripting environment and if an expression used an import class, it resolved to an empty string. For more information, see ImportELResolver.

NotFoundELResolver

This resolver always resolves a variable when other resolvers do not. It returns null by default, but you can alter this behavior by using the previously mentioned error-on-el-not-found element. For more information, see NotFoundELResolver.

Import updates

Default and implicit imports for the scripting environment now also apply to the expression language environment. These default imports are java.lang.*, jakarta.servlet.*, jakarta.servlet.jsp.*, and jakarta.servlet.http.*.

Namespace updates

The Jakarta Tag URIs now use the jakarta.tags.* pattern. Although support for the previous http://xmlns.jcp.org/jsp/jstl/* pattern is maintained for compatibility with earlier versions, it is recommended to update your applications to use these new URIs. The following example shows the taglib directive with the new URIs:

<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<%@ taglib prefix="x" uri="jakarta.tags.xml" %>
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
<%@ taglib prefix="fn" uri="jakarta.tags.functions" %>"
<%@ taglib prefix="sql" uri="jakarta.tags.sql" %>

For more information, see the Jakarta Tags doc.

Deprecations

The isThreadSafe directive is deprecated due to the removal of the SingleThreadModel interface in the Servlet 6.0 API. A workaround is implemented, but significant performance impacts might occur. Use of the isThreadSafe directive in Pages 3.1 is discouraged.

The jsp:plugin, jsp:params, and jsp:fallback actions are deprecated and are not operational. Current browsers no longer support the elements that are generated by the jsp:plugin and related actions.

Differences between Jakarta Servlet 6.0 and 5.0

The Jakarta Servlet 6.0 feature (servlet-6.0) provides new APIs and new configurations to set attributes on a response cookie.

In Jakarta Servlet 6.0, you can set attributes on a response cookie either from a deployment descriptor file, at application startup with the jakarta.servlet.ServletContainerInitializer API, or at request time.

To set cookie attributes in a web.xml deployment descriptor file, specify the attribute element within the cookie-config element, as shown in the following example:

<session-config>
   <cookie-config>
     <name>SampleCookieName</name>
     <domain>my.domain.com</domain>
     <path>/</path>
     <http-only>true</http-only>
     <secure>true</secure>
     <attribute>
        <attribute-name>MyAttributeName</attribute-name>
        <attribute-value>valueExample</attribute-value>
     </attribute>
     <attribute>
        <attribute-name>MyOtherAttribute</attribute-name>
        <attribute-value>OtherValue</attribute-value>
     </attribute>
   </cookie-config>
</session-config>

You can also set cookie attributes dynamically from an application during application startup by using the jakarta.servlet.ServletContainerInitializer API, as shown in the following example:

@Override
public void onStartup(Set<Class<?>> setOfClasses, ServletContext context) throws ServletException {
      SessionCookieConfig scc = context.getSessionCookieConfig();
      scc.setName("MyDynaCookieName");
      scc.setAttribute("MyDynamicAttribute", "DynamicValue");
      ...
}

Alternatively, you can set attributes from the application at request time, as shown in the following example:

SessionCookieConfig scc = getServletContext().getSessionCookieConfig();
scc.setName("MyRequestCookieName");
scc.setAttribute("MyRequestAttribute", "RequestValue");

If conflicts arise among different sources for the cookie configuration, the following precedence order applies to resolve the conflict, from highest to lowest precedence:

  1. Attributes that are set by the application at request time

  2. Attributes that are set by the application by using the ServletContainerInitializer API

  3. Attributes that are set in the web.xml deployment descriptor file

Servlet 6.0 implements the HTTP request cookie behavior by following the rfc6265 standard, which states that HTTP client agents such as browsers do not send back cookie attributes to the application server.

Previously, you could include request cookie attributes by adding the dollar sign ($) as a prefix to a valid attribute name. For example, $Domain=myDomain.com was treated as the Domain attribute for the request cookie. Starting in Servlet 6.0, $Domain is treated as a new cookie that is named $Domain. The dollar sign is also part of the cookie name. The only exception to this rule is the $Version value.

For example, consider the following HTTP request, which includes a cookie header:

Cookie: $Version=1; name1=value1; $Path=/Dollar_Path; $Domain=localhost; $NAME2=DollarNameValue;Domain=DomainValue

Before Servlet 6.0, the server created the following three request cookies from this request:

cookie1: name1 with the associated attributes: Path=/Dollar_Path; Domain=localhost
cookie2: NAME2
cookie3: Domain

In Servlet 6.0 and later, the server creates the following five request cookies from the same HTTP request:

cookie1: name1
cookie2: $Path
cookie3: $Domain
cookie4: $NAME2
cookie5: Domain

Application debug enhancements

New jakarta.servlet.ServletRequest APIs and a new jakarta.servlet.ServletConnection class are available to help you debug requests to your application. With the enhancement, you can track or refer to a request or obtain details of the network connection that is used by the request by using the request ID.

The following Jakarta.servlet.ServletRequest APIs are available in Servlet 6.0:

  • String getRequestId()

  • String getProtocolRequestId()

  • ServletConnection getServletConnection()

A new jakarta.servlet.ServletConnection object is retrieved from the getServletConnection() servlet request. It includes the following APIs:

  • String getConnectionId()

  • String getProtocol()

  • String getProtocolConnectionId()

  • boolean isSecure()

URI Path Verification

Beginning with the Servlet 6.0 release, if any of the following sequences are present in a URI, a direct request is rejected with a 400 Bad Request status:

  • The encoded dot (%2E) character

  • The encoded forward-slash (%2F) character

  • The fragment (#) character, whether encoded (%23) or not

  • The back-slash character (\), whether encoded (%5C) or not

  • Any control characters, whether encoded or not

  • Any period (.) or double-period (..) segment that has a path parameter (;), for example /path/..;/info

  • Any path that starts with a double-period (..), for example /../path/info

Note: the URI path verification is not applied to the query string.

You can skip the verification of encoded characters by setting the skipEncodedCharVerification property true. The default value is false.

To opt out of the encoded characters verification in the request URI for a servlet, you can configure this property as a context-param element in the application web.xml file.

<context-param>
   <param-name>SKIP_ENCODED_CHAR_VERIFICATION</param-name>
   <param-value>true</param-value>
</context-param>

Alternatively, you can set it as an attribute for the webContainer element in the server.xml file to skip the verification for all deployed applications.

<webContainer skipEncodedCharVerification="true"/>

The application-level context-param setting takes precedence over the server-level webContainer setting.

X-Powered-By response header

By default, the X-Powered-By header is not included in the response header. Beginning with Servlet 6.0, no configuration option is available to add the X-Powered-By header to the response header.

Removed APIs and classes

The following previously deprecated APIs and their corresponding constructors and methods are removed:

  • jakarta.servlet.ServletContext - Servlet getServlet(String), Enumeration<Servlet> getServlets(), Enumeration<String> getServletNames(), void log(Exception, String)

  • jakarta.servlet.ServletRequest - String getRealPath(String)

  • jakarta.servlet.ServletRequestWrapper - String getRealPath(String)

  • jakarta.servlet.UnavailableException - UnavailableException(Servlet, String), Servlet getServlet()

  • jakarta.servlet.http.HttpServletRequest - boolean isRequestedSessionIdFromUrl()

  • jakarta.servlet.http.HttpServletRequestWrapper - boolean isRequestedSessionIdFromUrl()

  • jakarta.servlet.http.HttpServletResponse - String encodeUrl(String), String encodeRedirectUrl(String), void setStatus(int, String)

  • jakarta.servlet.http.HttpServletResponseWrapper - String encodeUrl(String), String encodeRedirectUrl(String), v`oid setStatus(int, String)`

  • jakarta.servlet.http.HttpSession - HttpSessionContext getSessionContext(), Object getValue(String), String[] getValueNames(), void putValue(String, Object), void removeValue(String)

The following previously deprecated classes are removed:

  • jakarta.servlet.SingleThreadModel

  • jakarta.servlet.http.HttpSessionContext

  • jakarta.servlet.http.HttpUtils

For more information, see the Jakarta Servlet 6.0 Javadoc.

Differences between Jakarta WebSocket 2.1 and 2.0

The Jakarta WebSocket 2.1 feature implements changes for specification APIs and methods. It also includes updates to the handling of user properties and the setting of the client SSL context.

API replacement for the WsWsocServerContainer#upgrade SPI

In Jakarta WebSocket 2.1, you can programmatically upgrade your HTTP requests to a WebSocket connection by using the new jakarta.websocket.server.ServerContainer#upgradeHttpToWebSocket() API method. This method replaces the com.ibm.websphere.wsoc.WsWsocServerContainer SPI, which is now deprecated, with plans to remove it in the next WebSocket release. However, this SPI is still available with the Jakarta WebSocket feature version 2.0 and earlier.

Updates for the handling of user properties

The WebSocket 2.1 release includes changes for user properties. The user properties for server sessions are initially populated by the ServerEndpointConfig.getUserProperties() method. This method enables endpoints to retrieve properties that might be set in an overridden ServerEndpointConfig.Configurator#modifyHandshake call for the incoming request​.

Similarly, user properties for client sessions are populated with the EndpointConfig.getUserProperties() method. These initial contents are shallow copies, which means that ClientEndpointConfig#getUserProperties and ServerEndpointConfig#getUserProperties() instances are now handled per endpoint, per WebSocket session. Properties are no longer global between all endpoint instances as they were in previous WebSocket versions.

Client SSL configuration

Starting with WebSocket 2.1, applications can set their SSLContext class by using a jakarta.websocket.ClientEndpointConfig.Builder#sslContext​ instance, which Liberty uses to establish the wss connection to a server. This option overrides all Liberty server SSL configurations and must be used with caution. It is recommended to enable SSL communication in the server.xml file by enabling the Transport Security feature. Also, you can configure SSL by setting the WAS WebSocket Outbound element in the server.xml file.

Other changes

The following changes are effective starting with WebSocket 2.1.

For more information, see the Jakarta WebSocket 2.1 specification.

Differences between Jakarta XML Binding 4.0 and 3.0

The Jakarta XML Binding 4.0 feature gives you the option to switch to a third-party implementation and removes support for the Validator API.

Switch to a third-party implementation

In Jakarta XML Binding 4.0, you can specify the jakarta.xml.bind.JAXBContextFactory property to switch to a preferred third-party implementation. The xmlBinding-4.0 feature then uses the specified implementation instead of the reference implementation. Consider the following notes when you choose a third-party implementation.

If you set the jakarta.xml.bind.JAXBContextFactory property, you must add the specified third-party implementation to the application class path. Otherwise, a java.lang.ClassNotFoundException exception occurs. Furthermore, the third-party implementation must be shared between all applications that are running on the JVM. Any application that is running on the JVM that does not have the implementation added to its class path encounters a java.lang.ClassNotFoundException exception.

Removal of the Validator API

The xmlBinding-4.0 feature does not support the jakarta.xml.bind.Validator APIs. Any application that uses this API must either remove it or replace it with a SchemaValidation instance. The following examples demonstrate how to use a SchemaValidation instance as a replacement for a Validator API:

SchemaFactoryschemaFactory= SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema dataObjectSchema= schemaFactory.newSchema(new File("dataObjectSchema.xml")); jaxbUnmarshaller.setSchema(dataObjectSchema)

For more information, see the Jakarta XML Binding 4.0 specification.

Differences between Jakarta XML Web Services 4.0 and 3.0

The Jakarta XML Web Services 4.0 feature includes changes for Global Handlers and the Jakarata Web Services Metadata specification. It also removes a previously deprecated class for the SOAP with Attachments 3.0 API, which is supported in Open Liberty by the Jakarta XML Web Services feature.

  • With the 4.0 release, the Jakarata Web Services Metadata specification is merged into the Jakarta Web Services specification. All the Jakarta Web Services APIs for Open Liberty are now included in the dev\api\spec\io.openliberty.jakarta.xmlWS.4.0…​jar file.

  • In Jakarta XML Web Services 4.0, and across the Jakarta EE 10 platform, Global Handlers are disabled by default. For more information, see Global Handlers.

  • In Open Liberty, the SOAP with Attachments 3.0 release coincides with the Jakarta XML Web Services 4.0 release. With this release, the previously deprecated SOAPElementFactory class of the SOAP with Attachments 3.0 API is removed.