diff --git a/posts/2026-04-07-26.0.0.4-beta.adoc b/posts/2026-04-07-26.0.0.4-beta.adoc index 2c379bd92..b7861c064 100644 --- a/posts/2026-04-07-26.0.0.4-beta.adoc +++ b/posts/2026-04-07-26.0.0.4-beta.adoc @@ -22,96 +22,18 @@ This beta introduces Jakarta EE 11 Platform and Web Profile, Jakarta Authenticat The link:{url-about}[Open Liberty] 26.0.0.4-beta includes the following beta features (along with link:{url-prefix}/docs/latest/reference/feature/feature-overview.html[all GA features]): - -* <> * <> -* <> -* <> +** <> +** <> +** <> * <> * <> -* <> -* <> +* <> +* <> See also link:{url-prefix}/blog/?search=beta&key=tag[previous Open Liberty beta blog posts]. -// // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // -// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34495 -// Contact/Reviewer: benjamin-confino, tbitonti -// // // // // // // // -[#jandex_index] -== Web module Jandex Indexes can be read from WEB-INF/classes. - -Before this update, within all modules, Jandex indexes were read-only from `META-INF/jandex.idx`. With this update, for web modules, Jandex indexes are also read from `WEB-INF/classes/META-INF/jandex.idx`. This update is consistent with industry practices. - -Jandex indexes from the prior location or from the new location are read-only if Jandex use is enabled. For compatibility with earlier versions, reads from the new location must be enabled by a new application property. - -=== Benefits - -* Improved Compatibility: Improve compatibility with industry standard practices. -* Faster Startup Times: Continue to benefit from Jandex's efficient annotation indexing. - -=== Target Persona - -Customers who wish to place Jandex indexes at industry standard locations in their web modules. - -=== Target Features - -This update applies to the scanning of classes within applications. Class scanning (which includes annotation scanning) is a general purpose function that is used by many features. - -=== Problem Description - -To gather information about application classes, including annotation data, the application classes must be scanned. This scan is expensive because the entire application must be read and processed. - -To improve performance, class scans can be done during application packaging, and the scan results are placed in an index within the application. Jandex provides this capability. - -Jandex scan results are usually written to "META-INF/jandex.idx". For JAR files, this location is relative to the root of the JAR file. For WAR files, the "META-INF/jandex.idx" location has two possible interpretations. First, the location can be relative to the root of the WAR file. Second, the location can be relative to the "WEB-INF/classes" folder. - -Before this update, Liberty used the location relative to the root of the WAR file. However, industry standards place the location relative to "WEB-INF/classes". This update enables Liberty to also use the "WEB-INF/classes" location. - -=== How to Use - -Support for reading Jandex indexes under WEB-INF/classes is enabled by a new property of application and application manager elements: - -* Property: *useJandexUnderClasses* -* Description: Enables use of a jandex index for WAR "WEB-INF/classes" under "/WEB-INF/classes/META-INF/jandex.idx". -* Possible values: true | *false* -* Default value: false - -For example: - -[source,xml] ----- - ----- - -Also for example: - -[source,xml] ----- - ----- - -When the new property is placed on an application manager element, the property applies to all web modules of all applications. When the new property is placed on an application element, the property applies to only that application. If the property is set on both the application manager element and an application element, the value on the application element overrides the value on the application manager element for that application. - -=== Limitation - -Jandex index support requires explicit enablement. See the property *useJandex* on application manager and on application elements. The new property *useJandexUnderClasses* is meaningful only if the property *useJandex* is *true*. - -For compatibility with an earlier versions, reads of jandex from the new location requires explicit enablement. See the new property *useJandexUnderClasses*, as documented previously. Explicit enablement is required to prevent applications from accidentally reading an out of date Jandex index from the new location. An out of date Jandex index might cause hard to detect application errors. - -The name of the new property, *useJandexUnderClasses*, is subject to revision. - -=== Learn More - -* link:https://smallrye.io/jandex/jandex/3.5.3/index.html[Jandex Documentation] -* link:https://openliberty.io/docs/latest/reference/config/applicationManager.html[Application Manager Documentation] -* link:https://openliberty.io/docs/latest/reference/config/applicationManager.html[Application Documentation] -* link:https://github.com/OpenLiberty/open-liberty/issues/34231[Open Liberty Jandex Index Format Update] - -// DO NOT MODIFY THIS LINE. - - // // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // // Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34471 @@ -120,15 +42,15 @@ The name of the new property, *useJandexUnderClasses*, is subject to revision. [#jakarta_ee] == Jakarta EE 11 Platform and Web Profile -Open Liberty 24.0.0.11-beta was one of the ratifying implementations for Jakarta EE 11 Core Profile. Building on that foundation, the 26.0.0.4-beta releases complete Jakarta EE 11 support, including Jakarta EE Application Client 11.0, Jakarta EE Web Profile 11.0, and Jakarta EE Platform 11.0. +Open Liberty 24.0.0.11-beta was one of the ratifying implementations for Jakarta EE 11 Core Profile. Building on that foundation, the 26.0.0.4-beta release completes Jakarta EE 11 beta support, including Jakarta EE Application Client 11.0, Jakarta EE Web Profile 11.0, and Jakarta EE Platform 11.0. Liberty provides convenience features that bundle all component specifications in the Jakarta EE Web Profile and Jakarta EE Platform. The `webProfile-11.0` Liberty feature includes all Jakarta EE Web Profile functions, including the new Jakarta Data 1.0 component. The `jakartaee-11.0` Liberty feature provides the Jakarta EE Platform version 11 implementation. For Jakarta EE 11 features in the application client, use the `jakartaeeClient-11.0` Liberty feature. -These convenience features enable developers to rapidly develop applications using all APIs in the Web Profile and Platform specifications. Unlike the `jakartaee-10.0` Liberty feature, the `jakartaee-11.0` Liberty feature does not enable Managed Beans feature, as this specification was removed from the platform and the `jakarta.annotation.ManagedBean` annotation was deprecated. Applications relying on `@ManagedBean` must migrate to CDI annotations. +These convenience features enable developers to rapidly develop applications using all APIs in the Web Profile and Platform specifications. Unlike the `jakartaee-10.0` Liberty feature, the `jakartaee-11.0` Liberty feature does not enable the Managed Beans specification function any longer, as this specification was removed from the platform which includes removal of the `jakarta.annotation.ManagedBean` annotation API. Applications relying on the `@ManagedBean` annotation must migrate to use CDI annotations. -The Jakarta EE 11 Platform specification removes all optional specifications from the platform, meaning Jakarta SOAP with Attachments, XML Binding, XML Web Services, and Enterprise Beans 2.x APIs functions are not included with the `jakartaee-11.0` Liberty feature. To use these capabilities, explicitly add Liberty features to your `server.xml` feature list: `xmlBinding-4.0` for XML Binding, `xmlWS-4.0` for SOAP with Attachments and XML Web Services, and `enterpriseBeansHome-4.0` for Jakarta Enterprise Beans 2.x API. Alternatively, use the versionless features with the `jakartaee-11.0` platform specification. +The Jakarta EE 11 Platform specification removes all optional specifications from the platform, meaning Jakarta SOAP with Attachments, XML Binding, XML Web Services, and Enterprise Beans 2.x APIs functions are not included with the `jakartaee-11.0` Liberty feature. To use these capabilities, explicitly add Liberty features to your `server.xml` feature list: `xmlBinding-4.0` for XML Binding, `xmlWS-4.0` for SOAP with Attachments and XML Web Services, and `enterpriseBeansHome-4.0` for Jakarta Enterprise Beans 2.x APIs. Alternatively, use the equivalent versionless features with the `jakartaee-11.0` platform specification. -When using the Liberty application client with the `jakartaeeClient-11.0` feature, Jakarta SOAP with Attachments, XML Binding, and XML Web Services client functions are not available. To continue using these functions in your Liberty application client, enable the `xmlBinding-4.0` and `xmlWSClient-4.0` features in your `client.xml` file. +When using the Liberty application client with the `jakartaeeClient-11.0` feature, Jakarta SOAP with Attachments, XML Binding, and XML Web Services client functions are not available. To continue using these functions in your Liberty application client, enable the `xmlBinding-4.0` and the new `xmlWSClient-4.0` features in your `client.xml` file. To enable the Jakarta EE 11 beta features in your Liberty server's `server.xml`: @@ -157,7 +79,7 @@ You can enable the Jakarta EE 11 features on the Application Client Container in ---- -For more information see the link:https://jakarta.ee/specifications/platform/11/jakarta-platform-spec-11.0[Jakarta EE Platform 11 Specification] and the link:https://jakarta.ee/specifications/webprofile/11/jakarta-webprofile-spec-11.0[Jakarta EE Web Profile 11 Specification]. +For more information, see the link:https://jakarta.ee/specifications/platform/11/jakarta-platform-spec-11.0[Jakarta EE Platform 11 Specification] and the link:https://jakarta.ee/specifications/webprofile/11/jakarta-webprofile-spec-11.0[Jakarta EE Web Profile 11 Specification]. // DO NOT MODIFY THIS LINE. @@ -166,7 +88,7 @@ For more information see the link:https://jakarta.ee/specifications/platform/11/ // Contact/Reviewer: jhanders34 // // // // // // // // [#jakarta_auth] -== Jakarta Authentication 3.1 +== Application Authentication 3.1 (Jakarta Authentication 3.1) Jakarta Authentication defines a general SPI for authentication mechanisms, which are controllers that interact with a caller and the container's environment to obtain and validate the caller's credentials. It then passes an authenticated identity (such as name and groups) to the container. @@ -181,7 +103,7 @@ You can enable the Jakarta Authentication 3.1 feature by adding the `appAuthenti ---- -For more information see the Jakarta Authentication 3.1 link:https://jakarta.ee/specifications/authentication/3.1/jakarta-authentication-spec-3.1[specification] and link:https://jakarta.ee/specifications/authentication/3.1/apidocs/jakarta.security.auth.message/module-summary.html[javadoc]. +For more information, see the Jakarta Authentication 3.1 link:https://jakarta.ee/specifications/authentication/3.1/jakarta-authentication-spec-3.1[specification] and link:https://jakarta.ee/specifications/authentication/3.1/apidocs/jakarta.security.auth.message/module-summary.html[javadoc]. // DO NOT MODIFY THIS LINE. @@ -190,7 +112,7 @@ For more information see the Jakarta Authentication 3.1 link:https://jakarta.ee/ // Contact/Reviewer: jhanders34 // // // // // // // // [#jakarta_authz] -== Jakarta Authorization 3.0 +== Application Authorization 3.0 (Jakarta Authorization 3.0) Jakarta Authorization defines an SPI for authorization modules, which are repositories of permissions that facilitate subject-based security by determining whether a subject has a specific permission. It also defines algorithms that transform security constraints for specific containers, such as Jakarta Servlet or Jakarta Enterprise Beans, into these permissions. @@ -198,7 +120,7 @@ The 3.0 API introduces the new `jakarta.security.jacc.PolicyFactory` and `jakart Additionally, the 3.0 specification defines a mechanism to define `PolicyConfigurationFactory` and `PolicyFactory` classes in your application by using a `web.xml` file. This design allows for an application to have a different configuration than the server-scoped one, but still allow for it to delegate to a server scoped factory for any other applications. Authorization modules can do this delegation by using decorator constructors for both `PolicyConfigurationFactory` and `PolicyFactory` classes. -To configure your authorization modules in `web.xml` file, add specification defined context parameters: +To configure your authorization modules in your application's `web.xml` file, add specification defined context parameters: [source,xml] ---- @@ -221,12 +143,13 @@ To configure your authorization modules in `web.xml` file, add specification def ---- -Due to Jakarta Authorization 3.0 no longer using the `java.security.Policy` class and introducing a new configuration mechanism for authorization modules, the `com.ibm.wsspi.security.authorization.jacc.ProviderService` Liberty API is no longer provided. This API is not available with the appAuthorization-3.0 feature. -If a Liberty user feature configures authorization modules, it must be updated to use the `PolicyConfigurationFactory` and `PolicyFactory` `set` methods. These methods configure the modules in the OSGi service. Alternatively you can use a Web Application Bundle (WAB) in your user feature to specify your security modules in a `web.xml` file. +Due to Jakarta Authorization 3.0 no longer using the `java.security.Policy` class and introducing a new configuration mechanism for authorization modules, the `com.ibm.wsspi.security.authorization.jacc.ProviderService` Liberty API is no longer available with the appAuthorization-3.0 feature. + +If a Liberty user feature configures authorization modules, the OSGi service that provided a `ProviderService` implementation must be updated to use the `PolicyConfigurationFactory` and `PolicyFactory` `set` methods. These methods configure the modules in the OSGi service. Alternatively you can use a Web Application Bundle (WAB) in your user feature to specify your security modules in a `web.xml` file. Finally, the 3.0 API adds a new `jakarta.security.jacc.PrincipalMapper` class that you can obtain from the `PolicyContext` class when authorization processing is done in your `Policy` implementation. From this class, you can obtain the roles that are associated with a specific Subject to be able to determine whether the Subject is in the required role. -You can use the `PrincipalMapper` class in your `Policy`'s `implies` or `impliesByRole` method: +You can use the `PrincipalMapper` class in your `Policy` implementation's `impliesByRole`(or `implies`) method, as shown in the following example: [source,java] ---- @@ -264,451 +187,166 @@ You can enable the Jakarta Authorization 3.0 feature by adding the `appAuthoriza ---- -For more information see the Jakarta Authorization 3.0 link:https://jakarta.ee/specifications/authorization/3.0/jakarta-authorization-spec-3.0[specification] and link:https://jakarta.ee/specifications/authorization/3.0/apidocs/jakarta.security.jacc/module-summary.html[javadoc]. +For more information, see the Jakarta Authorization 3.0 link:https://jakarta.ee/specifications/authorization/3.0/jakarta-authorization-spec-3.0[specification] and link:https://jakarta.ee/specifications/authorization/3.0/apidocs/jakarta.security.jacc/module-summary.html[javadoc]. // DO NOT MODIFY THIS LINE. // // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // -// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34436 -// Contact/Reviewer: Arunkumar-Kallyodan +// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34086 +// Contact/Reviewer: daveywebster // // // // // // // // -[#java_26] -== Beta support for Java 26 - -Java 26 is a recent version of Java. It contains new features and enhancements over earlier versions that can be useful to review. This release is not a Long-Term-Support (LTS) release. +[#jakarta_security] +== Application Security 6.0 (Jakarta Security 4.0) -There are 10 new features (JEPs) in link:https://openjdk.org/projects/jdk/26/[Java 26]. Five are test features and five are fully delivered. +An In-memory Identity Store is a developer-defined store of credential information that is used during the Open Liberty authentication and authorization work flow. It provides a quick, simple, and convenient authentication mechanism for Liberty application testing, debugging, demos, and more. -*Test Features:* +* Multiple HTTP Authentication Mechanisms (HAMs) can now be defined within the same application. These mechanisms can be specified through built-in Jakarta annotations such as `@FormAuthenticationMechanismDefinition` or through custom implementations of the `HttpAuthenticationMechanism` interface. +* A new method is added to the `SecurityContext` interface called `getAllDeclaredCallerRoles()`, which returns a list of all static (declared) application roles that the authenticated caller is in. +* References to the `IdentityStorePermission` class are removed as it was previously deprecated. -* 524: link:https://openjdk.org/jeps/524[PEM Encodings of Cryptographic Objects (Second Preview)] -* 525: link:https://openjdk.org/jeps/525[Structured Concurrency (Sixth Preview)] -* 526: link:https://openjdk.org/jeps/526[Lazy Constants (Second Preview)] -* 529: link:https://openjdk.org/jeps/529[Vector API (Eleventh Incubator)] -* 530: link:https://openjdk.org/jeps/530[Primitive Types in Patterns, instanceof, and switch (Fourth Preview)] +All features are available as part of `appSecurity-6.0`. -*Delivered Features:* +All feature use cases are targeted towards Jakarta EE web application developers who want to move to a modern Jakarta version and use implementations of the Jakarta Security 4.0 specification. -* 500: link:https://openjdk.org/jeps/500[Prepare to Make Final Mean Final] -* 504: link:https://openjdk.org/jeps/504[Remove the Applet API] -* 516: link:https://openjdk.org/jeps/516[Ahead-of-Time Object Caching with Any GC] -* 517: link:https://openjdk.org/jeps/517[HTTP/3 for the HTTP Client API] -* 522: link:https://openjdk.org/jeps/522[G1 GC: Improve Throughput by Reducing Synchronization] +=== In-memory identity store -A new change JEP 500 ("Prepare to Make Final Mean Final") in Java 26 starts enforcing true immutability of final fields by restricting their mutation by using deep reflection. -In JDK 26, such mutations still work but trigger runtime warnings by default, preparing developers for stricter enforcement. -Future releases would likely throw exceptions instead, making the final truly nonmutable. -Developers can opt in early to this stricter behavior by using a JVM flag (for example, `--illegal-final-field-mutation=deny`) to detect issues sooner. -This change improves program correctness, security, and JVM optimizations. +Before the introduction of the new identity store specification, Jakarta Security natively supported only two types of identity stores: *database* and *LDAP*, both of which are used for credential validation. While effective for production environments, these options were considered heavyweight for testing, debugging, and demonstration scenarios. -Take advantage of trying out the new changes now and gain more time to preview how your applications and microservices run with Java 26. +Developers can also implement custom identity stores, but doing so requires bespoke code to collect, validate, and manage credential information. This effort can divert attention from core application development. A built-in, in-memory identity store reduces this burden for non-production use cases such as testing, debugging, and demonstrations. -Just link:https://jdk.java.net/26/[download the latest release of Java 26], download and install the link:https://openliberty.io/downloads/#runtime_betas[26.0.0.4-beta] version of Open Liberty, edit your Liberty server's link:https://openliberty.io/docs/latest/reference/config/server-configuration-overview.html#server-env[server.env] file with `JAVA_HOME` set to your Java 26 installation directory and start testing! +The following example shows an application that uses a single authentication mechanism and three identities, which includes the new in‑memory identity store, all managed by the existing `IdentityStoreHandler` internal implementation. This implementation cycles through each identity store to validate credentials. The identity‑store handler can also be overridden with a user‑defined implementation, which is existing functionality. -For more information on Java 26, see the Java 26 link:https://jdk.java.net/26/release-notes[release notes page], link:https://download.java.net/java/early_access/jdk26/docs/api/[API Javadoc page] or link:https://jdk.java.net/26/[download page]. -For more information on Open Liberty, see our link:https://openliberty.io/docs[documentation page]. +image::https://github.com/user-attachments/assets/f3ddf9b1-9d2d-481d-9bf2-be3bad28614c[Application with single authentication mechanism and three identity stores,width=1809,height=1065] -// DO NOT MODIFY THIS LINE. +=== Multiple HAMs -// // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // -// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34314 -// Contact/Reviewer: Azquelt -// // // // // // // // -[#mcp] -== Updates to `mcpServer-1.0` +It is now possible for multiple authentication mechanisms to logically act as a single HTTP Authentication Mechanism (HAM), providing a more flexible, dynamic, and configurable approach to the authentication workflow. -The link:https://modelcontextprotocol.io/docs/getting-started/intro[Model Context Protocol (MCP)] is an open standard that enables AI applications to access real-time information from external sources. The Liberty MCP Server feature `mcpServer-1.0` allows developers to expose the business logic of their applications, allowing it to be integrated into agentic AI workflows. +Access to the `HttpAuthenticationMechanism` is now abstracted by an internal implementation of the new Jakarta `HttpAuthenticationMechanismHandler` interface. This implementation prioritizes custom‑defined HAMs first and then falls back to the built‑in (annotation‑defined) HAMs, in the following order: OpenID, custom form, form, and basic authentication mechanisms. -This beta release of Open Liberty includes updates to the `mcpServer-1.0` feature including dynamic registration of tools and support for version `2025-11-25` of the protocol. +Developers are free to provide their own implementation of the `HttpAuthenticationMechanismHandler`, allowing them to define a custom prioritization strategy for selecting HAMs. They *must* supply such an implementation if any built‑in HAMs are defined with the optional `qualifiers` attribute set. -=== Dynamically register MCP tools +The following example illustrates an application with three HAMs (Basic, Form, and Custom). In this case, the internal implementation of the Jakarta `HttpAuthenticationMechanismHandler` selects Custom, as it takes priority over built-in HAMs such as Basic and Form. A custom implementation of the `HttpAuthenticationMechanismHandler` can select any HAM based on a bespoke selection algorithm. The HAM hand-off to the identity‑store handler remains in place. -Tools can now be registered dynamically through an API and by annotating a method. This capability allows the available tools on the server to be changed based on configuration or environment. +image::https://github.com/user-attachments/assets/e50a5eaa-fd8b-49c6-84b9-8532f79983e0[Application with three HAMs,width=1855,height=1044] -Tools can be registered by injecting `ToolManager` and calling its methods to add, remove, and list the available tools on the server. The full Javadoc for `ToolManager` can be found within the liberty beta in `dev/api/ibm/javadoc/io.openliberty.mcp_1.0-javadoc.zip`. +=== getAllDeclaredCallerRoles() -Tools can be registered when the application starts through the CDI `Startup` event. See the following example where the `Startup` event is used to register a weather forecast tool only if a `WeatherClient` bean is available. +The `SecurityContext` interface implementation is updated to include a new method, `getAllDeclaredCallerRoles()`, which returns a list of the declared application roles for an authenticated caller. If the caller is not authenticated or has no declared roles, the method returns an empty list. -[source,java] ----- - @Inject - ToolManager toolManager; +=== How to use - @Inject - Instance weatherClientInstance; +Enable Jakarta Security 4.0 features within the `server.xml` file by adding the `appSecurity-6.0` feature as shown in the following example: - private void createWeatherTool(@Observes Startup startup) { - if (weatherClientInstance.isResolvable()) { - WeatherClient weatherClient = weatherClientInstance.get(); - toolManager.newTool("getForecast") - .setTitle("Weather Forecast Provider") - .setDescription("Get weather forecast for a location") - .addArgument("latitude", "Latitude of the location", true, Double.class) - .addArgument("longitude", "Longitude of the location", true, Double.class) - .setHandler(toolArguments -> { - Double latitude = (Double) toolArguments.args().get("latitude"); - Double longitude = (Double) toolArguments.args().get("longitude"); - String result = weatherClient.getForecast( - latitude, - longitude, - 4, - "temperature_2m,snowfall,rain,precipitation,precipitation_probability"); - return ToolResponse.success(result); - }) - .register(); - } - } +[source,xml] ---- + -Tool registration starts with `newTool()`, then the information about the tool is added, including its title, description, and arguments. The handler supplies the code to run when the tool is called. It has one parameter, which is a `ToolArguments` object, which provides access to the arguments and other information about the tool call request. The handler must always create and return a `ToolResponse`. - -=== Accept the 2025-11-25 MCP protocol - -The `mcpServer-1.0` feature now accepts MCP protocol version `2025-11-25`, though it doesn't support any of the new features added in this version of the protocol. - -There are two main changes as a result of supporting `2025-11-25`: + . . . -* Tool names are now restricted to ASCII letters (`A-Z,a-z`), digits (`0-9`), and the underscore (`_`), hyphen ('-') and dot (`.`) characters -* Invalid arguments passed when calling a tool are now treated as tool execution errors, rather than protocol errors. This allows the LLM to receive feedback that it called the tool incorrectly and make another attempt + + appSecurity-6.0 + -=== Paginated results + -The result of a `tools/list` call is now paginated with a page size of 20. This means that if there are more than 20 tools deployed on the server, clients make several small calls to retrieve the list of tools, rather than one large call. + . . . -=== Bug fixes +---- -* During cancellation of a tool call, we check that both the session id and the authenticated user match the session id and the user that made the tool call. Previously only the session id was checked. -* Messages that are returned to the MCP client no longer contain OpenLiberty message codes. -* Structured content is only returned when client is using protocol version `2025-06-18` or later. +NOTE: As shown in the preceding example, when an application defines an in‑memory identity store in code, its use must also be explicitly enabled in the `server.xml` configuration. By default, the `allowInMemoryIdentityStores` attribute is set to false, which instructs the Liberty authentication workflows not to use in‑memory identity stores, even when a custom identity store handler is present. For applications that rely on multiple HAMs, the `allowInMemoryIdentityStores` attribute does not need to be set. -=== Further information +==== In-Memory Identity Store -* More information about the `mcpServer-1.0` feature and how to get started using the beta, see our link:https://openliberty.io/blog/2025/10/23/mcp-standalone-blog.html[dedicated blog post]. -* More information about Model Context Protocol can be found at link:https://modelcontextprotocol.io/docs/getting-started/intro[modelcontextprotocol.io] +The link:https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#in-memory-annotation[Jakarta Security Specification 4.0] provides details on how to specify credential information to be used during the authentication workflow through the new `@InMemoryIdentityStoreDefinition` annotation, as shown in the following example: -// DO NOT MODIFY THIS LINE. +[source,java] +---- +. . . +@InMemoryIdentityStoreDefinition ( + priority = 10, + priorityExpression = "${80/20}", + useFor = {VALIDATE, PROVIDE_GROUPS}, + useForExpression = "#{'VALIDATE'}", + value = { + @Credentials(callerName = "jasmine", password = "secret1", groups = { "caller", "user" } ) + } +) +---- -// // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // -// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/33186 -// Contact/Reviewer: isaacrivriv,mrsaldana,pnicolucci,volosied -// // // // // // // // -[#jakarta_data] -== Preview of some Jakarta Data 1.1 M2 capability +All attributes for the `@InMemoryIdentityStoreDefinition` annotation are shown in the example. The `priority`, `priorityExpression`, `useFor`, and `useForExpression` attributes are optional and set to sensible defaults. -Previews some new capability at the Jakarta Data 1.1 Milestone 2 level: `Constraint` subtype parameters for repository methods that constraints to repository `@Find` operations and limited use of `Restriction` with repository `@Find` operations. Also included from the prior beta are: retrieving a subset/projection of entity attributes and the `@Is` annotation. +The `@Credentials` annotation maps one or more caller names to a password and optional group values. The `callerName` and `password` attributes are mandatory. If either one is omitted, a compilation error occurs. -*Feature:* Jakarta Data (data-1.1) +The example demonstrates a single caller definition with credential information that uses a plain-text password. However, it is highly recommended that passwords be supplied that uses an Open Liberty–supported encoding mechanism, as illustrated in the next example. -*Target persona:* Application developer +[source,java] +---- +@InMemoryIdentityStoreDefinition ( + value = { + @Credentials(callerName = "jasmine", password = "{xor}LDo8LTorbg==", groups = { "caller", "user" } ), + @Credentials(callerName = "frank", groups = { "user" }, password = "{hash}ARAAA Fyyw=="), + @Credentials(callerName = "sally", groups = { "user" }, password = "{aes}ARAFIYJ WRQNA==") + } +) +---- -Previously, parameter-based `@Find` methods were not able to filter on conditions other than equality. Now filtration can be achieved at development time by multiple methods. One is by typing the repository method parameter with a `Constraint` subtype or indicating the `Constraint` subtype through the `@Is` annotation. Or, the repository method can include a special parameter of type `Restriction` and the application can supply one or more restrictions at run time when the repository method is started. +Encrypted and encoded passwords can be generated by using the Open Liberty `securityUtility`, which is included under the `wlp/bin/securityUtility` path. The following example demonstrates how to encode a text string by using the `xor` encoding mechanism. -In Jakarta Data, you write simple Java objects called *Entities* to represent data, and you write interfaces called *Repositories* to define operations on data. You inject a Repository into your application and use it. The implementation of the Repository is automatically provided. +[source,bash] +---- +wlp/bin/securityUtility encode --encoding=xor +Enter text: +Re-enter text: +{xor}PTA9Lyg +---- -Start by defining an entity class that corresponds to your data. With relational databases, the entity class corresponds to a database table and the entity properties (public methods and fields of the entity class) generally correspond to the columns of the table. An entity class can be: +==== Multiple HAMs -* annotated with `jakarta.persistence.Entity` and related annotations from Jakarta Persistence -* a Java class without entity annotations, in which case the primary key is inferred from an entity property named `id` or ending with `Id` and an entity property named `version` designates an automatically incremented version column. +===== Application Specification -Here's a simple entity: +The link:https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#handling-multiple-authentication-mechanisms[Jakarta Security 4.0] specification allows multiple multiple HTTP Authentication Mechanisms (HAMs) to be defined within a single application, as shown in the following example: [source,java] ---- -@Entity -public class Product { - @Id - public long id; - - public String name; +@BasicAuthenticationMechanismDefinition(realmName="basicAuth") - public double price; +@FormAuthenticationMechanismDefinition( + loginToContinue = @LoginToContinue(errorPage = "/form-login-error.html", + loginPage = "/form-login.html")) - public double weight; -} +@CustomFormAuthenticationMechanismDefinition( + loginToContinue = @LoginToContinue(errorPage = "/custom-login-error.html", + loginPage = "/custom-login.html")) ---- -After you define the entity to represent the data, it is usually helpful to have your IDE generate a static metamodel class for it. By convention, static metamodel classes begin with the underscore character, followed by the entity name. Because this beta is available well before the release of Jakarta Data 1.1, IDE support for this generation cannot be expected yet. However, a static metamodel class can be provided in the same form that an IDE would generate for the `Product` entity. +This example demonstrates how three HTTP Authentication Mechanisms (HAMs) can be defined within a single application. + +Custom HAMs can also be defined in the same application by implementing the `HttpAuthenticationMechanism` interface in one or more classes, as shown in the following example: [source,java] ---- -@StaticMetamodel(Product.class) -public interface _Product { - String ID = "id"; - String NAME = "name"; - String PRICE = "price"; - String WEIGHT = "weight"; +@ApplicationScoped +// @Priority is optional and used to control selection priority if multiple custom definitions exist +@Priority(100) +public class CustomHAM implements HttpAuthenticationMechanism { + + @Override + public AuthenticationStatus validateRequest( + HttpServletRequest request, + HttpServletResponse response, + HttpMessageContext httpMessageContext) throws AuthenticationException { - NumericAttribute id = NumericAttribute.of( - Product.class, ID, long.class); - TextAttribute name = TextAttribute.of( - Product.class, NAME); - NumericAttribute price = NumericAttribute.of( - Product.class, PRICE, double.class); - NumericAttribute weight = NumericAttribute.of( - Product.class, WEIGHT, double.class); + // implement custom logic here, and return an AuthenticationStatus + return AuthenticationStatus.NOT_DONE; + } } ---- -The first half of the static metamodel class includes constants for each of the entity attribute names so that you don't need to otherwise hardcode string values into your application. The second half of the static metamodel class provides a special instance for each entity attribute, from which you can build restrictions and sorting to apply to queries at run time. This capability enables many powerful operations with repository queries, but those features are deferred to a future beta. +So a single application can have a mix of both annotation-defined HAMs and custom ones. In the previous two snippets of code, a total of four HAMs are defined (three by annotation and one custom one). -A repository defines operations that are related to the Product entity. Your repository interface can inherit from built-in interfaces such as `BasicRepository` and `CrudRepository` to gain various general-purpose repository methods for inserting, updating, deleting, and querying for entities. In addition to these capabilities, the repository can define custom operations by using the static metamodel and annotations such as @Find or @Delete. - -[source,java] ----- -@Repository(dataStore = "java:app/jdbc/my-example-data") -public interface Products extends CrudRepository { - - // Filtering is pre-defined at development time by the @Is annotation, - @Find - @OrderBy(_Product.PRICE) - @OrderBy(_Product.NAME) - List costingUpTo(@By(_Product.PRICE) @Is(AtMost.class) double maxPrice); - - // Constraint types, such as Like, can also pre-define filtering. - // Allow additional filtering at run time by including a Restriction, - @Find - Page named(@By(_Product.Name) Like namePattern, - Restriction filter, - Order sorting, - PageRequest pageRequest); - - // Retrieve a single entity attribute, identified by @Select, - @Find - @Select(_Product.PRICE) - Optional priceOf(@By(_Product.ID) long productNum); - - // Retrieve multiple entity attributes as a Java record, - @Find - @Select(_Product.WEIGHT) - @Select(_Product.NAME) - Optional weightAndNameOf(@By(_Product.ID) long productNum); - - static record WeightInfo(double itemWeight, String itemName) {} -} ----- - -Here is an example of using the repository and static metamodel: - -[source,java] ----- -@DataSourceDefinition(name = "java:app/jdbc/my-example-data", - className = "org.postgresql.xa.PGXADataSource", - databaseName = "ExampleDB", - serverName = "localhost", - portNumber = 5432, - user = "${example.database.user}", - password = "${example.database.password}") -public class MyServlet extends HttpServlet { - @Inject - Products products; - - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - // Insert: - Product prod = ... - prod = products.insert(prod); - - // Filter by supplying values only: - List found = products.costingUpTo(50.0, "%keyboard%"); - - // Compute filtering at run time, - Page page1 = products.named( - Like.suffix("printer"), - Restrict.all(_Product.price.times(taxRate).plus(shipping).lessThan(250.0), - _Product.weight.times(kgToPounds).between(10.0, 20.0)), - Order.by(_Product.price.desc(), - _Product.name.asc(), - _Product.id.asc()), - PageRequest.ofSize(10)); - - // Find one entity attribute: - price = products.priceOf(prod.id).orElseThrow(); - - // Find multiple entity attributes as a Java record: - WeightInfo info = products.getWeightAndName(prod.id); - System.out.println(info.itemName() + " weighs " + info.itemWeight() + " kg."); - - ... - } -} ----- - -=== Learn more - -* link:https://jakarta.ee/specifications/data/1.1/apidocs[Jakarta Data 1.1 API Javadoc] -* link:https://jakarta.ee/specifications/data/1.1/[Jakarta Data 1.1 overview page] -* Maven coordinates for Data 1.1 Milestone 2: -+ -[source,xml] ----- - - jakarta.data - jakarta.data-api - 1.1.0-M2 - ----- -+ -NOTE: This beta includes only the Data 1.1 features for entity subsets and projections, the @Is annotation, and Constraint subtypes as parameters for repository Find methods. It also includes limited support for Restriction as a special parameter for repository Find methods. The `navigate` operations are not implemented for restrictions and constraints. Other new Data 1.1 features are not included in this beta. - -// DO NOT MODIFY THIS LINE. - -// // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // -// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34086 -// Contact/Reviewer: daveywebster -// // // // // // // // -[#jakarta_security] -== Jakarta Security 4.0 - -An In-memory Identity Store is a developer-defined store of credential information that is used during the Open Liberty authentication and authorization work flow. It provides a quick, simple, and convenient authentication mechanism for Liberty application testing, debugging, demos, and more. - -* Multiple HTTP Authentication Mechanisms (HAMs) can now be defined within the same application. These mechanisms can be specified through built-in Jakarta annotations such as `@FormAuthenticationMechanismDefinition` or through custom implementations of the `HttpAuthenticationMechanism` interface. -* A new method is added to the `SecurityContext` interface called `getAllDeclaredCallerRoles()`, which returns a list of all static (declared) application roles that the authenticated caller is in. -* References to the `IdentityStorePermission` class are removed as it was previously deprecated. - -All features are available as part of `appSecurity-6.0`. - -All feature use cases are targeted towards Jakarta EE web application developers who want to move to a modern Jakarta version and use implementations of the Jakarta Security 4.0 specification. - -=== In-memory identity store - -Before the new identity store specification was introduced, Jakarta natively supported only two identity stores. They are database and LDAP and used for credential validation. However, these options were regarded as heavy‑weight for testing, debugging, and demonstration scenarios. - -A developer can also write a custom identity store, but it requires bespoke coding to gather, validate and store credential information, reducing developer focus from core activities. A built-in, in-memory identity store alleviates this burden for the _non-production_ deployment use cases. - -The following example shows an application that uses a single authentication mechanism and three identities, which includes the new in‑memory identity store, all managed by the existing `IdentityStoreHandler` internal implementation. This implementation cycles through each identity store to validate credentials. The identity‑store handler can also be overridden with a user‑defined implementation, which is existing functionality. - -image::https://github.com/user-attachments/assets/f3ddf9b1-9d2d-481d-9bf2-be3bad28614c[Application with single authentication mechanism and three identity stores,width=1809,height=1065] - -=== Multiple HAMs - -It is now possible for multiple authentication mechanisms to logically act as a single HTTP Authentication Mechanism (HAM), providing a more flexible, dynamic, and configurable approach to the authentication workflow. - -Access to the `HttpAuthenticationMechanism` is now abstracted by an internal implementation of the new Jakarta `HttpAuthenticationMechanismHandler` interface. This implementation prioritizes custom‑defined HAMs first and then falls back to the built‑in (annotation‑defined) HAMs, in the following order: OpenID, custom form, form, and basic authentication mechanisms. - -Developers are free to provide their own implementation of the `HttpAuthenticationMechanismHandler`, allowing them to define a custom prioritization strategy for selecting HAMs. They *must* supply such an implementation if any built‑in HAMs are defined with the optional `qualifiers` attribute set. - -The following example illustrates an application with three HAMs (Basic, Form, and Custom). In this case, the internal implementation of the Jakarta `HttpAuthenticationMechanismHandler` selects Custom, as it takes priority over built-in HAMs such as Basic and Form. A custom implementation of the `HttpAuthenticationMechanismHandler` can select any HAM based on a bespoke selection algorithm. The HAM hand-off to the identity‑store handler remains in place. - -image::https://github.com/user-attachments/assets/e50a5eaa-fd8b-49c6-84b9-8532f79983e0[Application with three HAMs,width=1855,height=1044] - -=== getAllDeclaredCallerRoles() - -The `SecurityContext` interface implementation is updated to include a new method, `getAllDeclaredCallerRoles()`, which returns a list of the declared application roles for an authenticated caller. If the caller is not authenticated or has no declared roles, the method returns an empty list. - -=== How to use - -Enable Jakarta Security 4.0 features within the `server.xml` file by adding the `appSecurity-6.0` feature as shown in the following example: - -[source,xml] ----- - - - . . . - - - appSecurity-6.0 - - - - - . . . - ----- - -NOTE: As shown in the preceding example, when an application defines an in‑memory identity store in code, it must also explicitly enable its use in the `server.xml` configuration. By default, the `allowInMemoryIdentityStores` attribute is set to false, which instructs the Liberty authentication workflows not to use in‑memory identity stores, even when a custom identity store handler is present. For applications that rely on multiple HAMs, the `allowInMemoryIdentityStores` attribute does not need to be set. - -==== in-memory identity store - -The link:https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#in-memory-annotation[Jakarta Security Specification 4.0] provides details on how to specify credential information to be used during the authentication workflow through the new `@InMemoryIdentityStoreDefinition` annotation, as shown in the following example: - -[source,java] ----- -. . . - -@InMemoryIdentityStoreDefinition ( - priority = 10, - priorityExpression = "${80/20}", - useFor = {VALIDATE, PROVIDE_GROUPS}, - useForExpression = "#{'VALIDATE'}", - value = { - @Credentials(callerName = "jasmine", password = "secret1", groups = { "caller", "user" } ) - } -) ----- - -All attributes for the `@InMemoryIdentityStoreDefinition` annotation are shown in the example. The `priority`, `priorityExpression`, `useFor`, and `useForExpression` attributes are optional and set to sensible defaults. - -The `@Credentials` annotation maps one or more caller names to a password and optional group values. The `callerName` and `password` attributes are mandatory. If either one is omitted, a compilation error occurs. - -The example demonstrates a single caller definition with credential information that uses a plain-text password. However, it is highly recommended that passwords be supplied that uses an Open Liberty–supported encoding mechanism, as illustrated in the next example. - -[source,java] ----- -@InMemoryIdentityStoreDefinition ( - value = { - @Credentials(callerName = "jasmine", password = "{xor}LDo8LTorbg==", groups = { "caller", "user" } ), - @Credentials(callerName = "frank", groups = { "user" }, password = "{hash}ARAAA Fyyw=="), - @Credentials(callerName = "sally", groups = { "user" }, password = "{aes}ARAFIYJ WRQNA==") - } -) ----- - -Encrypted and encoded passwords can be created by using the Open Liberty application `securityUtility` found under `wlp/bin/securityUtility`. Encoding a text string by using `xor` is shown in the following example: - -[source,bash] ----- -wlp/bin/securityUtility encode --encoding=xor -Enter text: -Re-enter text: -{xor}PTA9Lyg ----- - -==== multiple hams - -===== application specification - -The link:https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#handling-multiple-authentication-mechanisms[Jakarta Security Specification 4.0] allows multiple HAMs to be implemented within a single application by specifying their details as shown in the following example: - -[source,java] ----- -@BasicAuthenticationMechanismDefinition(realmName="basicAuth") - -@FormAuthenticationMechanismDefinition( - loginToContinue = @LoginToContinue(errorPage = "/form-login-error.html", - loginPage = "/form-login.html")) - -@CustomFormAuthenticationMechanismDefinition( - loginToContinue = @LoginToContinue(errorPage = "/custom-login-error.html", - loginPage = "/custom-login.html")) ----- - -This example allows for three HAMs to be defined for the application. - -Custom HAMs can also be defined within the same application by having one or more classes, which implement the `HttpAuthenticationMechanism` interface as shown in the following example: - -[source,java] ----- -@ApplicationScoped -// @Priority is optional and used to control selection priority if multiple custom definitions exist -@Priority(100) -public class CustomHAM implements HttpAuthenticationMechanism { - - @Override - public AuthenticationStatus validateRequest( - HttpServletRequest request, - HttpServletResponse response, - HttpMessageContext httpMessageContext) throws AuthenticationException { - - // implement custom logic here, and return an AuthenticationStatus - return AuthenticationStatus.NOT_DONE; - } -} ----- - -So a single application can have a mix of both annotation-defined HAMs and custom ones. In the previous two snippets of code, a total of four HAMs are defined (three by annotation and one custom one). - -IMPORTANT: `@Priority` must be used to raise or lower the priority of one custom HAM over another. If not specified, then a default priority is assigned. If more than one custom HAM is defined, their priorities need to be explicitly set to unique values. If the priorities are set to the same value or remain unset and inherit the same default value, an error occurs. +IMPORTANT: `@Priority` must be used to raise or lower the priority of one custom HAM over another. If not specified, then a default priority is assigned. If more than one custom HAM is defined, their priorities need to be explicitly set to unique values. If the priorities are set to the same value or remain unset and inherit the same default value, an error occurs. ''' @@ -727,7 +365,7 @@ The order in which HAMs are considered (when present) is as follows: Given this ordering, the Custom HAM is always selected in the authentication workflow if all five HAM types are defined in the application. -IMPORTANT: A developer can provide a custom implementation of the `HttpAuthenticationMechanismHandler` interface (a "custom HAM handler") if the internal HAM handler does not meet their requirements. A custom handler always takes precedence over the internal HAM handler, allowing any tailored algorithm to select a single HAM from multiple available mechanisms. Additional information about creating and using a custom HAM handler is provided in a later section. +IMPORTANT: A developer must provide a custom implementation of the `HttpAuthenticationMechanismHandler` interface (a "custom HAM handler") if the internal HAM handler does not meet their requirements. A custom handler always takes precedence over the internal HAM handler, allowing any tailored algorithm to select a single HAM from multiple available mechanisms. Additional information about creating and using a custom HAM handler is provided in a later section. ''' @@ -793,9 +431,8 @@ public class CustomHAMHandler implements HttpAuthenticationMechanismHandler { @Inject @Fallback // this will be the Custom HAM private HttpAuthenticationMechanism fallbackHAM; - public AuthenticationStatus validateRequest(HttpServletRequest request, - HttpServletResponse response, - HttpMessageContext context) throws AuthenticationException { + public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, + HttpMessageContext context) throws AuthenticationException { String path = request.getRequestURI(); @@ -839,7 +476,374 @@ Further information can be found in the Jakarta Security Specification 4.0: * link:https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#handling-multiple-authentication-mechanisms[multiple-hams] * link:https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#retrieving-and-testing-for-caller-data[getAllDeclaredCallerRoles()] -Information about the `securityUtility` can be found in the link:https://www.ibm.com/docs/en/was-liberty/base?topic=applications-securityutility-command[WAS Liberty topic base]. +For more information about the `securityUtility` command, see the link:https://www.ibm.com/docs/en/was-liberty/base?topic=applications-securityutility-command[WAS Liberty base topic]. + +// DO NOT MODIFY THIS LINE. + + +// // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // +// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34436 +// Contact/Reviewer: Arunkumar-Kallyodan +// // // // // // // // +[#java_26] +== Beta support for Java 26 + +Java 26 is a recent Java release that introduces new features and enhancements over earlier versions that can be useful to review. This release is not a long-term support (LTS) release. + +There are 10 new features (JEPs) in link:https://openjdk.org/projects/jdk/26/[Java 26]. Five are test features and five are fully delivered. + +*Test Features:* + +* 524: link:https://openjdk.org/jeps/524[PEM Encodings of Cryptographic Objects (Second Preview)] +* 525: link:https://openjdk.org/jeps/525[Structured Concurrency (Sixth Preview)] +* 526: link:https://openjdk.org/jeps/526[Lazy Constants (Second Preview)] +* 529: link:https://openjdk.org/jeps/529[Vector API (Eleventh Incubator)] +* 530: link:https://openjdk.org/jeps/530[Primitive Types in Patterns, instanceof, and switch (Fourth Preview)] + +*Delivered Features:* + +* 500: link:https://openjdk.org/jeps/500[Prepare to Make Final Mean Final] +* 504: link:https://openjdk.org/jeps/504[Remove the Applet API] +* 516: link:https://openjdk.org/jeps/516[Ahead-of-Time Object Caching with Any GC] +* 517: link:https://openjdk.org/jeps/517[HTTP/3 for the HTTP Client API] +* 522: link:https://openjdk.org/jeps/522[G1 GC: Improve Throughput by Reducing Synchronization] + +A new change JEP 500 ("Prepare to Make Final Mean Final") in Java 26 starts enforcing true immutability of final fields by restricting their mutation when using deep reflection. +In Java 26, such mutations still work but trigger runtime warnings by default, preparing developers for stricter enforcement. +Future releases would likely throw exceptions instead, making the final truly nonmutable. + +Developers can opt in early to this stricter behavior by using a JVM flag (for example, `--illegal-final-field-mutation=deny`) to detect issues sooner. +This change improves program correctness, security, and JVM optimizations. + +Take advantage of these changes now to gain more time to evaluate how your applications +and microservices behave on Java 26. + +Get started today by downloading the latest release of link:https://developer.ibm.com/languages/java/semeru-runtimes/downloads/[IBM Semeru Runtime 26] or link:https://adoptium.net/temurin/releases/?version=26[Temurin 26], then download and install the Open Liberty link:{url-prefix}/downloads/#runtime_betas[26.0.0.4-beta]. Update your Liberty server's link:{url-prefix}/docs/latest/reference/config/server-configuration-overview.html#server-env[server.env] file with `JAVA_HOME` set to your Java 26 installation directory and start testing. + +For more information on Java 26, see the Java 26 link:https://jdk.java.net/26/release-notes[release notes page] and link:https://docs.oracle.com/en/java/javase/26/docs/api/index.html[API Javadoc page]. + + +// DO NOT MODIFY THIS LINE. + +// // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // +// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34314 +// Contact/Reviewer: Azquelt +// // // // // // // // +[#mcp] +== Updates to `mcpServer-1.0` + +The link:https://modelcontextprotocol.io/docs/getting-started/intro[Model Context Protocol (MCP)] is an open standard that enables AI applications to access real-time information from external sources. The Liberty MCP Server feature `mcpServer-1.0` allows developers to expose the business logic of their applications, allowing it to be integrated into agentic AI workflows. + +This beta release of Open Liberty includes updates to the `mcpServer-1.0` feature including dynamic registration of tools and support for version `2025-11-25` of the protocol. + +=== Dynamically register MCP tools + +Tools can now be registered dynamically through an API or by annotating a method. This capability allows the set of available tools on the server to be adjusted based on configuration or environment. + +Tools can be registered by injecting `ToolManager` and calling its methods to add, remove, and list the available tools on the server. The full Javadoc for `ToolManager` can be found within the liberty beta in `dev/api/ibm/javadoc/io.openliberty.mcp_1.0-javadoc.zip`. + +Tools can be registered when the application starts through the CDI `Startup` event. See the following example where the `Startup` event is used to register a weather forecast tool only if a `WeatherClient` bean is available. + +[source,java] +---- + @Inject + ToolManager toolManager; + + @Inject + Instance weatherClientInstance; + + private void createWeatherTool(@Observes Startup startup) { + if (weatherClientInstance.isResolvable()) { + WeatherClient weatherClient = weatherClientInstance.get(); + toolManager.newTool("getForecast") + .setTitle("Weather Forecast Provider") + .setDescription("Get weather forecast for a location") + .addArgument("latitude", "Latitude of the location", true, Double.class) + .addArgument("longitude", "Longitude of the location", true, Double.class) + .setHandler(toolArguments -> { + Double latitude = (Double) toolArguments.args().get("latitude"); + Double longitude = (Double) toolArguments.args().get("longitude"); + String result = weatherClient.getForecast( + latitude, + longitude, + 4, + "temperature_2m,snowfall,rain,precipitation,precipitation_probability"); + return ToolResponse.success(result); + }) + .register(); + } + } +---- + +Tool registration starts with `newTool()`, then the information about the tool is added, including its title, description, and arguments. The handler supplies the code to run when the tool is called. It has one parameter, which is a `ToolArguments` object, which provides access to the arguments and other information about the tool call request. The handler must always create and return a `ToolResponse`. + +=== Accept the 2025-11-25 MCP protocol + +The `mcpServer-1.0` feature now accepts version `2025-11-25` of the Model Context Protocol (MCP), although it does not support any new features introduced in this version of the protocol. + +Supporting MCP 2025-11-25 introduces two notable behavior changes: + +* *Tool name restrictions*: Tool names are now limited to ASCII letters ('A–Z, a–z'), digits ('0–9'), and the underscore ('_'), hyphen ('-'), and dot ('.') characters. +* *Improved handling of invalid tool arguments*: Invalid arguments passed when invoking a tool are now treated as _tool execution errors_ rather than _protocol errors_. This change allows the LLM to receive feedback that the tool was called incorrectly and to retry with corrected arguments. + +=== Paginated results + +The result of a `tools/list` call is now paginated with a page size of 20. This means that if there are more than 20 tools deployed on the server, clients make several small calls to retrieve the list of tools, rather than one large call. + +=== Bug fixes + +* During cancellation of a tool call, we check that both the session id and the authenticated user match the session id and the user that made the tool call. Previously only the session id was checked. +* Messages that are returned to the MCP client no longer contain OpenLiberty message codes. +* Structured content is only returned when client is using protocol version `2025-06-18` or later. + +=== Further information + +* For more information about the `mcpServer-1.0` feature and how to get started using the beta, see our link:{url-prefix}/blog/2025/10/23/mcp-standalone-blog.html[dedicated blog post]. +* For more information about the Model Context Protocol, see link:https://modelcontextprotocol.io/docs/getting-started/intro[modelcontextprotocol.io] + +// DO NOT MODIFY THIS LINE. + + +// // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // +// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34299 +// Contact/Reviewer: njr-11 +// // // // // // // // +[#data_1.1] +== Preview of some Jakarta Data 1.1 M2 capability + +Previews some new capability at the Jakarta Data 1.1 Milestone 2 level: `Constraint` subtype parameters for repository methods that constraints to repository `@Find` operations and limited use of `Restriction` with repository `@Find` operations. Also included from the prior beta are: retrieving a subset/projection of entity attributes and the `@Is` annotation. + +Previously, parameter-based `@Find` reposotory methods could filter results only using equality conditions. This limitation has now been removed, allowing additional filtering options to be defined. + +Filtering can now be specified in several ways. One approach is to define the repository method parameter as a `Constraint` subtype, or to indicate the constraint subtype by using the `@Is` annotation. Alternatively, a repository `@Find` method can include a special parameter of type `Restriction`, allowing the application to supply one or more restrictions dynamically at runtime when the method is invoked. + +In Jakarta Data, you define simple Java objects called `entities` to represent data, and interfaces called `repositories` to define data operations. You inject a repository into your application and use it. The implementation of the repository is automatically provided. + +Start by defining an entity class that corresponds to your data. With relational databases, the entity class corresponds to a database table and the entity properties (public methods and fields of the entity class) generally correspond to the columns of the table. An entity class can be: + +* annotated with `jakarta.persistence.Entity` and related annotations from Jakarta Persistence +* a Java class without entity annotations, in which case the primary key is inferred from an entity property named `id` or ending with `Id` and an entity property named `version` designates an automatically incremented version column. + +Here's a simple entity: + +[source,java] +---- +@Entity +public class Product { + @Id + public long id; + + public String name; + + public double price; + + public double weight; +} +---- + +After you define the entity to represent the data, it is usually helpful to have your IDE generate a static metamodel class for it. By convention, static metamodel classes begin with the underscore ('_') character, followed by the entity name. + +Because this beta is available well before the release of Jakarta Data 1.1, IDE support for this generation cannot be expected yet. However, a static metamodel class can be provided in the same form that an IDE would generate for the `Product` entity. + +[source,java] +---- +@StaticMetamodel(Product.class) +public interface _Product { + String ID = "id"; + String NAME = "name"; + String PRICE = "price"; + String WEIGHT = "weight"; + + NumericAttribute id = NumericAttribute.of( + Product.class, ID, long.class); + TextAttribute name = TextAttribute.of( + Product.class, NAME); + NumericAttribute price = NumericAttribute.of( + Product.class, PRICE, double.class); + NumericAttribute weight = NumericAttribute.of( + Product.class, WEIGHT, double.class); +} +---- + +The first half of the static metamodel class includes constants for each of the entity attribute names so that you don't need to otherwise hardcode string values into your application. The second half of the static metamodel class provides a special instance for each entity attribute, from which you can build restrictions and sorting to apply to queries at run time. This capability enables many powerful operations with repository queries, but those features are deferred to a future beta. + +A repository defines operations that are related to the Product entity. Your repository interface can inherit from built-in interfaces such as `BasicRepository` and `CrudRepository` to gain various general-purpose repository methods for inserting, updating, deleting, and querying for entities. In addition to these capabilities, the repository can define custom operations by using the static metamodel and annotations such as @Find or @Delete. + +[source,java] +---- +@Repository(dataStore = "java:app/jdbc/my-example-data") +public interface Products extends CrudRepository { + + // Filtering is pre-defined at development time by the @Is annotation, + @Find + @OrderBy(_Product.PRICE) + @OrderBy(_Product.NAME) + List costingUpTo(@By(_Product.PRICE) @Is(AtMost.class) double maxPrice); + + // Constraint types, such as Like, can also pre-define filtering. + // Allow additional filtering at run time by including a Restriction, + @Find + Page named(@By(_Product.Name) Like namePattern, + Restriction filter, + Order sorting, + PageRequest pageRequest); + + // Retrieve a single entity attribute, identified by @Select, + @Find + @Select(_Product.PRICE) + Optional priceOf(@By(_Product.ID) long productNum); + + // Retrieve multiple entity attributes as a Java record, + @Find + @Select(_Product.WEIGHT) + @Select(_Product.NAME) + Optional weightAndNameOf(@By(_Product.ID) long productNum); + + static record WeightInfo(double itemWeight, String itemName) {} +} +---- + +Here is an example of using the repository and static metamodel: + +[source,java] +---- +@DataSourceDefinition(name = "java:app/jdbc/my-example-data", + className = "org.postgresql.xa.PGXADataSource", + databaseName = "ExampleDB", + serverName = "localhost", + portNumber = 5432, + user = "${example.database.user}", + password = "${example.database.password}") +public class MyServlet extends HttpServlet { + @Inject + Products products; + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + // Insert: + Product prod = ... + prod = products.insert(prod); + + // Filter by supplying values only: + List found = products.costingUpTo(50.0, "%keyboard%"); + + // Compute filtering at run time, + Page page1 = products.named( + Like.suffix("printer"), + Restrict.all(_Product.price.times(taxRate).plus(shipping).lessThan(250.0), + _Product.weight.times(kgToPounds).between(10.0, 20.0)), + Order.by(_Product.price.desc(), + _Product.name.asc(), + _Product.id.asc()), + PageRequest.ofSize(10)); + + // Find one entity attribute: + price = products.priceOf(prod.id).orElseThrow(); + + // Find multiple entity attributes as a Java record: + WeightInfo info = products.getWeightAndName(prod.id); + System.out.println(info.itemName() + " weighs " + info.itemWeight() + " kg."); + + ... + } +} +---- + +=== Learn more + +* link:https://jakarta.ee/specifications/data/1.1/apidocs[Jakarta Data 1.1 API Javadoc] +* link:https://jakarta.ee/specifications/data/1.1/[Jakarta Data 1.1 overview page] +* Maven coordinates for Data 1.1 Milestone 2: ++ +[source,xml] +---- + + jakarta.data + jakarta.data-api + 1.1.0-M2 + +---- ++ +NOTE: This beta includes only the Data 1.1 features for entity subsets and projections, the @Is annotation, and Constraint subtypes as parameters for repository Find methods. It also includes limited support for Restriction as a special parameter for repository Find methods. The `navigate` operations are not implemented for restrictions and constraints. Other new Data 1.1 features are not included in this beta. + +// DO NOT MODIFY THIS LINE. + + +// // // // DO NOT MODIFY THIS COMMENT BLOCK // // // // +// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/34495 +// Contact/Reviewer: benjamin-confino, tbitonti +// // // // // // // // +[#jandex_index] +== Support for Reading Jandex Indexes from WEB-INF/classes in Web Modules. + +Previously, Jandex indexes across all module types were read only from `META-INF/jandex.idx`. This update extends support for web modules to also read indexes from `WEB-INF/classes/META-INF/jandex.idx`, bringing it in line with industry practices. + +Jandex indexes are read from the original or the new location only when Jandex use is enabled. For compatibility with earlier versions, reading indexes from the new location must be enabled using a new application property. + +=== Benefits + +* Improved Compatibility: Improve compatibility with industry standard practices. +* Faster Startup Times: Continue to benefit from Jandex's efficient annotation indexing. + +=== Target Persona + +Customers who wish to place Jandex indexes at industry standard locations in their web modules. + +=== Target Features + +This update applies to the scanning of classes within applications. Class scanning (which includes annotation scanning) is a general purpose function that is used by many features. + +=== Problem Description + +To gather information about application classes, including annotation data, the classes must be scanned. This scanning process is expensive because the entire application must be read and processed. + +To improve performance, class scanning can be performed during application packaging, with the scan results stored in an index within the application. Jandex provides this capability. + +Jandex scan results are typically written to `META-INF/jandex.idx`. + +For JAR files, this path is relative to the root of the JAR. For WAR files, however, the `META-INF/jandex.idx` path can have two interpretations: it can be relative to the root of the WAR file, or relative to the `WEB-INF/classes` directory. + +Before this update, Liberty used the location relative to the root of the WAR file. However, industry-standard practices place the location relative to the `WEB-INF/classes` directory. This update enables Liberty to also use the `WEB-INF/classes` location. + +=== How to Use + +Support for reading Jandex indexes under `WEB-INF/classes` is enabled by a new property on the `application` and `applicationManager` elements: + +* Property: *useJandexUnderClasses* +* Description: Enables use of a Jandex index for WAR `WEB-INF/classes` under `/WEB-INF/classes/META-INF/jandex.idx`. +* Possible values: true | false +* Default value: false + +Example: applicationManager + +[source,xml] +---- + +---- + +Example: application + +[source,xml] +---- + +---- + +When the new property is placed on an application manager element, it applies to all web modules of all applications. When the new property is placed on an application element, the property applies to only that application. If the property is set on both the application manager element and an application element, the value on the application element overrides the value on the application manager element for that application. + +=== Limitation + +Jandex index support requires explicit enablement. See the `useJandex` property  on `applicationManager` and on `application` elements. The new `useJandexUnderClasses` property is meaningful only if the `useJandex` property is `true`. + +For compatibility with an earlier versions, reads of Jandex from the new location requires explicit enablement. See the new *useJandexUnderClasses* property, as documented previously. Explicit enablement is required to prevent applications from accidentally reading an out of date Jandex index from the new location. An out of date Jandex index might cause hard to detect application errors. + +The name of the new property, *useJandexUnderClasses*, is subject to revision. + +=== Learn More + +* link:https://smallrye.io/jandex/jandex/3.5.3/index.html[Jandex Documentation] +* link:{url-prefix}/docs/latest/reference/config/applicationManager.html[Application Manager Documentation] +* link:{url-prefix}/docs/latest/reference/config/application.html[Application Documentation] +* link:https://github.com/OpenLiberty/open-liberty/issues/32438[Look for jandex index under WEB-INF/classes] // DO NOT MODIFY THIS LINE. @@ -913,7 +917,7 @@ FROM icr.io/appcafe/open-liberty:beta Or take a look at our link:{url-prefix}/downloads/#runtime_betas[Downloads page]. -If you're using link:https://plugins.jetbrains.com/plugin/14856-liberty-tools[IntelliJ IDEA], link:https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext[Visual Studio Code] or link:https://marketplace.eclipse.org/content/liberty-tools[Eclipse IDE], you can also take advantage of our open source link:https://openliberty.io/docs/latest/develop-liberty-tools.html[Liberty developer tools] to enable effective development, testing, debugging and application management all from within your IDE. +If you're using link:https://plugins.jetbrains.com/plugin/14856-liberty-tools[IntelliJ IDEA], link:https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext[Visual Studio Code] or link:https://marketplace.eclipse.org/content/liberty-tools[Eclipse IDE], you can also take advantage of our open source link:{url-prefix}/docs/latest/develop-liberty-tools.html[Liberty developer tools] to enable effective development, testing, debugging and application management all from within your IDE. For more information on using a beta release, refer to the link:{url-prefix}docs/latest/installing-open-liberty-betas.html[Installing Open Liberty beta releases] documentation.