<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.8.6">Jekyll</generator><link href="https://openliberty.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://openliberty.io/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-04-29T10:23:38+00:00</updated><id>https://openliberty.io/feed.xml</id><title type="html">Open Liberty</title><subtitle>Open Liberty is the most flexible server runtime available to Earth’s Java developers.
</subtitle><entry><title type="html">Enhanced JWT validation, Java 26 support, and more in 26.0.0.4</title><link href="https://openliberty.io/blog/2026/04/21/26.0.0.4.html" rel="alternate" type="text/html" title="Enhanced JWT validation, Java 26 support, and more in 26.0.0.4" /><published>2026-04-21T00:00:00+00:00</published><updated>2026-04-21T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/04/21/26.0.0.4</id><content type="html" xml:base="https://openliberty.io/blog/2026/04/21/26.0.0.4.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This release introduces support for selecting JWT signature algorithms from JOSE headers and adds Java 26 support. It also removes the default LTPA keys password for enhanced security, and includes file transfer restrictions and security vulnerability fixes.</p>
</div>
<div class="paragraph">
<p>In <a href="/">Open Liberty</a> 26.0.0.4:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#file_transfer">File Transfer changes for 26.0.0.4</a></p>
</li>
<li>
<p><a href="#ltpa">Default LTPA keys password removal</a></p>
</li>
<li>
<p><a href="#jwt">Support selecting JWT signature and decryption algorithms from JOSE header</a></p>
</li>
<li>
<p><a href="#java_26">Support for Java 26</a></p>
</li>
<li>
<p><a href="#displayCustomizedExceptionText">displayCustomizedExceptionText property</a></p>
</li>
<li>
<p><a href="#CVEs">Security Vulnerability (CVE) Fixes</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>View the list of fixed bugs in <a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A26004+label%3A%22release+bug%22">26.0.0.4</a>.</p>
</div>
<div class="paragraph">
<p>Check out <a href="/blog/?search=release&amp;search!=beta">previous Open Liberty GA release blog posts</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run">Develop and run your apps using 26.0.0.4</h2>
<div class="sectionbody">
<div class="paragraph">
<p>If you&#8217;re using <a href="/guides/maven-intro.html">Maven</a>, include the following in your <code>pom.xml</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.12.0<span class="tag">&lt;/version&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Or for <a href="/guides/gradle-intro.html">Gradle</a>, include the following in your <code>build.gradle</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:4.0.0'
    }
}
apply plugin: 'liberty'</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or if you&#8217;re using <a href="/docs/latest/container-images.html">container images</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or take a look at our <a href="/start/">Downloads page</a>.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="https://plugins.jetbrains.com/plugin/14856-liberty-tools">IntelliJ IDEA</a>, <a href="https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext">Visual Studio Code</a>, or <a href="https://marketplace.eclipse.org/content/liberty-tools">Eclipse IDE</a>, you can also take advantage of our open source <a href="https://openliberty.io/docs/latest/develop-liberty-tools.html">Liberty developer tools</a> to enable effective development, testing, debugging, and application management all from within your IDE.</p>
</div>
<div class="imageblock text-center">
<div class="content">
<a class="image" href="https://stackoverflow.com/tags/open-liberty"><img src="/img/blog/blog_btn_stack.svg" alt="Ask a question on Stack Overflow"></a>
</div>
</div>
<div class="sect2">
<h3 id="file_transfer">File Transfer changes for 26.0.0.4</h3>
<div class="paragraph">
<p>Liberty&#8217;s FileService MBean provided by the <code>restConnector-2.0</code> feature now includes an extra <code>blocklist</code> attribute. This attribute is configured by the <code>&lt;blockDir&gt;</code> config element in the <code>server.xml</code> file. The default value of this attribute is <code>${server.output.dir}/resources/security</code>. This behavior change resolves the security vulnerability <a href="https://github.com/advisories/GHSA-c39w-6qgm-5cp7">CVE-2025-14915</a>, by restricting default FileTransfer access to <code>${server.output.dir}/resources/security</code>.</p>
</div>
<div class="paragraph">
<p>If FileTransfer access to <code>${server.output.dir}/resources/security</code> is required, the original behavior can be restored by setting an empty blocklist.</p>
</div>
<div class="paragraph">
<p>For more information, see the <a href="https://www.ibm.com/docs/en/was-liberty/nd?topic=manually-file-transfer">documentation</a>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="ltpa">Default LTPA keys password removal</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The default LTPA keys password is removed to resolve the security vulnerability <a href="https://www.ibm.com/support/pages/node/7266845">CVE-2025-14917</a>.</p>
</div>
<div class="paragraph">
<p>Previously, a default password for the LTPA keys was used when the <code>keysPassword</code> attribute was not defined in the <code>&lt;ltpa /&gt;</code> element. With this change, the default password is no longer supported.</p>
</div>
<div class="paragraph">
<p>For existing servers, if the LTPA keys password is not configured in the <code>server.xml</code> file, the <code>keystore_password</code> in the <code>server.env</code> file is used. This value re-encrypts the LTPA keys in the <code>ltpa.keys</code> file. The LTPA keys themselves are not impacted. The <code>keystore_password</code> is configured in the <code>server.env</code> file during server creation unless the <code>--no-password</code> option is used with the <code>server create</code> command.</p>
</div>
<div class="paragraph">
<p>If a <code>keysPassword</code> is not defined in the <code>&lt;ltpa /&gt;</code> element in the <code>server.xml</code> file and a <code>keystore_password</code> is not defined in the <code>server.env</code> file, the LTPA service fails.
The following error message is displayed:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="text">CWWKS4118E: LTPA configuration error. A keysPassword attribute is not configured on the &lt;ltpa /&gt; element, the 'ltpa_keys_password' environment variable is not set, and the 'keystore_password' environment variable is not set.</code></pre>
</div>
</div>
<div class="paragraph">
<p>Confirm that an LTPA keys password is set up by doing the following steps:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Check to see whether a <code>keysPassword</code> attribute is provided for the <code>&lt;ltpa /&gt;</code> element in the <code>server.xml</code> file (for example, <code>&lt;ltpa keysPassword="myKeysPassword" /&gt;</code>).</p>
<div class="ulist">
<ul>
<li>
<p>If it is provided, this update does not affect you and no further action is needed.</p>
</li>
<li>
<p>If it is not provided, do <strong>not</strong> add it and proceed to the next step.</p>
</li>
</ul>
</div>
</li>
<li>
<p>Check to see whether the <code>keystore_password</code> environment variable exists in the <code>server.env</code> file (for example, <code>keystore_password=myKeystorePassword</code>).</p>
<div class="ulist">
<ul>
<li>
<p>If it exists, then the <code>keystore_password</code> is used to reencrypt the LTPA keys that were previously encrypted with the default <code>keysPassword</code> when the server starts.</p>
</li>
<li>
<p>If it does not exist, proceed to the next step.</p>
</li>
</ul>
</div>
</li>
<li>
<p>Add the following environment variable to the <code>server.env</code> file (ensure you use the <code>keystore_password</code> here and <strong>not</strong> the <code>ltpa_keys_password</code> described in the next section for new servers):</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="properties">keystore_password=your-desired-password</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>The <code>keystore_password</code> is used to reencrypt the LTPA keys that were previously encrypted with the default <code>keysPassword</code> when the server starts.</p>
</li>
</ul>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>For new servers, a new <code>ltpa_keys_password</code> is randomly generated during server creation. It is stored in the <code>server.env</code> file unless the <code>--no-password</code> option is specified with the <code>server create</code> command. The randomly generated <code>ltpa_keys_password</code> is used if the <code>keysPassword</code> attribute is not defined for the <code>&lt;ltpa /&gt;</code> element.</p>
</div>
<div class="paragraph">
<p>For more information, see the <a href="https://openliberty.io/docs/latest/reference/config/ltpa.html">LTPA</a> configuration element.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jwt">Support selecting JWT signature and decryption algorithms from JOSE header</h2>
<div class="sectionbody">
<div class="paragraph">
<p>JSON Web Tokens (JWTs) can be signed by using various cryptographic signature algorithms. With this release, the JWT Consumer, MicroProfile JWT, OpenID Connect Client, and Social Media Login features support selecting the JWT signature algorithm from the JOSE header. This support allows different signature algorithms to be used based on the token header.</p>
</div>
<div class="paragraph">
<p>Previously, only one single signature algorithm (for example, <code>RS256</code>) was able to be configured for each configuration in the <code>server.xml</code> file. If the incoming JWT was signed with a different algorithm, validation would fail. This update allows the signature algorithm from the JWT header to be used for validation. It provides the flexibility of using different signature algorithms within a single configuration.</p>
</div>
<div class="sect2">
<h3 id="how-to-use">How to use</h3>
<div class="paragraph">
<p>To enable signature algorithm selection from the header, set the <code>signatureAlgorithm</code> attribute to <code>FROM_HEADER</code> and optionally configure the <code>allowedSignatureAlgorithms</code> attribute to specify which algorithms are permitted.</p>
</div>
<div class="paragraph">
<p>If <code>allowedSignatureAlgorithms</code> is not configured, the default list contains all Open Liberty-supported signature algorithms: <code>RS256, RS384, RS512, HS256, HS384, HS512, ES256, ES384</code>, and <code>ES512</code>.</p>
</div>
<div class="paragraph">
<p>When using <code>FROM_HEADER</code> with asymmetric algorithms and a trust store setup, the public keys must be prefixed with their corresponding algorithm (e.g., <code>RS256_keyalias</code>) for automatic selection. During validation, the server searches the trust store for an alias that begins with the algorithm specified in the JWT&#8217;s header. If no algorithm-prefixed alias is found, the client falls back to using the alias specified by the <code>trustedAlias</code> attribute (for <code>jwtConsumer</code>) or <code>trustAliasName</code> attribute (for <code>openidConnectClient</code>, <code>oidcLogin</code> and <code>mpJwt</code>), if configured.</p>
</div>
<div class="paragraph">
<p>See the following <code>server.xml</code> file configurations for examples on how to apply these settings to the supported elements:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;jwtConsumer</span>
    <span class="attribute-name">signatureAlgorithm</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">FROM_HEADER</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">allowedSignatureAlgorithms</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">RS256, ES384, HS512</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">...</span>
<span class="tag">/&gt;</span>

<span class="tag">&lt;mpJwt</span>
    <span class="attribute-name">signatureAlgorithm</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">FROM_HEADER</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">allowedSignatureAlgorithms</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">RS256, ES384, HS512</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">...</span>
<span class="tag">/&gt;</span>

<span class="tag">&lt;openidConnectClient</span>
    <span class="attribute-name">signatureAlgorithm</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">FROM_HEADER</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">allowedSignatureAlgorithms</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">RS256, ES384, HS512</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">...</span>
<span class="tag">/&gt;</span>

<span class="tag">&lt;oidcLogin</span>
    <span class="attribute-name">signatureAlgorithm</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">FROM_HEADER</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">allowedSignatureAlgorithms</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">RS256, ES384, HS512</span><span class="delimiter">&quot;</span></span>
    <span class="attribute-name">...</span>
<span class="tag">/&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="learn-more">Learn more</h3>
<div class="paragraph">
<p><strong>Server configurations:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/config/openidConnectClient.html">openidConnectClient</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/config/jwtConsumer.html">jwtConsumer</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/config/mpJwt.html">mpJwt</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/config/oidcLogin.html">oidcLogin</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p><strong>Documentation:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/feature/openidConnectClient-1.0.html">OpenID Connect Client 1.0</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/feature/jwt-1.0.html">JSON Web Token 1.0</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/feature/mpJwt-2.1.html">MicroProfile JWT 2.1</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/latest/reference/feature/socialLogin-1.0.html">Social Media Login 1.0</a></p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="java_26">Support for Java 26</h3>
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>There are 10 new features (JEPs) in <a href="https://openjdk.org/projects/jdk/26/">Java 26</a>. Five are test features and five are fully delivered.</p>
</div>
<div class="paragraph">
<p><strong>Test Features:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>524: <a href="https://openjdk.org/jeps/524">PEM Encodings of Cryptographic Objects (Second Preview)</a></p>
</li>
<li>
<p>525: <a href="https://openjdk.org/jeps/525">Structured Concurrency (Sixth Preview)</a></p>
</li>
<li>
<p>526: <a href="https://openjdk.org/jeps/526">Lazy Constants (Second Preview)</a></p>
</li>
<li>
<p>529: <a href="https://openjdk.org/jeps/529">Vector API (Eleventh Incubator)</a></p>
</li>
<li>
<p>530: <a href="https://openjdk.org/jeps/530">Primitive Types in Patterns, instanceof, and switch (Fourth Preview)</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p><strong>Delivered Features:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>500: <a href="https://openjdk.org/jeps/500">Prepare to Make Final Mean Final</a></p>
</li>
<li>
<p>504: <a href="https://openjdk.org/jeps/504">Remove the Applet API</a></p>
</li>
<li>
<p>516: <a href="https://openjdk.org/jeps/516">Ahead-of-Time Object Caching with Any GC</a></p>
</li>
<li>
<p>517: <a href="https://openjdk.org/jeps/517">HTTP/3 for the HTTP Client API</a></p>
</li>
<li>
<p>522: <a href="https://openjdk.org/jeps/522">G1 GC: Improve Throughput by Reducing Synchronization</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>Developers can opt in early to this stricter behavior by using a JVM flag (for example, <code>--illegal-final-field-mutation=deny</code>) to detect issues sooner.
This change improves program correctness, security, and JVM optimizations.</p>
</div>
<div class="paragraph">
<p>Take advantage of these changes now to gain more time to evaluate how your applications
and microservices behave on Java 26.</p>
</div>
<div class="paragraph">
<p>Get started today by downloading the latest release of  <a href="https://developer.ibm.com/languages/java/semeru-runtimes/downloads/">IBM Semeru Runtime 26</a> or <a href="https://adoptium.net/temurin/releases/?version=26">Temurin 26</a>, then download and install the Open Liberty <a href="/start/#runtime_releases">26.0.0.4</a>. Update your Liberty server&#8217;s <a href="/docs/latest/reference/config/server-configuration-overview.html#server-env">server.env</a> file with <code>JAVA_HOME</code> set to your Java 26 installation directory and start testing.</p>
</div>
<div class="paragraph">
<p>For more information on Java 26, see the Java 26 <a href="https://jdk.java.net/26/release-notes">release notes page</a> and <a href="https://docs.oracle.com/en/java/javase/26/docs/api/index.html">API Javadoc page</a>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="displayCustomizedExceptionText">displayCustomizedExceptionText property</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This release adds documentation and tests for the <code>displayCustomizedExceptionText</code> configuration, which allows users to override Liberty’s default error messages (such as SRVE0218E: Forbidden and SRVE0232E: An exception occurred) with clearer, user-defined messages.</p>
</div>
<div class="paragraph">
<p>The feature is enabled through simple <code>server.xml</code> file configuration, where custom messages can be mapped to specific HTTP status codes (<code>403</code> and <code>500</code>).</p>
</div>
<div class="paragraph">
<p>Testing ensures that these custom messages correctly replace Liberty’s defaults across all supported platforms, confirming that the configured text is returned consistently in all scenarios.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;webContainer</span> <span class="attribute-name">displaycustomizedexceptiontext</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Custom error message</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="CVEs">Security vulnerability (CVE) fixes in this release</h2>
<div class="sectionbody">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">CVE</th>
<th class="tableblock halign-left valign-top">CVSS Score</th>
<th class="tableblock halign-left valign-top">Vulnerability Assessment</th>
<th class="tableblock halign-left valign-top">Versions Affected</th>
<th class="tableblock halign-left valign-top">Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2025-14915">CVE-2025-14915</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">6.5</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Privilege escalation</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-26.0.0.3</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Affects the <code>restConnector-2.0</code> feature</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2025-14917">CVE-2025-14917</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">6.7</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Weaker security</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-26.0.0.3</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Affects the <code>appSecurity-1.0</code>, <code>appSecurity-2.0</code>, <code>appSecurity-3.0</code>, <code>appSecurity-4.0</code>, and <code>appSecurity-5.0</code> features</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2026-1561">CVE-2026-1561</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">5.4</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Server-side request forgery</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-26.0.0.3</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Affects the <code>samlWeb-2.0</code> feature</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2026-29063">CVE-2026-29063</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">8.7</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Prototype pollution</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-26.0.0.3</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Affects the <code>openapi-3.1</code>, <code>mpOpenAPI-1.0</code>, <code>mpOpenAPI-1.1</code>, <code>mpOpenAPI-2.0</code>, <code>mpOpenAPI-3.0</code>, <code>mpOpenAPI-3.1</code>, <code>mpOpenAPI-4.0</code> and <code>mpOpenAPI-4.1</code> features</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>For a list of past security vulnerability fixes, reference the <a href="/docs/latest/security-vulnerabilities.html">Security vulnerability (CVE) list</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="get-open-liberty-26-0-0-4-now">Get Open Liberty 26.0.0.4 now</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Available through <a href="#run">Maven, Gradle, Docker, and as a downloadable archive</a>.</p>
</div>
</div>
</div>]]></content><author><name>Navaneeth S Nair</name></author><category term="blog" /><category term="announcements" /><category term="microprofile" /><category term="java-se" /><category term="release" /><category term="security" /><summary type="html"><![CDATA[This release introduces support for selecting JWT signature algorithms from JOSE headers and adds Java 26 support. It also removes the default LTPA keys password for enhanced security, and includes file transfer restrictions and security vulnerability fixes.]]></summary></entry><entry><title type="html">Jakarta EE 11 Platform, Java 26, and more in 26.0.0.4-beta</title><link href="https://openliberty.io/blog/2026/04/07/26.0.0.4-beta.html" rel="alternate" type="text/html" title="Jakarta EE 11 Platform, Java 26, and more in 26.0.0.4-beta" /><published>2026-04-07T00:00:00+00:00</published><updated>2026-04-07T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/04/07/26.0.0.4-beta</id><content type="html" xml:base="https://openliberty.io/blog/2026/04/07/26.0.0.4-beta.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This beta introduces Jakarta EE 11 Platform and Web Profile, and delivers enhancements across Jakarta Authentication 3.1, Jakarta Authorization 3.0, and Jakarta Security 4.0. In addition, it provides a preview of Jakarta Data 1.1 M2, support for Java 26, MCP Server updates, and Jandex index improvements.</p>
</div>
<div class="paragraph">
<p>The <a href="/">Open Liberty</a> 26.0.0.4-beta includes the following beta features (along with <a href="/docs/latest/reference/feature/feature-overview.html">all GA features</a>):</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#jakarta_ee">Jakarta EE 11 Platform and Web Profile</a></p>
<div class="ulist">
<ul>
<li>
<p><a href="#jakarta_auth">Application Authentication 3.1 (Jakarta Authentication 3.1)</a></p>
</li>
<li>
<p><a href="#jakarta_authz">Application Authorization 3.0 (Jakarta Authorization 3.0)</a></p>
</li>
<li>
<p><a href="#jakarta_security">Application Security 6.0 (Jakarta Security 4.0)</a></p>
</li>
</ul>
</div>
</li>
<li>
<p><a href="#java_26">Beta support for Java 26</a></p>
</li>
<li>
<p><a href="#mcp">Updates to <code>mcpServer-1.0</code></a></p>
</li>
<li>
<p><a href="#jakarta_data">Preview of some Jakarta Data 1.1 M2 capability</a></p>
</li>
<li>
<p><a href="#jandex_index">Support for Reading Jandex Indexes from WEB-INF/classes in Web Modules</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>See also <a href="/blog/?search=beta&amp;key=tag">previous Open Liberty beta blog posts</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jakarta_ee">Jakarta EE 11 Platform and Web Profile</h2>
<div class="sectionbody">
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>Liberty provides convenience features that bundle all component specifications in the Jakarta EE Web Profile and Jakarta EE Platform. The <code>webProfile-11.0</code> Liberty feature includes all Jakarta EE Web Profile functions, including the new Jakarta Data 1.0 component. The <code>jakartaee-11.0</code> Liberty feature provides the Jakarta EE Platform version 11 implementation. For Jakarta EE 11 features in the application client, use the <code>jakartaeeClient-11.0</code> Liberty feature.</p>
</div>
<div class="paragraph">
<p>These convenience features enable developers to rapidly develop applications using all APIs in the Web Profile and Platform specifications. Unlike the <code>jakartaee-10.0</code> Liberty feature, the <code>jakartaee-11.0</code> 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 <code>jakarta.annotation.ManagedBean</code> annotation API. Applications relying on the <code>@ManagedBean</code> annotation must migrate to use CDI annotations.</p>
</div>
<div class="paragraph">
<p>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 <code>jakartaee-11.0</code> Liberty feature. To use these capabilities, explicitly add Liberty features to your <code>server.xml</code> feature list: <code>xmlBinding-4.0</code> for XML Binding, <code>xmlWS-4.0</code> for SOAP with Attachments and XML Web Services, and <code>enterpriseBeansHome-4.0</code> for Jakarta Enterprise Beans 2.x APIs. Alternatively, use the equivalent versionless features with the <code>jakartaee-11.0</code> platform.</p>
</div>
<div class="paragraph">
<p>When using the Liberty application client with the <code>jakartaeeClient-11.0</code> 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 <code>xmlBinding-4.0</code> and the new <code>xmlWSClient-4.0</code> features in your <code>client.xml</code> file.</p>
</div>
<div class="paragraph">
<p>To enable the Jakarta EE 11 beta features in your Liberty server&#8217;s <code>server.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">  <span class="tag">&lt;featureManager&gt;</span>
    <span class="tag">&lt;feature&gt;</span>jakartaee-11.0<span class="tag">&lt;/feature&gt;</span>
  <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Or you can add the Web Profile convenience feature to enable all of the Jakarta EE 11 Web Profile beta features at once:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">  <span class="tag">&lt;featureManager&gt;</span>
    <span class="tag">&lt;feature&gt;</span>webProfile-11.0<span class="tag">&lt;/feature&gt;</span>
  <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You can enable the Jakarta EE 11 features on the Application Client Container in the <code>client.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"> <span class="tag">&lt;featureManager&gt;</span>
       <span class="tag">&lt;feature&gt;</span>jakartaeeClient-11.0<span class="tag">&lt;/feature&gt;</span>
 <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>For more information, see the <a href="https://jakarta.ee/specifications/platform/11/jakarta-platform-spec-11.0">Jakarta EE Platform 11 Specification</a> and the <a href="https://jakarta.ee/specifications/webprofile/11/jakarta-webprofile-spec-11.0">Jakarta EE Web Profile 11 Specification</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jakarta_auth">Application Authentication 3.1 (Jakarta Authentication 3.1)</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Jakarta Authentication defines a general SPI for authentication mechanisms, which are controllers that interact with a caller and the container&#8217;s environment to obtain and validate the caller&#8217;s credentials. It then passes an authenticated identity (such as name and groups) to the container.</p>
</div>
<div class="paragraph">
<p>The 3.1 version of the Jakarta Authentication API removes the deprecated Permission-related fields in the <code>jakarta.security.auth.message.config.AuthConfigFactory</code> class. The methods in the class no longer do permission checking also. These changes are part of Jakarta EE 11&#8217;s removal of SecurityManager support.</p>
</div>
<div class="paragraph">
<p>You can enable the Jakarta Authentication 3.1 feature by adding the <code>appAuthentication-3.1</code> Liberty feature in the <code>server.xml</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">    <span class="tag">&lt;featureManager&gt;</span>
        <span class="tag">&lt;feature&gt;</span>appAuthentication-3.1<span class="tag">&lt;/feature&gt;</span>
    <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>For more information, see the Jakarta Authentication 3.1 <a href="https://jakarta.ee/specifications/authentication/3.1/jakarta-authentication-spec-3.1">specification</a> and <a href="https://jakarta.ee/specifications/authentication/3.1/apidocs/jakarta.security.auth.message/module-summary.html">javadoc</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jakarta_authz">Application Authorization 3.0 (Jakarta Authorization 3.0)</h2>
<div class="sectionbody">
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>The 3.0 API introduces the new <code>jakarta.security.jacc.PolicyFactory</code> and <code>jakarta.security.jacc.Policy</code> classes for doing authorization decisions. These classes are added to remove the dependency on the <code>java.security.Policy</code> class, which is deprecated in newer versions of Java. With the new <code>PolicyFactory</code> API, now you can have a <code>Policy</code> per policy context instead of having a global policy. This design allows separate policies to be maintained for each application.</p>
</div>
<div class="paragraph">
<p>Additionally, the 3.0 specification defines a mechanism to define <code>PolicyConfigurationFactory</code> and <code>PolicyFactory</code> classes in your application by using a <code>web.xml</code> 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 <code>PolicyConfigurationFactory</code> and <code>PolicyFactory</code> classes.</p>
</div>
<div class="paragraph">
<p>To configure your authorization modules in your application&#8217;s <code>web.xml</code> file, add specification defined context parameters:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="preprocessor">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</span>
<span class="tag">&lt;web-app</span> <span class="attribute-name">xmlns</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">https://jakarta.ee/xml/ns/jakartaee</span><span class="delimiter">&quot;</span></span>
  <span class="attribute-name">xmlns:xsi</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">http://www.w3.org/2001/XMLSchema-instance</span><span class="delimiter">&quot;</span></span>
  <span class="attribute-name">xsi:schemaLocation</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_1.xsd</span><span class="delimiter">&quot;</span></span>
  <span class="attribute-name">version</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">6.1</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>

  <span class="tag">&lt;context-param&gt;</span>
    <span class="tag">&lt;param-name&gt;</span>jakarta.security.jacc.PolicyConfigurationFactory.provider<span class="tag">&lt;/param-name&gt;</span>
    <span class="tag">&lt;param-value&gt;</span>com.example.MyPolicyConfigurationFactory<span class="tag">&lt;/param-value&gt;</span>
  <span class="tag">&lt;/context-param&gt;</span>

  <span class="tag">&lt;context-param&gt;</span>
    <span class="tag">&lt;param-name&gt;</span>jakarta.security.jacc.PolicyFactory.provider<span class="tag">&lt;/param-name&gt;</span>
    <span class="tag">&lt;param-value&gt;</span>com.example.MyPolicyFactory<span class="tag">&lt;/param-value&gt;</span>
  <span class="tag">&lt;/context-param&gt;</span>

<span class="tag">&lt;/web-app&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Due to Jakarta Authorization 3.0 no longer using the <code>java.security.Policy</code> class and introducing a new configuration mechanism for authorization modules, the <code>com.ibm.wsspi.security.authorization.jacc.ProviderService</code> 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 <code>ProviderService</code> implementation must be updated to use the <code>PolicyConfigurationFactory</code> and <code>PolicyFactory</code> <code>set</code> 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 <code>web.xml</code> file.</p>
</div>
<div class="paragraph">
<p>Finally, the 3.0 API adds a new <code>jakarta.security.jacc.PrincipalMapper</code> class that you can obtain from the <code>PolicyContext</code> class when authorization processing is done in your <code>Policy</code> 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.</p>
</div>
<div class="paragraph">
<p>You can use the <code>PrincipalMapper</code> class in your <code>Policy</code> implementation&#8217;s <code>impliesByRole</code> (or <code>implies</code>) method, as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="directive">public</span> <span class="type">boolean</span> impliesByRole(<span class="predefined-type">Permission</span> p, <span class="predefined-type">Subject</span> subject) {
        <span class="predefined-type">Map</span>&lt;<span class="predefined-type">String</span>, <span class="predefined-type">PermissionCollection</span>&gt; perRolePermissions =
            PolicyConfigurationFactory.get().getPolicyConfiguration(contextID).getPerRolePermissions();
        PrincipalMapper principalMapper = PolicyContext.get(PolicyContext.PRINCIPAL_MAPPER);

        <span class="comment">// Check to see if the Permission is in the all authenticated users role (**)</span>
        <span class="keyword">if</span> (!principalMapper.isAnyAuthenticatedUserRoleMapped() &amp;&amp; !subject.getPrincipals().isEmpty()) {
            <span class="predefined-type">PermissionCollection</span> rolePermissions = perRolePermissions.get(<span class="string"><span class="delimiter">&quot;</span><span class="content">**</span><span class="delimiter">&quot;</span></span>);
            <span class="keyword">if</span> (rolePermissions != <span class="predefined-constant">null</span> &amp;&amp; rolePermissions.implies(p)) {
                <span class="keyword">return</span> <span class="predefined-constant">true</span>;
            }
        }

        <span class="comment">// Check to see if the roles for the Subject provided imply the permission</span>
        <span class="predefined-type">Set</span>&lt;<span class="predefined-type">String</span>&gt; mappedRoles = principalMapper.getMappedRoles(subject);
        <span class="keyword">for</span> (<span class="predefined-type">String</span> mappedRole : mappedRoles) {
            <span class="predefined-type">PermissionCollection</span> rolePermissions = perRolePermissions.get(mappedRole);
            <span class="keyword">if</span> (rolePermissions != <span class="predefined-constant">null</span> &amp;&amp; rolePermissions.implies(p)) {
                <span class="keyword">return</span> <span class="predefined-constant">true</span>;
            }
        }
        <span class="keyword">return</span> <span class="predefined-constant">false</span>;
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can enable the Jakarta Authorization 3.0 feature by adding the <code>appAuthorization-3.0</code> Liberty feature in the <code>server.xml</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">    <span class="tag">&lt;featureManager&gt;</span>
        <span class="tag">&lt;feature&gt;</span>appAuthorization-3.0<span class="tag">&lt;/feature&gt;</span>
    <span class="tag">&lt;/featureManager&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>For more information, see the Jakarta Authorization 3.0 <a href="https://jakarta.ee/specifications/authorization/3.0/jakarta-authorization-spec-3.0">specification</a> and <a href="https://jakarta.ee/specifications/authorization/3.0/apidocs/jakarta.security.jacc/module-summary.html">javadoc</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jakarta_security">Application Security 6.0 (Jakarta Security 4.0)</h2>
<div class="sectionbody">
<div class="paragraph">
<p>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.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>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 <code>@FormAuthenticationMechanismDefinition</code> or through custom implementations of the <code>HttpAuthenticationMechanism</code> interface.</p>
</li>
<li>
<p>A new method is added to the <code>SecurityContext</code> interface called <code>getAllDeclaredCallerRoles()</code>, which returns a list of all static (declared) application roles that the authenticated caller is in.</p>
</li>
<li>
<p>References to the <code>IdentityStorePermission</code> class are removed as it was previously deprecated.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>All features are available as part of <code>appSecurity-6.0</code>.</p>
</div>
<div class="paragraph">
<p>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.</p>
</div>
<div class="sect2">
<h3 id="in-memory-identity-store">In-memory identity store</h3>
<div class="paragraph">
<p>Before the introduction of the new identity store specification, Jakarta Security natively supported only two types of identity stores: <strong>database</strong> and <strong>LDAP</strong>, both of which are used for credential validation. While effective for production environments, these options were considered heavyweight for testing, debugging, and demonstration scenarios.</p>
</div>
<div class="paragraph">
<p>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.</p>
</div>
</div>
<div class="sect2">
<h3 id="multiple-hams">Multiple HAMs</h3>
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>Access to the <code>HttpAuthenticationMechanism</code> is now abstracted by an internal implementation of the new Jakarta <code>HttpAuthenticationMechanismHandler</code> 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.</p>
</div>
<div class="paragraph">
<p>Developers are free to provide their own implementation of the <code>HttpAuthenticationMechanismHandler</code>, allowing them to define a custom prioritization strategy for selecting HAMs. They <strong>must</strong> supply such an implementation if any built‑in HAMs are defined with the optional <code>qualifiers</code> attribute set.</p>
</div>
</div>
<div class="sect2">
<h3 id="getalldeclaredcallerroles">getAllDeclaredCallerRoles()</h3>
<div class="paragraph">
<p>The <code>SecurityContext</code> interface implementation is updated to include a new method, <code>getAllDeclaredCallerRoles()</code>, 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.</p>
</div>
</div>
<div class="sect2">
<h3 id="how-to-use">How to use</h3>
<div class="paragraph">
<p>Enable Jakarta Security 4.0 features within the <code>server.xml</code> file by adding the <code>appSecurity-6.0</code> feature as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;server</span> <span class="attribute-name">description</span> = <span class="string"><span class="delimiter">&quot;</span><span class="content">Liberty server</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>

    . . .

    <span class="tag">&lt;featureManager&gt;</span>
        <span class="tag">&lt;feature&gt;</span>appSecurity-6.0<span class="tag">&lt;/feature&gt;</span>
    <span class="tag">&lt;/featureManager&gt;</span>

    <span class="tag">&lt;webAppSecurity</span> <span class="attribute-name">allowInMemoryIdentityStores</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>

    . . .</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
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 <code>server.xml</code> configuration. By default, the <code>allowInMemoryIdentityStores</code> 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 <code>allowInMemoryIdentityStores</code> attribute does not need to be set.
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="in-memory-identity-store-2">In-Memory Identity Store</h4>
<div class="paragraph">
<p>The <a href="https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#in-memory-annotation">Jakarta Security Specification 4.0</a> provides details on how to specify credential information to be used during the authentication workflow through the new <code>@InMemoryIdentityStoreDefinition</code> annotation, as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">. . .

<span class="annotation">@InMemoryIdentityStoreDefinition</span> (
    priority = <span class="integer">10</span>,
    priorityExpression = <span class="string"><span class="delimiter">&quot;</span><span class="content">${80/20}</span><span class="delimiter">&quot;</span></span>,
    useFor = {VALIDATE, PROVIDE_GROUPS},
    useForExpression = <span class="string"><span class="delimiter">&quot;</span><span class="content">#{'VALIDATE'}</span><span class="delimiter">&quot;</span></span>,
    value = {
        <span class="annotation">@Credentials</span>(callerName = <span class="string"><span class="delimiter">&quot;</span><span class="content">jasmine</span><span class="delimiter">&quot;</span></span>, password = <span class="string"><span class="delimiter">&quot;</span><span class="content">secret1</span><span class="delimiter">&quot;</span></span>, groups = { <span class="string"><span class="delimiter">&quot;</span><span class="content">caller</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">user</span><span class="delimiter">&quot;</span></span> } )
    }
)</code></pre>
</div>
</div>
<div class="paragraph">
<p>All attributes for the <code>@InMemoryIdentityStoreDefinition</code> annotation are shown in the example. The <code>priority</code>, <code>priorityExpression</code>, <code>useFor</code>, and <code>useForExpression</code> attributes are optional and set to sensible defaults.</p>
</div>
<div class="paragraph">
<p>The <code>@Credentials</code> annotation maps one or more caller names to a password and optional group values. The <code>callerName</code> and <code>password</code> attributes are mandatory. If either one is omitted, a compilation error occurs.</p>
</div>
<div class="paragraph">
<p>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.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@InMemoryIdentityStoreDefinition</span> (
    value = {
        <span class="annotation">@Credentials</span>(callerName = <span class="string"><span class="delimiter">&quot;</span><span class="content">jasmine</span><span class="delimiter">&quot;</span></span>,  password = <span class="string"><span class="delimiter">&quot;</span><span class="content">{xor}LDo8LTorbg==</span><span class="delimiter">&quot;</span></span>, groups = { <span class="string"><span class="delimiter">&quot;</span><span class="content">caller</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">user</span><span class="delimiter">&quot;</span></span> } ),
        <span class="annotation">@Credentials</span>(callerName = <span class="string"><span class="delimiter">&quot;</span><span class="content">frank</span><span class="delimiter">&quot;</span></span>, groups = { <span class="string"><span class="delimiter">&quot;</span><span class="content">user</span><span class="delimiter">&quot;</span></span> }, password = <span class="string"><span class="delimiter">&quot;</span><span class="content">{hash}ARAAA &lt;sequence shortened&gt; Fyyw==</span><span class="delimiter">&quot;</span></span>),
        <span class="annotation">@Credentials</span>(callerName = <span class="string"><span class="delimiter">&quot;</span><span class="content">sally</span><span class="delimiter">&quot;</span></span>, groups = { <span class="string"><span class="delimiter">&quot;</span><span class="content">user</span><span class="delimiter">&quot;</span></span> }, password = <span class="string"><span class="delimiter">&quot;</span><span class="content">{aes}ARAFIYJ &lt;sequence shortened&gt; WRQNA==</span><span class="delimiter">&quot;</span></span>)
    }
)</code></pre>
</div>
</div>
<div class="paragraph">
<p>Encrypted and encoded passwords can be generated by using the Open Liberty <code>securityUtility</code>, which is included under the <code>wlp/bin/securityUtility</code> path. The following example demonstrates how to encode a text string by using the <code>xor</code> encoding mechanism.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="bash">wlp/bin/securityUtility encode --encoding=xor
Enter text: &lt;enter text to encode&gt;
Re-enter text:
{xor}PTA9Lyg</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="multiple-hams-2">Multiple HAMs</h4>
<div class="sect4">
<h5 id="application-specification">Application Specification</h5>
<div class="paragraph">
<p>The <a href="https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#handling-multiple-authentication-mechanisms">Jakarta Security 4.0</a> specification allows multiple HTTP Authentication Mechanisms (HAMs) to be defined within a single application, as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@BasicAuthenticationMechanismDefinition</span>(realmName=<span class="string"><span class="delimiter">&quot;</span><span class="content">basicAuth</span><span class="delimiter">&quot;</span></span>)

<span class="annotation">@FormAuthenticationMechanismDefinition</span>(
                loginToContinue = <span class="annotation">@LoginToContinue</span>(errorPage = <span class="string"><span class="delimiter">&quot;</span><span class="content">/form-login-error.html</span><span class="delimiter">&quot;</span></span>,
                loginPage = <span class="string"><span class="delimiter">&quot;</span><span class="content">/form-login.html</span><span class="delimiter">&quot;</span></span>))

<span class="annotation">@CustomFormAuthenticationMechanismDefinition</span>(
                loginToContinue = <span class="annotation">@LoginToContinue</span>(errorPage = <span class="string"><span class="delimiter">&quot;</span><span class="content">/custom-login-error.html</span><span class="delimiter">&quot;</span></span>,
                loginPage = <span class="string"><span class="delimiter">&quot;</span><span class="content">/custom-login.html</span><span class="delimiter">&quot;</span></span>))</code></pre>
</div>
</div>
<div class="paragraph">
<p>This example demonstrates how three HTTP Authentication Mechanisms (HAMs) can be defined within a single application.</p>
</div>
<div class="paragraph">
<p>Custom HAMs can also be defined in the same application by implementing the <code>HttpAuthenticationMechanism</code> interface in one or more classes, as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span>
<span class="comment">// @Priority is optional and used to control selection priority if multiple custom definitions exist</span>
<span class="annotation">@Priority</span>(<span class="integer">100</span>)
<span class="directive">public</span> <span class="type">class</span> <span class="class">CustomHAM</span> <span class="directive">implements</span> HttpAuthenticationMechanism {

    <span class="annotation">@Override</span>
    <span class="directive">public</span> AuthenticationStatus validateRequest(
        HttpServletRequest request,
        HttpServletResponse response,
        HttpMessageContext httpMessageContext) <span class="directive">throws</span> <span class="exception">AuthenticationException</span> {

            <span class="comment">// implement custom logic here, and return an AuthenticationStatus</span>
            <span class="keyword">return</span> AuthenticationStatus.NOT_DONE;
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>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).</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<code>@Priority</code> 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.
</td>
</tr>
</table>
</div>
<hr>
</div>
<div class="sect4">
<h5 id="ham-resolution">HAM resolution</h5>
<div class="paragraph">
<p>An internal implementation of the Jakarta Security 4.0 <code>HttpAuthenticationMechanismHandler</code> interface (the "internal HAM handler") is provided. When an application defines multiple HAMs, this internal handler selects a single HAM to be used in the authentication flow.</p>
</div>
<div class="paragraph">
<p>The order in which HAMs are considered (when present) is as follows:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Custom (developer‑provided) HAMs</p>
<div class="ulist">
<ul>
<li>
<p>If multiple custom HAMs are defined, their relative order is resolved by using <code>@Priority</code>.</p>
</li>
</ul>
</div>
</li>
<li>
<p><code>OpenIdAuthenticationMechanismDefinition</code></p>
</li>
<li>
<p><code>CustomFormAuthenticationMechanismDefinition</code></p>
</li>
<li>
<p><code>FormAuthenticationMechanismDefinition</code></p>
</li>
<li>
<p><code>BasicAuthenticationMechanismDefinition</code></p>
</li>
</ol>
</div>
<div class="paragraph">
<p>Given this ordering, the Custom HAM is always selected in the authentication workflow if all five HAM types are defined in the application.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
A developer must provide a custom implementation of the <code>HttpAuthenticationMechanismHandler</code> 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.
</td>
</tr>
</table>
</div>
<hr>
</div>
<div class="sect4">
<h5 id="qualifiers">Qualifiers</h5>
<div class="paragraph">
<p>HAMs - whether defined through annotations or as custom defined - can also include an optional class‑level qualifier to simplify HAM injection into a custom HAM handler. For example, if you want to define qualified HAMs, you would first declare qualifier interfaces such as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Qualifier</span>
<span class="annotation">@Retention</span>(RUNTIME)
<span class="annotation">@Target</span>({TYPE, METHOD, FIELD, PARAMETER})
<span class="directive">public</span> <span class="annotation">@interface</span> Admin {
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><em>(Not shown is the qualifier definitions for <code>User</code>, <code>Fallback</code> which follow an identical pattern, and are used below).</em></p>
</div>
<div class="paragraph">
<p>Then, import and use the qualifiers in your in-built or custom HAM specifications, such as:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@CustomFormAuthenticationMechanismDefinition</span>(&lt;existing details not shown&gt;, qualifiers={Admin.class})

<span class="annotation">@BasicAuthenticationMechanismDefinition</span>(&lt;existing details not shown&gt;, qualifiers={User.class})</code></pre>
</div>
</div>
<div class="paragraph">
<p>and</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span>
<span class="annotation">@Fallback</span>   <span class="comment">// add custom qualifier to be used during injection</span>
<span class="directive">public</span> <span class="type">class</span> <span class="class">CustomHAM</span> <span class="directive">implements</span> HttpAuthenticationMechanism {

    <span class="annotation">@Override</span>
    <span class="directive">public</span> AuthenticationStatus validateRequest (. . .)  {
         . . .
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The three HAMs defined in the example are available for injection into a custom HAM handler based on their qualifier names. This scenario represents the typical use case for applications that define multiple HAMs.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
If qualifiers are specified in any of the built-in HAM definitions, a custom HAM handler must be provided; otherwise, an error is raised. This requirement comes directly from the Jakarta Security specification. Details about creating and using a custom HAM handler are explained in the next section.
</td>
</tr>
</table>
</div>
<hr>
<div class="paragraph">
<p>To implement a custom HAM handler, define a public class that is annotated with <code>@ApplicationScoped</code> that implements the <code>HttpAuthenticationMechanismHandler</code> interface. Also, inject the qualified HAMs by using standard CDI syntax, as shown in the following section:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Default</span>
<span class="annotation">@ApplicationScoped</span>
<span class="directive">public</span> <span class="type">class</span> <span class="class">CustomHAMHandler</span> <span class="directive">implements</span> HttpAuthenticationMechanismHandler {

    <span class="annotation">@Inject</span> <span class="annotation">@Admin</span> <span class="comment">// this will be the FormHAM</span>
    <span class="directive">private</span> HttpAuthenticationMechanism adminHAM;

    <span class="annotation">@Inject</span> <span class="annotation">@User</span> <span class="comment">// this will be the BasicHAM</span>
    <span class="directive">private</span> HttpAuthenticationMechanism userHAM;

    <span class="annotation">@Inject</span> <span class="annotation">@Fallback</span> <span class="comment">// this will be the Custom HAM</span>
    <span class="directive">private</span> HttpAuthenticationMechanism fallbackHAM;

    <span class="directive">public</span> AuthenticationStatus validateRequest(
        HttpServletRequest request,
        HttpServletResponse response,
        HttpMessageContext context
    ) <span class="directive">throws</span> <span class="exception">AuthenticationException</span> {

        <span class="predefined-type">String</span> path = request.getRequestURI();

        <span class="comment">// route to appropriate mechanism based on path, default to my-realm</span>
        <span class="keyword">if</span> (path.startsWith(<span class="string"><span class="delimiter">&quot;</span><span class="content">/admin</span><span class="delimiter">&quot;</span></span>)) { <span class="comment">// FormHAM</span>
            <span class="keyword">return</span> adminHAM.validateRequest(request, response, context);
        } <span class="keyword">else</span> <span class="keyword">if</span> (path.startsWith(<span class="string"><span class="delimiter">&quot;</span><span class="content">/user</span><span class="delimiter">&quot;</span></span>)) { <span class="comment">// BasicHAM</span>
            <span class="keyword">return</span> userHAM.validateRequest(request, response, context);
        } <span class="keyword">else</span> { <span class="comment">// Custom HAM</span>
            <span class="keyword">return</span> fallbackHAM.validateRequest(request, response, context);
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This custom HAM handler takes priority over the internal HAM handler, allowing a different prioritisation algorithm to be implemented.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="getalldeclaredcallerroles-2">getAllDeclaredCallerRoles()</h4>
<div class="paragraph">
<p>To use the new <code>SecurityContext</code> method, inject the <code>SecurityContext</code> implementation into your application and call the method directly, as shown in the following section:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="annotation">@Inject</span>
    <span class="directive">private</span> SecurityContext securityContext;

. . .

    Set&lt;<span class="predefined-type">String</span>&gt; allDeclaredCallerRoles = securityContext.getAllDeclaredCallerRoles();

    <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">&quot;</span><span class="content">All declared caller roles for caller [</span><span class="delimiter">&quot;</span></span>
        + securityContext.getCallerPrincipal().getName()
        + <span class="string"><span class="delimiter">&quot;</span><span class="content">] are </span><span class="delimiter">&quot;</span></span>
        + allDeclaredCallerRoles.toString());</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="learn-more">Learn more</h3>
<div class="paragraph">
<p>Further information can be found in the Jakarta Security Specification 4.0:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#in-memory-annotation">in-memory identity store</a></p>
</li>
<li>
<p><a href="https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#handling-multiple-authentication-mechanisms">multiple-hams</a></p>
</li>
<li>
<p><a href="https://jakarta.ee/specifications/security/4.0/jakarta-security-spec-4.0#retrieving-and-testing-for-caller-data">getAllDeclaredCallerRoles()</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For more information about the <code>securityUtility</code> command, see the <a href="https://www.ibm.com/docs/en/was-liberty/base?topic=applications-securityutility-command">WAS Liberty base topic</a>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="java_26">Beta support for Java 26</h2>
<div class="sectionbody">
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>There are 10 new features (JEPs) in <a href="https://openjdk.org/projects/jdk/26/">Java 26</a>. Five are test features and five are fully delivered.</p>
</div>
<div class="paragraph">
<p><strong>Test Features:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>524: <a href="https://openjdk.org/jeps/524">PEM Encodings of Cryptographic Objects (Second Preview)</a></p>
</li>
<li>
<p>525: <a href="https://openjdk.org/jeps/525">Structured Concurrency (Sixth Preview)</a></p>
</li>
<li>
<p>526: <a href="https://openjdk.org/jeps/526">Lazy Constants (Second Preview)</a></p>
</li>
<li>
<p>529: <a href="https://openjdk.org/jeps/529">Vector API (Eleventh Incubator)</a></p>
</li>
<li>
<p>530: <a href="https://openjdk.org/jeps/530">Primitive Types in Patterns, instanceof, and switch (Fourth Preview)</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p><strong>Delivered Features:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>500: <a href="https://openjdk.org/jeps/500">Prepare to Make Final Mean Final</a></p>
</li>
<li>
<p>504: <a href="https://openjdk.org/jeps/504">Remove the Applet API</a></p>
</li>
<li>
<p>516: <a href="https://openjdk.org/jeps/516">Ahead-of-Time Object Caching with Any GC</a></p>
</li>
<li>
<p>517: <a href="https://openjdk.org/jeps/517">HTTP/3 for the HTTP Client API</a></p>
</li>
<li>
<p>522: <a href="https://openjdk.org/jeps/522">G1 GC: Improve Throughput by Reducing Synchronization</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>Developers can opt in early to this stricter behavior by using a JVM flag (for example, <code>--illegal-final-field-mutation=deny</code>) to detect issues sooner.
This change improves program correctness, security, and JVM optimizations.</p>
</div>
<div class="paragraph">
<p>Take advantage of these changes now to gain more time to evaluate how your applications
and microservices behave on Java 26.</p>
</div>
<div class="paragraph">
<p>Get started today by downloading the latest release of  <a href="https://developer.ibm.com/languages/java/semeru-runtimes/downloads/">IBM Semeru Runtime 26</a> or <a href="https://adoptium.net/temurin/releases/?version=26">Temurin 26</a>, then download and install the Open Liberty <a href="/downloads/#runtime_betas">26.0.0.4-beta</a>. Update your Liberty server&#8217;s <a href="/docs/latest/reference/config/server-configuration-overview.html#server-env">server.env</a> file with <code>JAVA_HOME</code> set to your Java 26 installation directory and start testing.</p>
</div>
<div class="paragraph">
<p>For more information on Java 26, see the Java 26 <a href="https://jdk.java.net/26/release-notes">release notes page</a> and <a href="https://docs.oracle.com/en/java/javase/26/docs/api/index.html">API Javadoc page</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="mcp">Updates to <code>mcpServer-1.0</code></h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <a href="https://modelcontextprotocol.io/docs/getting-started/intro">Model Context Protocol (MCP)</a> is an open standard that enables AI applications to access real-time information from external sources. The Liberty MCP Server feature <code>mcpServer-1.0</code> allows developers to expose the business logic of their applications, allowing it to be integrated into agentic AI workflows.</p>
</div>
<div class="paragraph">
<p>This beta release of Open Liberty includes updates to the <code>mcpServer-1.0</code> feature including dynamic registration of tools and support for version <code>2025-11-25</code> of the protocol.</p>
</div>
<div class="sect2">
<h3 id="dynamically-register-mcp-tools">Dynamically register MCP tools</h3>
<div class="paragraph">
<p>Tools can now be registered dynamically through an API. This capability allows the set of available tools on the server to be adjusted based on configuration or environment.</p>
</div>
<div class="paragraph">
<p>Tools can be registered by injecting <code>ToolManager</code> and calling its methods to add, remove, and list the available tools on the server. The full Javadoc for <code>ToolManager</code> can be found within the Liberty beta in <code>dev/api/ibm/javadoc/io.openliberty.mcp_1.0-javadoc.zip</code>.</p>
</div>
<div class="paragraph">
<p>Tools can be registered when the application starts through the CDI <code>Startup</code> event. See the following example where the <code>Startup</code> event is used to register a weather forecast tool only if a <code>WeatherClient</code> bean is available.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="annotation">@Inject</span>
    ToolManager toolManager;

    <span class="annotation">@Inject</span>
    Instance&lt;WeatherClient&gt; weatherClientInstance;

    <span class="directive">private</span> <span class="type">void</span> createWeatherTool(<span class="annotation">@Observes</span> Startup startup) {
        <span class="keyword">if</span> (weatherClientInstance.isResolvable()) {
            WeatherClient weatherClient = weatherClientInstance.get();
            toolManager.newTool(<span class="string"><span class="delimiter">&quot;</span><span class="content">getForecast</span><span class="delimiter">&quot;</span></span>)
                       .setTitle(<span class="string"><span class="delimiter">&quot;</span><span class="content">Weather Forecast Provider</span><span class="delimiter">&quot;</span></span>)
                       .setDescription(<span class="string"><span class="delimiter">&quot;</span><span class="content">Get weather forecast for a location</span><span class="delimiter">&quot;</span></span>)
                       .addArgument(<span class="string"><span class="delimiter">&quot;</span><span class="content">latitude</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Latitude of the location</span><span class="delimiter">&quot;</span></span>, <span class="predefined-constant">true</span>, <span class="predefined-type">Double</span>.class)
                       .addArgument(<span class="string"><span class="delimiter">&quot;</span><span class="content">longitude</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Longitude of the location</span><span class="delimiter">&quot;</span></span>, <span class="predefined-constant">true</span>, <span class="predefined-type">Double</span>.class)
                       .setHandler(toolArguments -&gt; {
                           <span class="predefined-type">Double</span> latitude = (<span class="predefined-type">Double</span>) toolArguments.args().get(<span class="string"><span class="delimiter">&quot;</span><span class="content">latitude</span><span class="delimiter">&quot;</span></span>);
                           <span class="predefined-type">Double</span> longitude = (<span class="predefined-type">Double</span>) toolArguments.args().get(<span class="string"><span class="delimiter">&quot;</span><span class="content">longitude</span><span class="delimiter">&quot;</span></span>);
                           <span class="predefined-type">String</span> result = weatherClient.getForecast(
                                     latitude,
                                     longitude,
                                     <span class="integer">4</span>,
                                     <span class="string"><span class="delimiter">&quot;</span><span class="content">temperature_2m,snowfall,rain,precipitation,precipitation_probability</span><span class="delimiter">&quot;</span></span>);
                           <span class="keyword">return</span> ToolResponse.success(result);
                       })
                       .register();
        }
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Tool registration starts with <code>newTool()</code>, 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 <code>ToolArguments</code> object, which provides access to the arguments and other information about the tool call request. The handler must always create and return a <code>ToolResponse</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="accept-the-2025-11-25-mcp-protocol">Accept the 2025-11-25 MCP protocol</h3>
<div class="paragraph">
<p>The <code>mcpServer-1.0</code> feature now accepts version <code>2025-11-25</code> of the Model Context Protocol (MCP), although it does not support any new features introduced in this version of the protocol.</p>
</div>
<div class="paragraph">
<p>Supporting MCP 2025-11-25 introduces two notable behavior changes:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Tool name restrictions</strong>: Tool names are now limited to ASCII letters ('A–Z, a–z'), digits ('0–9'), and the underscore ('_'), hyphen ('-'), and dot ('.') characters.</p>
</li>
<li>
<p><strong>Improved handling of invalid tool arguments</strong>: Invalid arguments passed when invoking a tool are now treated as <em>tool execution errors</em> rather than <em>protocol errors</em>. This change allows the LLM to receive feedback that the tool was called incorrectly and to retry with corrected arguments.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="paginated-results">Paginated results</h3>
<div class="paragraph">
<p>The result of a <code>tools/list</code> 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.</p>
</div>
</div>
<div class="sect2">
<h3 id="bug-fixes">Bug fixes</h3>
<div class="ulist">
<ul>
<li>
<p>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.</p>
</li>
<li>
<p>Messages that are returned to the MCP client no longer contain Open Liberty message codes.</p>
</li>
<li>
<p>Structured content is only returned when client is using protocol version <code>2025-06-18</code> or later.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="further-information">Further information</h3>
<div class="ulist">
<ul>
<li>
<p>For more information about the <code>mcpServer-1.0</code> feature and how to get started using the beta, see our <a href="/blog/2025/10/23/mcp-standalone-blog.html">dedicated blog post</a>.</p>
</li>
<li>
<p>For more information about the Model Context Protocol, see <a href="https://modelcontextprotocol.io/docs/getting-started/intro">modelcontextprotocol.io</a></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jakarta_data">Preview of some Jakarta Data 1.1 M2 capability</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Previews some new capability at the Jakarta Data 1.1 Milestone 2 level: <code>Constraint</code> subtype parameters for repository methods that constrain to repository <code>@Find</code> operations and limited use of <code>Restriction</code> with repository <code>@Find</code> operations. Also included from the prior beta are: retrieving a subset/projection of entity attributes and the <code>@Is</code> annotation.</p>
</div>
<div class="paragraph">
<p>Previously, parameter-based <code>@Find</code> reposotory methods could filter results only using equality conditions. This limitation has now been removed, allowing additional filtering options to be defined.</p>
</div>
<div class="paragraph">
<p>Filtering can now be specified in several ways. One approach is to define the repository method parameter as a <code>Constraint</code> subtype, or to indicate the constraint subtype by using the <code>@Is</code> annotation. Alternatively, a repository <code>@Find</code> method can include a special parameter of type <code>Restriction</code>, allowing the application to supply one or more restrictions dynamically at runtime when the method is invoked.</p>
</div>
<div class="paragraph">
<p>In Jakarta Data, you define simple Java objects called <code>entities</code> to represent data, and interfaces called <code>repositories</code> to define data operations. You inject a repository into your application and use it. The implementation of the repository is automatically provided.</p>
</div>
<div class="paragraph">
<p>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:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>annotated with <code>jakarta.persistence.Entity</code> and related annotations from Jakarta Persistence</p>
</li>
<li>
<p>a Java class without entity annotations, in which case the primary key is inferred from an entity property named <code>id</code> or ending with <code>Id</code> and an entity property named <code>version</code> designates an automatically incremented version column.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Here&#8217;s a simple entity:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Entity</span>
<span class="directive">public</span> <span class="type">class</span> <span class="class">Product</span> {
    <span class="annotation">@Id</span>
    <span class="directive">public</span> <span class="type">long</span> id;

    <span class="directive">public</span> <span class="predefined-type">String</span> name;

    <span class="directive">public</span> <span class="type">double</span> price;

    <span class="directive">public</span> <span class="type">double</span> weight;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>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 <code>Product</code> entity.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@StaticMetamodel</span>(Product.class)
<span class="directive">public</span> <span class="type">interface</span> <span class="class">_Product</span> {
    <span class="predefined-type">String</span> ID = <span class="string"><span class="delimiter">&quot;</span><span class="content">id</span><span class="delimiter">&quot;</span></span>;
    <span class="predefined-type">String</span> NAME = <span class="string"><span class="delimiter">&quot;</span><span class="content">name</span><span class="delimiter">&quot;</span></span>;
    <span class="predefined-type">String</span> PRICE = <span class="string"><span class="delimiter">&quot;</span><span class="content">price</span><span class="delimiter">&quot;</span></span>;
    <span class="predefined-type">String</span> WEIGHT = <span class="string"><span class="delimiter">&quot;</span><span class="content">weight</span><span class="delimiter">&quot;</span></span>;

    NumericAttribute&lt;Product, <span class="predefined-type">Long</span>&gt; id = NumericAttribute.of(
            Product.class, ID, <span class="type">long</span>.class);
    <span class="predefined-type">TextAttribute</span>&lt;Product&gt; name = <span class="predefined-type">TextAttribute</span>.of(
            Product.class, NAME);
    NumericAttribute&lt;Product, <span class="predefined-type">Double</span>&gt; price = NumericAttribute.of(
            Product.class, PRICE, <span class="type">double</span>.class);
    NumericAttribute&lt;Product, <span class="predefined-type">Double</span>&gt; weight = NumericAttribute.of(
            Product.class, WEIGHT, <span class="type">double</span>.class);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The first half of the static metamodel class includes constants for each of the entity attribute names so that you don&#8217;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.</p>
</div>
<div class="paragraph">
<p>A repository defines operations that are related to the Product entity. Your repository interface can inherit from built-in interfaces such as <code>BasicRepository</code> and <code>CrudRepository</code> 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.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Repository</span>(dataStore = <span class="string"><span class="delimiter">&quot;</span><span class="content">java:app/jdbc/my-example-data</span><span class="delimiter">&quot;</span></span>)
<span class="directive">public</span> <span class="type">interface</span> <span class="class">Products</span> <span class="directive">extends</span> CrudRepository&lt;Product, <span class="predefined-type">Long</span>&gt; {

    <span class="comment">// Filtering is pre-defined at development time by the @Is annotation,</span>
    <span class="annotation">@Find</span>
    <span class="annotation">@OrderBy</span>(_Product.PRICE)
    <span class="annotation">@OrderBy</span>(_Product.NAME)
    <span class="predefined-type">List</span>&lt;Product&gt; costingUpTo(<span class="annotation">@By</span>(_Product.PRICE) <span class="annotation">@Is</span>(AtMost.class) <span class="type">double</span> maxPrice);

    <span class="comment">// Constraint types, such as Like, can also pre-define filtering.</span>
    <span class="comment">// Allow additional filtering at run time by including a Restriction,</span>
    <span class="annotation">@Find</span>
    Page&lt;Product&gt; named(<span class="annotation">@By</span>(_Product.Name) Like namePattern,
                        Restriction&lt;Product&gt; filter,
                        Order&lt;Product&gt; sorting,
                        PageRequest pageRequest);

    <span class="comment">// Retrieve a single entity attribute, identified by @Select,</span>
    <span class="annotation">@Find</span>
    <span class="annotation">@Select</span>(_Product.PRICE)
    Optional&lt;<span class="predefined-type">Double</span>&gt; priceOf(<span class="annotation">@By</span>(_Product.ID) <span class="type">long</span> productNum);

    <span class="comment">// Retrieve multiple entity attributes as a Java record,</span>
    <span class="annotation">@Find</span>
    <span class="annotation">@Select</span>(_Product.WEIGHT)
    <span class="annotation">@Select</span>(_Product.NAME)
    Optional&lt;WeightInfo&gt; weightAndNameOf(<span class="annotation">@By</span>(_Product.ID) <span class="type">long</span> productNum);

    <span class="directive">static</span> record WeightInfo(<span class="type">double</span> itemWeight, <span class="predefined-type">String</span> itemName) {}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here is an example of using the repository and static metamodel:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@DataSourceDefinition</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">java:app/jdbc/my-example-data</span><span class="delimiter">&quot;</span></span>,
                      className = <span class="string"><span class="delimiter">&quot;</span><span class="content">org.postgresql.xa.PGXADataSource</span><span class="delimiter">&quot;</span></span>,
                      databaseName = <span class="string"><span class="delimiter">&quot;</span><span class="content">ExampleDB</span><span class="delimiter">&quot;</span></span>,
                      serverName = <span class="string"><span class="delimiter">&quot;</span><span class="content">localhost</span><span class="delimiter">&quot;</span></span>,
                      portNumber = <span class="integer">5432</span>,
                      user = <span class="string"><span class="delimiter">&quot;</span><span class="content">${example.database.user}</span><span class="delimiter">&quot;</span></span>,
                      password = <span class="string"><span class="delimiter">&quot;</span><span class="content">${example.database.password}</span><span class="delimiter">&quot;</span></span>)
<span class="directive">public</span> <span class="type">class</span> <span class="class">MyServlet</span> <span class="directive">extends</span> HttpServlet {
    <span class="annotation">@Inject</span>
    Products products;

    <span class="directive">protected</span> <span class="type">void</span> doGet(HttpServletRequest req, HttpServletResponse resp)
            <span class="directive">throws</span> ServletException, <span class="exception">IOException</span> {
        <span class="comment">// Insert:</span>
        Product prod = ...
        prod = products.insert(prod);

        <span class="comment">// Filter by supplying values only:</span>
        <span class="predefined-type">List</span>&lt;Product&gt; found = products.costingUpTo(<span class="float">50.0</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">%keyboard%</span><span class="delimiter">&quot;</span></span>);

        <span class="comment">// Compute filtering at run time,</span>
        Page&lt;Product&gt; page1 = products.named(
                        Like.suffix(<span class="string"><span class="delimiter">&quot;</span><span class="content">printer</span><span class="delimiter">&quot;</span></span>),
                        Restrict.all(_Product.price.times(taxRate).plus(shipping).lessThan(<span class="float">250.0</span>),
                                     _Product.weight.times(kgToPounds).between(<span class="float">10.0</span>, <span class="float">20.0</span>)),
                        Order.by(_Product.price.desc(),
                                 _Product.name.asc(),
                                 _Product.id.asc()),
                        PageRequest.ofSize(<span class="integer">10</span>));

        <span class="comment">// Find one entity attribute:</span>
        price = products.priceOf(prod.id).orElseThrow();

        <span class="comment">// Find multiple entity attributes as a Java record:</span>
        WeightInfo info = products.getWeightAndName(prod.id);
        <span class="predefined-type">System</span>.out.println(info.itemName() + <span class="string"><span class="delimiter">&quot;</span><span class="content"> weighs </span><span class="delimiter">&quot;</span></span> + info.itemWeight() + <span class="string"><span class="delimiter">&quot;</span><span class="content"> kg.</span><span class="delimiter">&quot;</span></span>);

        ...
    }
}</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="learn-more-2">Learn more</h3>
<div class="ulist">
<ul>
<li>
<p><a href="https://jakarta.ee/specifications/data/1.1/apidocs">Jakarta Data 1.1 API Javadoc</a></p>
</li>
<li>
<p><a href="https://jakarta.ee/specifications/data/1.1/">Jakarta Data 1.1 overview page</a></p>
</li>
<li>
<p>Maven coordinates for Data 1.1 Milestone 2:</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>jakarta.data<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>jakarta.data-api<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>1.1.0-M2<span class="tag">&lt;/version&gt;</span>
<span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
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 <code>navigate</code> operations are not implemented for restrictions and constraints. Other new Data 1.1 features are not included in this beta.
</td>
</tr>
</table>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jandex_index">Support for Reading Jandex Indexes from WEB-INF/classes in Web Modules.</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Previously, Jandex indexes across all module types were read only from <code>META-INF/jandex.idx</code>. This update extends support for web modules to also read indexes from <code>WEB-INF/classes/META-INF/jandex.idx</code>, bringing it in line with industry practices.</p>
</div>
<div class="paragraph">
<p>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.</p>
</div>
<div class="sect2">
<h3 id="benefits">Benefits</h3>
<div class="ulist">
<ul>
<li>
<p>Improved Compatibility: Improve compatibility with industry standard practices.</p>
</li>
<li>
<p>Faster Startup Times: Continue to benefit from Jandex&#8217;s efficient annotation indexing.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="target-persona">Target Persona</h3>
<div class="paragraph">
<p>Customers who wish to place Jandex indexes at industry standard locations in their web modules.</p>
</div>
</div>
<div class="sect2">
<h3 id="target-features">Target Features</h3>
<div class="paragraph">
<p>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.</p>
</div>
</div>
<div class="sect2">
<h3 id="problem-description">Problem Description</h3>
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>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.</p>
</div>
<div class="paragraph">
<p>Jandex scan results are typically written to <code>META-INF/jandex.idx</code>.</p>
</div>
<div class="paragraph">
<p>For JAR files, this path is relative to the root of the JAR. For WAR files, however, the <code>META-INF/jandex.idx</code> path can have two interpretations: it can be relative to the root of the WAR file, or relative to the <code>WEB-INF/classes</code> directory.</p>
</div>
<div class="paragraph">
<p>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 <code>WEB-INF/classes</code> directory. This update enables Liberty to also use the <code>WEB-INF/classes</code> location.</p>
</div>
</div>
<div class="sect2">
<h3 id="how-to-use-2">How to Use</h3>
<div class="paragraph">
<p>Support for reading Jandex indexes under <code>WEB-INF/classes</code> is enabled by a new property on the <code>application</code> and <code>applicationManager</code> elements:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Property: <strong>useJandexUnderClasses</strong></p>
</li>
<li>
<p>Description: Enables use of a Jandex index for WAR <code>WEB-INF/classes</code> under <code>/WEB-INF/classes/META-INF/jandex.idx</code>.</p>
</li>
<li>
<p>Possible values: true | false</p>
</li>
<li>
<p>Default value: false</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Example: applicationManager</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;applicationManager</span> <span class="attribute-name">useJandex</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">useJandexUnderClasses</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Example: application</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;application</span> <span class="attribute-name">location</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">TestServlet40.ear</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">useJandex</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">useJandexUnderClasses</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>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.</p>
</div>
</div>
<div class="sect2">
<h3 id="limitation">Limitation</h3>
<div class="paragraph">
<p>Jandex index support requires explicit enablement. See the <code>useJandex</code> property  on <code>applicationManager</code> and on <code>application</code> elements. The new <code>useJandexUnderClasses</code> property is meaningful only if the <code>useJandex</code> property is <code>true</code>.</p>
</div>
<div class="paragraph">
<p>For compatibility with earlier versions, reads of Jandex from the new location require explicit enablement. See the new <strong>useJandexUnderClasses</strong> 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 application errors that are hard to detect.</p>
</div>
<div class="paragraph">
<p>The name of the new property, <strong>useJandexUnderClasses</strong>, is subject to revision.</p>
</div>
</div>
<div class="sect2">
<h3 id="learn-more-3">Learn More</h3>
<div class="ulist">
<ul>
<li>
<p><a href="https://smallrye.io/jandex/jandex/3.5.3/index.html">Jandex Documentation</a></p>
</li>
<li>
<p><a href="/docs/latest/reference/config/applicationManager.html">Application Manager Documentation</a></p>
</li>
<li>
<p><a href="/docs/latest/reference/config/application.html">Application Documentation</a></p>
</li>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/32438">Look for jandex index under WEB-INF/classes</a></p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="run">Try it now</h3>
<div class="paragraph">
<p>To try out these features, update your build tools to pull the Open Liberty All Beta Features package instead of the main release. To enable the MCP server feature, follow the instructions from <a href="https://openliberty.io/blog/2025/10/23/mcp-standalone-blog.html">MCP standalone blog</a>. The beta works with Java SE 25, Java SE 21, Java SE 17, Java SE 11, and Java SE 8.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="/guides/maven-intro.html">Maven</a>, you can install the All Beta Features package using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.12.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;configuration&gt;</span>
        <span class="tag">&lt;runtimeArtifact&gt;</span>
          <span class="tag">&lt;groupId&gt;</span>io.openliberty.beta<span class="tag">&lt;/groupId&gt;</span>
          <span class="tag">&lt;artifactId&gt;</span>openliberty-runtime<span class="tag">&lt;/artifactId&gt;</span>
          <span class="tag">&lt;version&gt;</span>26.0.0.4-beta<span class="tag">&lt;/version&gt;</span>
          <span class="tag">&lt;type&gt;</span>zip<span class="tag">&lt;/type&gt;</span>
        <span class="tag">&lt;/runtimeArtifact&gt;</span>
    <span class="tag">&lt;/configuration&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You must also add dependencies to your <code>pom.xml</code> file for the beta version of the APIs that are associated with the beta features that you want to try. For example, the following block adds dependencies for two example beta APIs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>org.example.spec<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>exampleApi<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>7.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;type&gt;</span>pom<span class="tag">&lt;/type&gt;</span>
    <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
<span class="tag">&lt;/dependency&gt;</span>
<span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>example.platform<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>example.example-api<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>11.0.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
<span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Or for <a href="/guides/gradle-intro.html">Gradle</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:4.0.0'
    }
}
apply plugin: 'liberty'
dependencies {
    libertyRuntime group: 'io.openliberty.beta', name: 'openliberty-runtime', version: '[26.0.0.4-beta,)'
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or if you&#8217;re using <a href="/docs/latest/container-images.html">container images</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty:beta</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or take a look at our <a href="/downloads/#runtime_betas">Downloads page</a>.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="https://plugins.jetbrains.com/plugin/14856-liberty-tools">IntelliJ IDEA</a>, <a href="https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext">Visual Studio Code</a> or <a href="https://marketplace.eclipse.org/content/liberty-tools">Eclipse IDE</a>, you can also take advantage of our open source <a href="/docs/latest/develop-liberty-tools.html">Liberty developer tools</a> to enable effective development, testing, debugging and application management all from within your IDE.</p>
</div>
<div class="paragraph">
<p>For more information on using a beta release, refer to the <a href="docs/latest/installing-open-liberty-betas.html">Installing Open Liberty beta releases</a> documentation.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="feedback">We welcome your feedback</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let us know what you think on <a href="https://groups.io/g/openliberty">our mailing list</a>. If you hit a problem, <a href="https://stackoverflow.com/questions/tagged/open-liberty">post a question on StackOverflow</a>. If you hit a bug, <a href="https://github.com/OpenLiberty/open-liberty/issues">please raise an issue</a>.</p>
</div>
</div>
</div>]]></content><author><name>Navaneeth S Nair</name></author><category term="blog" /><category term="announcements" /><category term="java-se" /><category term="release" /><category term="beta" /><category term="security" /><category term="jakarta-ee" /><summary type="html"><![CDATA[This beta introduces Jakarta EE 11 Platform and Web Profile, and delivers enhancements across Jakarta Authentication 3.1, Jakarta Authorization 3.0, and Jakarta Security 4.0. In addition, it provides a preview of Jakarta Data 1.1 M2, support for Java 26, MCP Server updates, and Jandex index improvements.]]></summary></entry><entry><title type="html">UserRegistry Attribute Reader Enhancement, Jandex Index Format Support Update and more in 26.0.0.3</title><link href="https://openliberty.io/blog/2026/03/24/26.0.0.3.html" rel="alternate" type="text/html" title="UserRegistry Attribute Reader Enhancement, Jandex Index Format Support Update and more in 26.0.0.3" /><published>2026-03-24T00:00:00+00:00</published><updated>2026-03-24T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/03/24/26.0.0.3</id><content type="html" xml:base="https://openliberty.io/blog/2026/03/24/26.0.0.3.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This release introduces UserRegistry Attribute Reader APIs for retrieving user attributes from LDAP and custom registries, and adds support for Jandex index formats 11-13 to improve application startup performance. Other highlights include changes to AES encoding and fixes for security vulnerabilities and bugs.</p>
</div>
<div class="paragraph">
<p>In <a href="/">Open Liberty</a> 26.0.0.3:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#userregistry">UserRegistry Attribute Reader Enhancement</a></p>
</li>
<li>
<p><a href="#jandex">Jandex Index Format Support Update</a></p>
</li>
<li>
<p><a href="#aes">AES encoding changes</a></p>
</li>
<li>
<p><a href="#CVEs">Security Vulnerability (CVE) Fixes</a></p>
</li>
<li>
<p><a href="#bugs">Notable bug fixes</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>View the list of fixed bugs in <a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A26003+label%3A%22release+bug%22">26.0.0.3</a>.</p>
</div>
<div class="paragraph">
<p>Check out <a href="/blog/?search=release&amp;search!=beta">previous Open Liberty GA release blog posts</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run">Develop and run your apps using 26.0.0.3</h2>
<div class="sectionbody">
<div class="paragraph">
<p>If you&#8217;re using <a href="/guides/maven-intro.html">Maven</a>, include the following in your <code>pom.xml</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.12.0<span class="tag">&lt;/version&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Or for <a href="/guides/gradle-intro.html">Gradle</a>, include the following in your <code>build.gradle</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:4.0.0'
    }
}
apply plugin: 'liberty'</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or if you&#8217;re using <a href="/docs/latest/container-images.html">container images</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or take a look at our <a href="/start/">Downloads page</a>.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="https://plugins.jetbrains.com/plugin/14856-liberty-tools">IntelliJ IDEA</a>, <a href="https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext">Visual Studio Code</a> or <a href="https://marketplace.eclipse.org/content/liberty-tools">Eclipse IDE</a>, you can also take advantage of our open source <a href="https://openliberty.io/docs/latest/develop-liberty-tools.html">Liberty developer tools</a> to enable effective development, testing, debugging and application management all from within your IDE.</p>
</div>
<div class="imageblock text-center">
<div class="content">
<a class="image" href="https://stackoverflow.com/tags/open-liberty"><img src="/img/blog/blog_btn_stack.svg" alt="Ask a question on Stack Overflow"></a>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="userregistry">UserRegistry Attribute Reader Enhancement</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The UserRegistry API provides applications with the ability to retrieve specific user attributes and search for users based on attribute values directly from LDAP and custom user registries.</p>
</div>
<div class="sect2">
<h3 id="whats-new">What&#8217;s New?</h3>
<div class="paragraph">
<p>Previously, the UserRegistry API supported only basic user lookups such as searching by <code>userSecurityName</code> or by using wildcard pattern matching. However, it did not allow applications to retrieve specific user attributes or search for users based on attribute values. These capabilities were available in traditional WebSphere through the VMM API. The introduction of these two new APIs now enables applications to search for users and retrieve attributes from LDAP and custom user registries.</p>
</div>
<div class="paragraph">
<p>With this enhancement, you can now retrieve specific attributes for a user by using the <code>getAttributesForUser()</code> method. This method supports retrieval of individual attributes such as email or phoneNumber, or "*" to retrieve all available attributes for a user.</p>
</div>
<div class="paragraph">
<p>You can also search for users based on attribute values by using the <code>getUsersByAttribute()</code> method, enabling applications to locate users by matching specific attribute criteria. These methods are supported for LDAP user registries. Custom user registry implementations can also implement and support these methods.</p>
</div>
</div>
<div class="sect2">
<h3 id="how-to-use-it">How to Use It</h3>
<div class="paragraph">
<p>New API methods added to <code>UserRegistry.java</code>:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><code>default Map&lt;String, Object&gt; getAttributesForUser(String userSecurityName, Set&lt;String&gt; attributeNames)</code></p>
<div class="paragraph">
<p><strong>Description:</strong> Returns a Map&lt;String, Object&gt; containing the specified <code>attributesNames</code> and their corresponding values for the given <code>userSecurityName</code>, as configured in the LDAP user registry.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">UserRegistry ur = RegistryHelper.getUserRegistry(<span class="string"><span class="delimiter">&quot;</span><span class="content">realmName</span><span class="delimiter">&quot;</span></span>);

<span class="comment">// valid ldap attribute names</span>
<span class="predefined-type">Set</span>&lt;<span class="predefined-type">String</span>&gt; attributeNames = <span class="predefined-type">Set</span>.of(<span class="string"><span class="delimiter">&quot;</span><span class="content">telephoneNumber</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">uid</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">mail</span><span class="delimiter">&quot;</span></span>);  <span class="comment">// or &quot;*&quot; for retrieving all attributes</span>
<span class="predefined-type">Map</span>&lt;<span class="predefined-type">String</span>, <span class="predefined-type">Object</span>&gt; result = ur.getAttributesForUser(<span class="string"><span class="delimiter">&quot;</span><span class="content">testuser</span><span class="delimiter">&quot;</span></span>, attributeNames);

<span class="comment">// output in trace.log</span>
&gt; getAttributesForUser Entry
  testuser
  [telephoneNumber, uid, mail]

&lt; getAttributesForUser Exit
  {uid=testuser, mail=testuser<span class="annotation">@example</span>.com, telephoneNumber=&lt;telephone-number&gt;}</code></pre>
</div>
</div>
</li>
<li>
<p><code>default SearchResult getUsersByAttribute(String attributeName, String value, int limit)</code></p>
<div class="paragraph">
<p><strong>Description:</strong> Returns a <code>SearchResult</code> object that contains a list of users that match an <code>attributeName</code> with specified <code>value</code> that is configured in the LDAP user registry.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">UserRegistry ur = RegistryHelper.getUserRegistry(<span class="string"><span class="delimiter">&quot;</span><span class="content">realmName</span><span class="delimiter">&quot;</span></span>);

<span class="predefined-type">SearchResult</span> searchResult = ur.getUsersByAttribute(<span class="string"><span class="delimiter">&quot;</span><span class="content">email</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">testuser@example.com</span><span class="delimiter">&quot;</span></span>, <span class="integer">1</span>);

<span class="comment">// output in trace.log</span>
&gt; getUsersByAttribute Entry
  email
  testuser<span class="annotation">@example</span>.com
  <span class="integer">1</span>

&lt; getUsersByAttribute Exit
  <span class="predefined-type">SearchResult</span> hasMore=<span class="predefined-constant">false</span> [testuser]</code></pre>
</div>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>To learn more about the user registry, see the following resources:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://www.ibm.com/docs/en/was-liberty/base?topic=infrastructure-customizing-user-registries-repositories-liberty">Open Liberty Custom User Registry documentation</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/modules/reference/24.0.0.3/com.ibm.websphere.appserver.api.securityClient_1.1-javadoc/com/ibm/websphere/security/UserRegistry.html">UserRegistry API Javadoc</a></p>
</li>
<li>
<p><a href="https://openliberty.io/docs/latest/user-registries-application-security.html#_federated_user_registries">Federated User Registry configuration</a></p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jandex">Jandex Index Format Support Update</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Open Liberty now supports the latest Jandex index formats, allowing the use of Jandex indexes that are created with Jandex version 3.1.0 and later. Jandex is a space‑efficient Java annotation indexer and offline reflection library that improves application startup performance by pre‑indexing class metadata.</p>
</div>
<div class="paragraph">
<p>This feature targets application developers and DevOps engineers who work with Jakarta EE and MicroProfile applications. It is designed to optimize application startup times and reduce runtime costs.</p>
</div>
<div class="sect2">
<h3 id="whats-new-2">What&#8217;s New?</h3>
<div class="paragraph">
<p>With this update, Open Liberty supports Jandex index formats <strong>11, 12, and 13</strong>. Jandex versions 3.1.0 through the current latest version, 3.5.3, generate indexes that use these formats.</p>
</div>
<div class="paragraph">
<p>Previously, Open Liberty supported Jandex index format versions only up to and including version 10. This index format limitation meant that applications packaged with Jandex indexes could not use index formats beyond version 10 while retaining the expected performance improvements. To preserve these performance benefits, build tooling had to continue using a Jandex version prior to 3.1.0, or explicitly configure Jandex index generation to produce indexes that use index format up to and including version 10.</p>
</div>
</div>
<div class="sect2">
<h3 id="benefits">Benefits</h3>
<div class="paragraph">
<p>The added support for Jandex index formats has several benefits:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Improved Compatibility:</strong> Works seamlessly with the latest versions of build tools and frameworks that use newer Jandex versions</p>
</li>
<li>
<p><strong>Faster Startup Times:</strong> Continue to benefit from Jandex&#8217;s efficient annotation indexing without version constraints</p>
</li>
<li>
<p><strong>Reduced Maintenance:</strong> No need to maintain multiple Jandex versions or regenerate indexes for compatibility</p>
</li>
<li>
<p><strong>Future-Proof:</strong> Stay current with the Jandex ecosystem as it evolves</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="limitations">Limitations</h3>
<div class="paragraph">
<p><strong>When using Jandex indexes, ensure that the index files are kept up to date with the application classes.</strong> If a Jandex index is not synchronized with the application classes, it can contain incorrect annotation data, which can cause the application to function incorrectly. Out‑of‑date Jandex indexes cannot be reliably detected.</p>
</div>
<div class="paragraph">
<p>Open Liberty does not read index formats higher than index format 13. If a new version of Jandex adds a higher index format version, Open Liberty requires an update before it can read Jandex indexes that use the higher index format version.</p>
</div>
<div class="paragraph">
<p>The Open Liberty feature <code>mpGraphQL</code>, which is obtained from an external source, is limited to reading Jandex index formats no higher than index format 10. If the feature <code>mpGraphQL</code> is used, Jandex indexes should be generated by using index format 10. This limitation applies to all current versions of <code>mpGraphQL</code>, including the current highest version, <code>mpGraphQL-2.0</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="lifting-restriction">Lifting Restriction</h3>
<div class="paragraph">
<p>Previously, when Jandex usage was enabled and an application included Jandex indexes that used formats 11 through 13, Open Liberty displayed an error message and ignored those indexes. In such cases, annotation scanning was performed by using Liberty’s internal annotation scanning mechanism.</p>
</div>
<div class="paragraph">
<p>With the addition of support for Jandex index formats 11 through 13, Open Liberty now uses indexes that are generated in these formats. These indexes must be kept up to date with the application classes. Ensure that the Jandex indexes packaged with your application accurately reflect the current application classes.</p>
</div>
</div>
<div class="sect2">
<h3 id="how-to-use">How to Use</h3>
<div class="paragraph">
<p>No configuration changes are required in the <code>server.xml</code> file to enable support for the new Jandex index formats. Open Liberty automatically detects the Jandex index format and selects the appropriate index reader for that format. It reads indexes that use formats 11, 12, and 13, and continues to support indexes that use format up to version 10.</p>
</div>
<div class="paragraph">
<p>By default, Jandex usage is disabled. To enable Jandex, set the <code>useJandex</code> property to <code>true</code> in either an <code>application</code> element or the <code>applicationManager</code> element.</p>
</div>
<div class="paragraph">
<p>If you are generating Jandex indexes as part of your build process, you can now use the latest Jandex Maven plugin or Gradle plugin versions:</p>
</div>
<div class="paragraph">
<p><strong>Maven Example:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.smallrye<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>jandex-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.5.3<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;executions&gt;</span>
        <span class="tag">&lt;execution&gt;</span>
            <span class="tag">&lt;id&gt;</span>make-index<span class="tag">&lt;/id&gt;</span>
            <span class="tag">&lt;goals&gt;</span>
                <span class="tag">&lt;goal&gt;</span>jandex<span class="tag">&lt;/goal&gt;</span>
            <span class="tag">&lt;/goals&gt;</span>
        <span class="tag">&lt;/execution&gt;</span>
    <span class="tag">&lt;/executions&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Gradle Example:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">plugins {
    id 'org.kordamp.gradle.jandex' version '2.3.0'
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Open Liberty automatically detects and recognizes the generated <code>META-INF/jandex.idx</code> file for any supported index format version.</p>
</div>
<div class="paragraph">
<p>For more information, see the <a href="https://smallrye.io/jandex/jandex/3.5.3/index.html">Jandex Documentation</a></p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="aes">AES encoding changes</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>securityUtility encode</code> command now requires a key to be specified for AES encodings. Specify a key by including one of the following options: <code>--key</code>, <code>--base64Key</code>, <code>--aesConfigFile</code>, or <code>--keyring</code>. This update resolves <a href="https://www.ibm.com/support/pages/node/7261638">CVE-2025-14923</a>.</p>
</div>
<div class="paragraph">
<p>The following command now results in an error because a key is not specified in the command.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="bash">securityUtility encode --encoding=aes &quot;password&quot;

When using AES encoding, one of the following arguments must be specified: --key, --base64Key, --aesConfigFile, or --keyring.</code></pre>
</div>
</div>
<div class="paragraph">
<p>The following is an example of a valid usage with the new requirement.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="bash">securityUtility encode --encoding=aes --key=mycustomkey &quot;password&quot;
{aes}ARArmkfkgGyE1eiN8mKKjnkUDrFUFuuq2FlpDqrJKBgTAEYeN+PLP45wChLvIhlnWEDHnSA4zJI9KA3k5R9e/QDC+O2tzr3EwD3IMMAfvfOYxxqNPmoXqIeRVPD8TPZWnIIPmCnvyROw5A8=</code></pre>
</div>
</div>
<div class="paragraph">
<p>For more information, see the full documentation for <a href="https://openliberty.io/docs/latest/reference/command/securityUtility-encode.html">securityUtility encode</a> and <a href="https://openliberty.io/docs/latest/password-encryption.html">password encryption</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="CVEs">Security vulnerability (CVE) fixes in this release</h2>
<div class="sectionbody">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">CVE</th>
<th class="tableblock halign-left valign-top">CVSS Score</th>
<th class="tableblock halign-left valign-top">Vulnerability Assessment</th>
<th class="tableblock halign-left valign-top">Versions Affected</th>
<th class="tableblock halign-left valign-top">Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2025-14923">CVE-2025-14923</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">4.7</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Weaker security</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-26.0.0.2</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2024-29371">CVE-2024-29371</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">7.5</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Denial of service</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">21.0.0.3-26.0.0.2</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Affects the <code>openidConnectClient-1.0</code>, <code>socialLogin-1.0</code>, <code>mpJwt-1.2</code>, <code>mpJwt-2.0</code>, <code>mpJwt-2.1</code>, and <code>jwt-1.0</code> features</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>For a list of past security vulnerability fixes, reference the <a href="/docs/latest/security-vulnerabilities.html">Security vulnerability (CVE) list</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="bugs">Notable bugs fixed in this release</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We’ve spent some time fixing bugs. The following sections describe some of the issues resolved in this release. If you’re interested, here’s the <a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A26003+label%3A%22release+bug%22">full list of bugs fixed in 26.0.0.3</a>.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/34017">Missing error message in JMX REST client</a></p>
</li>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/34052">NullPointerException resurfaced in Open Liberty due to removal of EclipseLink 2.7.16 fix</a></p>
</li>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/34171">IBM WebSphere Application Server Liberty is affected by a denial of service due to jose4j (CVE-2024-29371 CVSS 7.5)</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="get-open-liberty-26-0-0-3-now">Get Open Liberty 26.0.0.3 now</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Available through <a href="#run">Maven, Gradle, Docker, and as a downloadable archive</a>.</p>
</div>
</div>
</div>]]></content><author><name>Navaneeth S Nair</name></author><category term="blog" /><category term="announcements" /><category term="microprofile" /><category term="java-se" /><category term="release" /><category term="security" /><category term="jakarta-ee" /><category term="performance-enhancements" /></entry><entry><title type="html">Model Context Protocol Server 1.0 updates in 26.0.0.3-beta</title><link href="https://openliberty.io/blog/2026/03/10/26.0.0.3-beta.html" rel="alternate" type="text/html" title="Model Context Protocol Server 1.0 updates in 26.0.0.3-beta" /><published>2026-03-10T00:00:00+00:00</published><updated>2026-03-10T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/03/10/26.0.0.3-beta</id><content type="html" xml:base="https://openliberty.io/blog/2026/03/10/26.0.0.3-beta.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>The 26.0.0.3-beta release updates the <code>mcpServer-1.0</code> feature with response encoders and provides request ID access to tools for logging and auditing.</p>
</div>
<div class="paragraph">
<p>The <a href="/">Open Liberty</a> 26.0.0.3-beta includes the following beta features (along with <a href="/docs/latest/reference/feature/feature-overview.html">all GA features</a>):</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#encoders">Encode responses with ContentEncoder and ToolResponseEncoder</a></p>
</li>
<li>
<p><a href="#requestid">Access the request ID from a tool</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The <a href="https://modelcontextprotocol.io/docs/getting-started/intro">Model Context Protocol (MCP)</a> is an open standard that enables AI applications to access real-time information from external sources. The Liberty MCP Server feature (<code>mcpServer-1.0</code>) allows developers to expose the business logic of their applications, allowing it to be integrated into agentic AI workflows.</p>
</div>
<div class="paragraph">
<p>See also <a href="/blog/?search=beta&amp;key=tag">previous Open Liberty beta blog posts</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="encoders">Encode responses with ContentEncoder and ToolResponseEncoder</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When a client calls a tool, the object that is returned by the tool method is converted to a <code>ToolResponse</code>, which usually contains one or more <code>Content</code> objects. The <code>ToolResponse</code> maps directly to the result returned in the response.</p>
</div>
<div class="paragraph">
<p>If you need more control over the response from your tool, you can return a <code>ToolResponse</code> or <code>Content</code> object directly. Now, it is also possible to register encoders to control how other objects are converted into a response.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Use <code>ToolResponseEncoder</code> to convert an object into a <code>ToolResponse</code>, which gives you complete control over the whole response.</p>
</li>
<li>
<p>Use <code>ContentEncoder</code> when you only need to convert an object into a <code>Content</code> that is included in the response. You can also return a list of objects, and each object is individually converted into a <code>Content</code> and included in the response.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>If a tool method returns an object for which no encoder is provided, JSON-B encodes the object as JSON, which is returned as text content.</p>
</div>
<div class="sect2">
<h3 id="example">Example</h3>
<div class="paragraph">
<p>Consider a tool that does a search over some datastore:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Tool</span>(description = <span class="string"><span class="delimiter">&quot;</span><span class="content">search the data store</span><span class="delimiter">&quot;</span></span>)
<span class="directive">public</span> <span class="predefined-type">SearchResult</span> search(<span class="annotation">@ToolArg</span>(name=<span class="string"><span class="delimiter">&quot;</span><span class="content">query</span><span class="delimiter">&quot;</span></span>, description=<span class="string"><span class="delimiter">&quot;</span><span class="content">the query to run</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> query) {
    <span class="predefined-type">SearchResult</span> result = datastore.runQuery(query);
    <span class="keyword">return</span> result;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>In this scenario, the <code>SearchResult</code> object encapsulates a list of individual results. Each entry contains a summary, associated metadata, and a relevance score that indicates its relationship to the query.</p>
</div>
<div class="paragraph">
<p>By default, the <code>SearchResult</code> object that is returned is encoded as JSON by using JSON-B and placed into a <code>TextContent</code>. However, to return each search result summary as an individual <code>TextContent</code> and map the relevance score to a priority annotation, a <code>ToolResponseEncoder</code> is to be used.</p>
</div>
<div class="paragraph">
<p>Create a CDI bean that implements the <code>ToolResponseEncoder</code> interface and implement:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>the <code>encode</code> method to create a <code>ToolResponse</code> from a <code>SearchResult</code></p>
</li>
<li>
<p>the <code>supports</code> method to indicate that your encoder can be used for any <code>SearchResult</code></p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span>
<span class="directive">public</span> <span class="type">class</span> <span class="class">SearchResultEncoder</span> <span class="directive">implements</span> ToolResponseEncoder&lt;<span class="predefined-type">SearchResult</span>&gt; {

    <span class="directive">public</span> <span class="type">boolean</span> supports(<span class="predefined-type">Class</span>&lt;?&gt; runtimeType) {
        <span class="comment">// This encoder can encode SearchResult and any subtypes</span>
        <span class="keyword">return</span> <span class="predefined-type">SearchResult</span>.class.isAssignableFrom(runtimeType);
    }

    <span class="directive">public</span> ToolResponse encode(<span class="predefined-type">SearchResult</span> searchResult) {
        <span class="keyword">if</span> (searchResult.results().isEmpty()) {
            <span class="keyword">return</span> ToolResponse.error(<span class="string"><span class="delimiter">&quot;</span><span class="content">No results</span><span class="delimiter">&quot;</span></span>);
        }

        <span class="predefined-type">ArrayList</span>&lt;TextContent&gt; contents = <span class="keyword">new</span> <span class="predefined-type">ArrayList</span>&lt;&gt;();
        <span class="keyword">for</span> (<span class="type">var</span> result : searchResult.results()) {
            <span class="comment">// Set the priority annotation based on the relevance</span>
            Annotations annotations = <span class="keyword">new</span> Annotations(<span class="predefined-constant">null</span>, <span class="predefined-constant">null</span>, result.relevance());
            <span class="comment">// Create a TextContent from the summary, and add the annotations</span>
            contents.add(<span class="keyword">new</span> TextContent(result.summary(), <span class="predefined-constant">null</span>, annotations));
        }

        <span class="comment">// Create a successful response, using the created TextContents</span>
        <span class="keyword">return</span> ToolResponse.success(contents);
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This encoder is used for any tools in the application that return a <code>SearchResult</code></p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="requestid">Access the request ID from a tool</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Each request from an MCP client includes a unique session-based Request ID, which is now accessible to tools and is useful for logging and auditing.</p>
</div>
<div class="paragraph">
<p>To access the ID, add a <code>RequestId</code> parameter to the tool method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Tool</span>(description = <span class="string"><span class="delimiter">&quot;</span><span class="content">search the data store</span><span class="delimiter">&quot;</span></span>)
<span class="directive">public</span> <span class="predefined-type">SearchResult</span> search(<span class="annotation">@ToolArg</span>(name=<span class="string"><span class="delimiter">&quot;</span><span class="content">query</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> query, RequestId requestId) {
    logger.log(INFO, <span class="string"><span class="delimiter">&quot;</span><span class="content">Running search (</span><span class="delimiter">&quot;</span></span> + requestId.asString() + <span class="string"><span class="delimiter">&quot;</span><span class="content">) for query: </span><span class="delimiter">&quot;</span></span> + query);
    <span class="comment">// ....</span>
}</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="notable-bug-fixes">Notable bug fixes</h3>
<div class="paragraph">
<p>The following bugs have been fixed:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Output schemas were not generated correctly for asynchronous tool methods which have <code>structuredContent = true</code></p>
</li>
<li>
<p>Omitting the <code>arguments</code> object when calling a tool would result in an error. The <code>arguments</code> object is optional if the tool does not require any arguments</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="run">Try it now</h3>
<div class="paragraph">
<p>To try out these features, update your build tools to pull the Open Liberty All Beta Features package instead of the main release. To enable the MCP server feature, follow the instructions from <a href="https://openliberty.io/blog/2025/10/23/mcp-standalone-blog.html">MCP standalone blog</a>. The beta works with Java SE 25, Java SE 21, Java SE 17, Java SE 11, and Java SE 8.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="/guides/maven-intro.html">Maven</a>, you can install the All Beta Features package using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.12.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;configuration&gt;</span>
        <span class="tag">&lt;runtimeArtifact&gt;</span>
          <span class="tag">&lt;groupId&gt;</span>io.openliberty.beta<span class="tag">&lt;/groupId&gt;</span>
          <span class="tag">&lt;artifactId&gt;</span>openliberty-runtime<span class="tag">&lt;/artifactId&gt;</span>
          <span class="tag">&lt;version&gt;</span>26.0.0.3-beta<span class="tag">&lt;/version&gt;</span>
          <span class="tag">&lt;type&gt;</span>zip<span class="tag">&lt;/type&gt;</span>
        <span class="tag">&lt;/runtimeArtifact&gt;</span>
    <span class="tag">&lt;/configuration&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You must also add dependencies to your <code>pom.xml</code> file for the beta version of the APIs that are associated with the beta features that you want to try. For example, the following block adds dependencies for two example beta APIs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>org.example.spec<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>exampleApi<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>7.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;type&gt;</span>pom<span class="tag">&lt;/type&gt;</span>
    <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
<span class="tag">&lt;/dependency&gt;</span>
<span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>example.platform<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>example.example-api<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>11.0.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
<span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Or for <a href="/guides/gradle-intro.html">Gradle</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.10.0'
    }
}
apply plugin: 'liberty'
dependencies {
    libertyRuntime group: 'io.openliberty.beta', name: 'openliberty-runtime', version: '[26.0.0.3-beta,)'
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or if you&#8217;re using <a href="/docs/latest/container-images.html">container images</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty:beta</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or take a look at our <a href="/downloads/#runtime_betas">Downloads page</a>.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="https://plugins.jetbrains.com/plugin/14856-liberty-tools">IntelliJ IDEA</a>, <a href="https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext">Visual Studio Code</a> or <a href="https://marketplace.eclipse.org/content/liberty-tools">Eclipse IDE</a>, you can also take advantage of our open source <a href="https://openliberty.io/docs/latest/develop-liberty-tools.html">Liberty developer tools</a> to enable effective development, testing, debugging and application management all from within your IDE.</p>
</div>
<div class="paragraph">
<p>For more information on using a beta release, refer to the <a href="docs/latest/installing-open-liberty-betas.html">Installing Open Liberty beta releases</a> documentation.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="feedback">We welcome your feedback</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let us know what you think on <a href="https://groups.io/g/openliberty">our mailing list</a>. If you hit a problem, <a href="https://stackoverflow.com/questions/tagged/open-liberty">post a question on StackOverflow</a>. If you hit a bug, <a href="https://github.com/OpenLiberty/open-liberty/issues">please raise an issue</a>.</p>
</div>
</div>
</div>]]></content><author><name>Ismath Badsha</name></author><category term="blog" /><category term="announcements" /><category term="release" /><category term="beta" /><summary type="html"><![CDATA[The 26.0.0.3-beta release updates the mcpServer-1.0 feature with response encoders and provides request ID access to tools for logging and auditing.]]></summary></entry><entry><title type="html">Support for Java Toolchains in Liberty Build Plugins</title><link href="https://openliberty.io/blog/2026/03/02/java-toolchains-in-liberty-build-plugins.html" rel="alternate" type="text/html" title="Support for Java Toolchains in Liberty Build Plugins" /><published>2026-03-02T00:00:00+00:00</published><updated>2026-03-02T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/03/02/java-toolchains-in-liberty-build-plugins</id><content type="html" xml:base="https://openliberty.io/blog/2026/03/02/java-toolchains-in-liberty-build-plugins.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Liberty Gradle and Maven plugins now support <strong>Java Toolchains</strong>. This feature allows you to decouple the JDK used to run your build tool (Gradle or Maven) from the JDK used to compile your code and run your Liberty server and applications.</p>
</div>
<div class="paragraph">
<p>When a toolchain is configured, the Liberty build plugins automatically detect the specified JDK and use it to start the Liberty server, ensuring environment consistency across your development team.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="why-use-java-toolchains">Why use Java Toolchains?</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Using Java toolchains provides several advantages for enterprise development and CI/CD pipelines:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Environment Consistency</strong>: Ensure every developer and build server uses the exact same JDK version for the runtime, regardless of what is installed as the system default.</p>
</li>
<li>
<p><strong>Decoupling</strong>: You can run your build tool (e.g., Maven or Gradle) on a newer, high-performance JVM while targeting an older JDK (like Java 8 or 11) for the actual Liberty server.</p>
</li>
<li>
<p><strong>Simplified Configuration</strong>: Avoid manually setting and maintaining <code>JAVA_HOME</code> environment variables across different machines. The build tool handles the discovery and provisioning of the required JDK.</p>
</li>
<li>
<p><strong>Early Detection</strong>: If a developer tries to build a project but lacks the required JDK version, the build tool will provide a clear error or automatically download the correct version (depending on your configuration).</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="minimum-version-requirements">Minimum Version Requirements</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To use toolchain support, ensure you are using the following plugin versions or newer:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Liberty Maven Plugin</strong>: <a href="https://central.sonatype.com/artifact/io.openliberty.tools/liberty-maven-plugin/3.12.0">3.12.0</a></p>
</li>
<li>
<p><strong>Liberty Gradle Plugin</strong>: <a href="https://central.sonatype.com/artifact/io.openliberty.tools/liberty-gradle-plugin/3.10.0">3.10.0</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="liberty-gradle-plugin-support">Liberty Gradle Plugin Support</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The Liberty Gradle plugin integrates with the standard <a href="https://docs.gradle.org/current/userguide/toolchains.html">Gradle Java Toolchain</a> feature. It does not require a Liberty-specific configuration block; it automatically honors the project&#8217;s <code>java { toolchain { &#8230;&#8203; } }</code> settings.</p>
</div>
<div class="sect2">
<h3 id="how-to-use">How to use</h3>
<div class="paragraph">
<p>Apply the <code>java</code> plugin and define the desired Java version in your <code>build.gradle</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">plugins {
    id 'java'
    id 'io.openliberty.tools.gradle.Liberty' version '3.10.0'
}

java {
    toolchain {
        // Required Java version for your project
        languageVersion = JavaLanguageVersion.of(17)
        // Optional: include vendor if you need to distinguish between toolchains
        // vendor.set(JvmVendorSpec.ADOPTIUM)
    }
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="liberty-maven-plugin-support">Liberty Maven Plugin Support</h2>
<div class="sectionbody">
<div class="paragraph">
<p>By leveraging Maven Toolchains, the Liberty Maven plugin can decouple the JDK used to run the plugin from the JDK used to run your Liberty server. It retrieves these definitions from your local <code>toolchains.xml</code>.</p>
</div>
<div class="sect2">
<h3 id="how-to-use-2">How to use</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Configure toolchains.xml</strong>: Ensure your <code>~/.m2/toolchains.xml</code> defines the JDKs available on your system.</p>
</li>
<li>
<p><strong>Update pom.xml</strong>: Configure the plugin versions in your <code>liberty-maven-plugin</code> configurations and add a <code>&lt;jdkToolchain&gt;</code> configuration.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.12.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;configuration&gt;</span>
        <span class="tag">&lt;jdkToolchain&gt;</span>
            <span class="tag">&lt;version&gt;</span>11<span class="tag">&lt;/version&gt;</span>
             <span class="comment">&lt;!-- Optional: include vendor if you need to distinguish between toolchains --&gt;</span>
             <span class="comment">&lt;!-- &lt;vendor&gt;ibm&lt;/vendor&gt; --&gt;</span>
        <span class="tag">&lt;/jdkToolchain&gt;</span>
    <span class="tag">&lt;/configuration&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="dev-mode-behavior">Dev mode behavior</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When you run <code>gradle libertyDev</code> or <code>mvn liberty:dev</code>, the plugin ensures environment consistency by applying the following logic:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong>Server JVM</strong>: Sets the Liberty server process&#8217;s <code>JAVA_HOME</code> to the configured toolchain JDK.</p>
</li>
<li>
<p><strong>Recompilation</strong>: Automatically uses the toolchain JDK for compilation (e.g., <code>compileJava</code> and <code>compileTestJava</code> tasks in Gradle, or <code>compiler:compile</code> and <code>compiler:testCompile</code> goals in Maven).</p>
</li>
<li>
<p><strong>Logs</strong>: Look for confirmation in the terminal output to verify the toolchain is active:</p>
</li>
</ul>
</div>
<div class="hdlist">
<table>
<tr>
<td class="hdlist1">
Gradle
</td>
<td class="hdlist2">
<p><code>CWWKM4101I: The :libertyDev task is using the configured toolchain JDK located at /path/to/jdk-17</code></p>
</td>
</tr>
<tr>
<td class="hdlist1">
Maven
</td>
<td class="hdlist2">
<p><code>CWWKM4101I: The liberty:dev goal is using the configured toolchain JDK located at /path/to/jdk-17</code></p>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="rules-and-precedence">Rules and precedence</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Both plugins follow a specific order of operations:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><strong>Manual Overrides</strong>: If <code>JAVA_HOME</code> is set in <code>server.env</code> or <code>jvm.options</code>, <strong>that value takes precedence</strong> over the Java toolchain.</p>
</li>
<li>
<p><strong>Toolchain Resolution</strong>: If no manual override exists, the plugin uses the resolved toolchain JDK.</p>
</li>
<li>
<p><strong>Fallback</strong>: If no toolchain is found, the plugin falls back to the JVM currently running the build.</p>
</li>
</ol>
</div>
</div>
</div>
<div class="sect1">
<h2 id="verification">Verification</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To confirm which JDK the Liberty server started with, check the <code>messages.log</code> file (located in <code>${server.output.dir}/logs/</code>). You should see entries similar to the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="text">********************************************************************************
product = Open Liberty 25.0.0.12 (wlp-1.0.108.cl251220251117-0302)
wlp.install.dir = /path/to/project/build/wlp/
java.home = /path/to/java/semeru-11.0.28/Contents/Home
java.version = 11.0.28
java.runtime = IBM Semeru Runtime Open Edition (11.0.28+6)
os = Mac OS X (26.1; aarch64) (en_IN)
process = 62955@Device-Name.local
Classpath = /path/to/project/build/wlp/bin/tools/ws-server.jar
Java Library path = /path/to/java/semeru-11.0.28/Contents/Home/lib/default:/path/to/java/semeru-11.0.28/Contents/Home/lib:/usr/lib
********************************************************************************</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>With Java toolchain support in the Liberty Gradle and Maven plugins, managing your development environment becomes significantly more robust. By defining your Java version at the project level, you eliminate the "it works on my machine" class of bugs related to mismatched JDKs. Whether you are using Gradle&#8217;s automatic provisioning or Maven&#8217;s toolchain manager, your Liberty server will now stay in perfect sync with your source code&#8217;s requirements.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="further-documentation">Further Documentation</h2>
<div class="sectionbody">
<div class="paragraph">
<p>For detailed technical specifications, refer to the <code>toolchains.md</code> documentation in the plugin repositories:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Liberty Gradle Plugin: <a href="https://github.com/OpenLiberty/ci.gradle/blob/main/docs/toolchain.md">toolchain.md</a></p>
</li>
<li>
<p>Liberty Maven Plugin: <a href="https://github.com/OpenLiberty/ci.maven/blob/main/docs/toolchain.md">toolchain.md</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="reporting-issues">Reporting Issues</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We welcome feedback and contributions! If you encounter any bugs or have feature requests, please report them in our open-source repositories:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>For Maven issues, visit the <a href="https://github.com/OpenLiberty/ci.maven/issues">Liberty Maven Plugin GitHub Issues</a>.</p>
</li>
<li>
<p>For Gradle issues, visit the <a href="https://github.com/OpenLiberty/ci.gradle/issues">Liberty Gradle Plugin GitHub Issues</a>.</p>
</li>
</ul>
</div>
</div>
</div>]]></content><author><name>Arun Venmany</name></author><category term="blog" /></entry><entry><title type="html">Java Toolchains in Liberty Build Plugins in 26.0.0.2</title><link href="https://openliberty.io/blog/2026/02/24/26.0.0.2.html" rel="alternate" type="text/html" title="Java Toolchains in Liberty Build Plugins in 26.0.0.2" /><published>2026-02-24T00:00:00+00:00</published><updated>2026-02-24T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/02/24/26.0.0.2</id><content type="html" xml:base="https://openliberty.io/blog/2026/02/24/26.0.0.2.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This release introduces Java Toolchains support, enabling developers to decouple the JDK used to run build tools from the JDK used to run the Liberty server.</p>
</div>
<div class="paragraph">
<p>In <a href="/">Open Liberty</a> 26.0.0.2:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#java_toolchains">Java Toolchains in Liberty Build Plugins</a></p>
</li>
<li>
<p><a href="#CVEs">Security Vulnerability (CVE) Fixes</a></p>
</li>
<li>
<p><a href="#bugs">Notable bug fixes</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>View the list of fixed bugs in <a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A26002+label%3A%22release+bug%22">26.0.0.2</a>.</p>
</div>
<div class="paragraph">
<p>Check out <a href="/blog/?search=release&amp;search!=beta">previous Open Liberty GA release blog posts</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run">Develop and run your apps using 26.0.0.2</h2>
<div class="sectionbody">
<div class="paragraph">
<p>If you&#8217;re using <a href="/guides/maven-intro.html">Maven</a>, include the following in your <code>pom.xml</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.12.0<span class="tag">&lt;/version&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Or for <a href="/guides/gradle-intro.html">Gradle</a>, include the following in your <code>build.gradle</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.10.0'
    }
}
apply plugin: 'liberty'</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or if you&#8217;re using <a href="/docs/latest/container-images.html">container images</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or take a look at our <a href="/start/">Downloads page</a>.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="https://plugins.jetbrains.com/plugin/14856-liberty-tools">IntelliJ IDEA</a>, <a href="https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext">Visual Studio Code</a> or <a href="https://marketplace.eclipse.org/content/liberty-tools">Eclipse IDE</a>, you can also take advantage of our open source <a href="https://openliberty.io/docs/latest/develop-liberty-tools.html">Liberty developer tools</a> to enable effective development, testing, debugging and application management all from within your IDE.</p>
</div>
<div class="imageblock text-center">
<div class="content">
<a class="image" href="https://stackoverflow.com/tags/open-liberty"><img src="/img/blog/blog_btn_stack.svg" alt="Ask a question on Stack Overflow"></a>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="java_toolchains">Java Toolchains in Liberty Build Plugins</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In the latest release of the Liberty build plugins, support has been added for Java Toolchains. This enhancement enables developers to decouple the JDK used to run their build tools (Maven or Gradle) from the JDK used to run the Liberty server and their applications. This provides greater flexibility and environmental consistency.</p>
</div>
<div class="sect2">
<h3 id="java-toolchains-support">Java Toolchains support</h3>
<div class="paragraph">
<p>The Liberty build plugins now support the standard Java Toolchain mechanism.
Previously, Liberty plugins were restricted to using the same Java version that was running Maven or Gradle.
This prevented developers from using more recent JDK versions for their build process if their applications required a specific older JDK version.</p>
</div>
<div class="paragraph">
<p>With Java Toolchains, you can now run your build tool on a modern JDK (for example, Java 25). At the same time, Liberty servers and all server operations can execute using a different, configured JDK (for example, Java 8).</p>
</div>
</div>
<div class="sect2">
<h3 id="maven-plugin-integration">Maven Plugin integration</h3>
<div class="paragraph">
<p>The Liberty Maven Plugin now integrates seamlessly with the maven-toolchain-plugin as of version 3.12.0.
To use this feature, define your available JDKs in your <code>~/.m2/toolchains.xml</code> file and then configure <code>&lt;jdkToolchain&gt;</code> tag in <code>&lt;configuration&gt;</code>.
The plugin automatically detects and uses the toolchain specified in your project’s <code>pom.xml</code> file.</p>
</div>
<div class="paragraph">
<p>For detailed configuration steps and parameters, see the <a href="https://github.com/OpenLiberty/ci.maven/blob/main/docs/toolchain.md">Liberty Maven Plugin Toolchain documentation</a>.</p>
</div>
<div class="paragraph">
<p>The plugin acknowledges the JDK vendor and version constraints that are defined in your Maven profiles, helping to ensure that your server environment remains consistent across different developer machines and CI/CD pipelines.</p>
</div>
</div>
<div class="sect2">
<h3 id="gradle-plugin-integration">Gradle Plugin integration</h3>
<div class="paragraph">
<p>The Liberty Gradle plugin now recognizes the native <code>java { toolchain { &#8230;&#8203; } }</code> configuration block as of version 3.10.0. This configuration provides a unified way to manage Java versions across multi-project builds, where different services might have different runtime requirements.</p>
</div>
<div class="paragraph">
<p>For detailed configuration steps and parameters, see the <a href="https://github.com/OpenLiberty/ci.gradle/blob/main/docs/toolchain.md">Liberty Gradle Plugin Toolchain documentation</a>.</p>
</div>
<div class="paragraph">
<p>When a toolchain is configured in your <code>build.gradle</code>, the Liberty plugin uses that specific Java runtime for all server-related tasks (for example, <code>libertyDev</code> and <code>libertyStart</code>).</p>
</div>
</div>
<div class="sect2">
<h3 id="try-it-now">Try it now</h3>
<div class="paragraph">
<p>To start using Java Toolchains, update your build tools to the latest versions of the Liberty Maven or Gradle plugins.</p>
</div>
<div class="paragraph">
<p><strong>For Maven:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.12.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;configuration&gt;</span>
        <span class="tag">&lt;jdkToolchain&gt;</span>
            <span class="tag">&lt;version&gt;</span>11<span class="tag">&lt;/version&gt;</span>
            <span class="comment">&lt;!-- Optional: include vendor if you need to distinguish between toolchains --&gt;</span>
             <span class="comment">&lt;!-- &lt;vendor&gt;ibm&lt;/vendor&gt; --&gt;</span>
        <span class="tag">&lt;/jdkToolchain&gt;</span>
    <span class="tag">&lt;/configuration&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>For Gradle:</strong></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.10.0'
    }
}
apply plugin: 'liberty'


java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
        // Optional: specify vendor
        // vendor = JvmVendorSpec.ADOPTIUM
    }
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="CVEs">Security vulnerability (CVE) fixes in this release</h2>
<div class="sectionbody">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">CVE</th>
<th class="tableblock halign-left valign-top">CVSS Score</th>
<th class="tableblock halign-left valign-top">Vulnerability Assessment</th>
<th class="tableblock halign-left valign-top">Versions Affected</th>
<th class="tableblock halign-left valign-top">Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2025-14914">CVE-2025-14914</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">7.6</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Remote code execution</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-26.0.0.1</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Affects the <code>restConnector-2.0</code> feature</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>For a list of past security vulnerability fixes, reference the <a href="/docs/latest/security-vulnerabilities.html">Security vulnerability (CVE) list</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="bugs">Notable bugs fixed in this release</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We’ve spent some time fixing bugs. The following sections describe the issues resolved in this release. If you’re interested, here’s the <a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A26002+label%3A%22release+bug%22">full list of bugs fixed in 26.0.0.2</a>.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/33927">IBM WebSphere Application Server Liberty is affected by a remote code execution vulnerability (CVE-2025-14914 CVSS 7.6)</a></p>
</li>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/32996">"WARNING: package sun.security.action not in java.base" shows up in console.log starting in Java 24</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="get-open-liberty-26-0-0-2-now">Get Open Liberty 26.0.0.2 now</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Available through <a href="#run">Maven, Gradle, Docker, and as a downloadable archive</a>.</p>
</div>
</div>
</div>]]></content><author><name>Navaneeth S Nair</name></author><category term="blog" /><category term="announcements" /><category term="release" /><category term="maven" /><category term="gradle" /><category term="java-ee" /></entry><entry><title type="html">Model Context Protocol Server 1.0 updates and more in 26.0.0.2-beta</title><link href="https://openliberty.io/blog/2026/02/10/26.0.0.2-beta.html" rel="alternate" type="text/html" title="Model Context Protocol Server 1.0 updates and more in 26.0.0.2-beta" /><published>2026-02-10T00:00:00+00:00</published><updated>2026-02-10T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/02/10/26.0.0.2-beta</id><content type="html" xml:base="https://openliberty.io/blog/2026/02/10/26.0.0.2-beta.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This beta release enhances the <code>mcpServer-1.0</code> feature with role-based authorization, the new <code>_meta</code> field, and key bug fixes. It also adds documentation and tests for <code>displayCustomizedExceptionText</code>, allowing users to replace default Liberty error messages with clearer, custom text.</p>
</div>
<div class="paragraph">
<p>The <a href="/">Open Liberty</a> 26.0.0.2-beta includes the following beta features (along with <a href="/docs/latest/reference/feature/feature-overview.html">all GA features</a>):</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#mcp">Model Context Protocol Server 1.0 updates</a></p>
</li>
<li>
<p><a href="#displayCustomizedExceptionText">displayCustomizedExceptionText property</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>See also <a href="/blog/?search=beta&amp;key=tag">previous Open Liberty beta blog posts</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="mcp">Model Context Protocol Server 1.0 updates</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <a href="https://modelcontextprotocol.io/docs/getting-started/intro">Model Context Protocol (MCP)</a> is an open standard that enables AI applications to access real-time information from external sources. The Liberty MCP Server feature (<code>mcpServer-1.0</code>) allows developers to expose the business logic of their applications, allowing it to be integrated into agentic AI workflows.</p>
</div>
<div class="paragraph">
<p>This beta release of Open Liberty includes important updates to the <code>mcpServer-1.0</code> feature including role-based authorization, the <code>_meta</code> field, and a few bug fixes.</p>
</div>
<div class="sect2">
<h3 id="prerequisites">Prerequisites</h3>
<div class="paragraph">
<p>To use the <code>mcpServer-1.0</code> feature, Java 17 or later must be installed on the system.</p>
</div>
</div>
<div class="sect2">
<h3 id="implement-role-based-authorization-for-mcp-tools-via-annotations">Implement role-based authorization for MCP tools via annotations</h3>
<div class="paragraph">
<p>The following new annotations allow you to restrict tool usage through authorization policies:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><code>@DenyAll</code> - Resource is denied. This annotation is the strictest policy.</p>
</li>
<li>
<p><code>@RolesAllowed</code> - Resource is allowed for pre-authorised users in a role (the same as a group in Liberty).</p>
</li>
<li>
<p><code>@PermitAll</code> - Resource is allowed for anyone (even unauthenticated users).</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>These security annotations are declared on two levels:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Class level - Every method in the class inherits this class level annotation.</p>
</li>
<li>
<p>Method level - Overrides any class level annotations.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>For complete reference documentation, see the <a href="https://jakarta.ee/specifications/security/">Jakarta Security Annotations specification</a>.</p>
</div>
<div class="paragraph">
<p>The <code>mcpServer-1.0</code> feature does not currently implement all of the <a href="https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization#authorization-server-metadata-discovery">authorization-server-metadata-discovery requirements</a> specified in the MCP specification. However, you can use any of Liberty&#8217;s <a href="https://openliberty.io/docs/latest/authentication.html">authentication and authorization mechanisms</a> to authenticate users and assign roles. The <code>mcpServer-1.0</code> feature can then ensure that users can access only the tools that are permitted for their assigned roles.</p>
</div>
<div class="sect3">
<h4 id="basic-authorization-example">Basic authorization example</h4>
<div class="paragraph">
<p>The following example shows how to configure MCP tools to require authentication and to ensure that users have the appropriate roles to access specific tools. Users authenticate using Basic Authentication, and the list of users and their roles are configured in a basicRegistry in the <code>server.xml</code> file.</p>
</div>
<div class="paragraph">
<p>Consider an online bookshop that has different users each with different authorization levels:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Users - can buy books and track prices</p>
</li>
<li>
<p>Moderators - can manage the books available</p>
</li>
<li>
<p>Admins - can manually ban users</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Clients who connect without authenticating can only display the available books or register as a new user.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="comment">// common imports for all classes below</span>

<span class="keyword">import</span> <span class="include">io.openliberty.mcp.annotations.Tool</span>;
<span class="keyword">import</span> <span class="include">io.openliberty.mcp.annotations.ToolArg</span>;
<span class="keyword">import</span> <span class="include">jakarta.annotation.security.PermitAll</span>;
<span class="keyword">import</span> <span class="include">jakarta.annotation.security.RolesAllowed</span>;
<span class="keyword">import</span> <span class="include">jakarta.enterprise.context.ApplicationScoped</span>;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="security-annotation-example-classes">Security Annotation example classes</h4>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span>
<span class="directive">public</span> <span class="type">class</span> <span class="class">BookShopTools</span> {

    <span class="comment">// Admin Tool</span>
    <span class="annotation">@RolesAllowed</span>(<span class="string"><span class="delimiter">&quot;</span><span class="content">Admins</span><span class="delimiter">&quot;</span></span>)
    <span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">banUser</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">public</span> <span class="predefined-type">String</span> banUser(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">userName</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Name of user to be banned</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> userName)  {...}

    <span class="comment">// Moderator Tools</span>
    <span class="annotation">@RolesAllowed</span>(<span class="string"><span class="delimiter">&quot;</span><span class="content">Moderators</span><span class="delimiter">&quot;</span></span>)
    <span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">addBook</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">public</span> <span class="predefined-type">String</span> addBook(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">bookCode</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Code to uniquely identify the book</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> bookCode)  {...}

    <span class="annotation">@RolesAllowed</span>(<span class="string"><span class="delimiter">&quot;</span><span class="content">Moderators</span><span class="delimiter">&quot;</span></span>)
    <span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">deleteBook</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">public</span> <span class="predefined-type">String</span> deleteBook(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">bookCode</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Code to uniquely identify the book</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> bookCode)  {...}

    <span class="comment">// User Tools</span>
    <span class="annotation">@RolesAllowed</span>(<span class="string"><span class="delimiter">&quot;</span><span class="content">Users</span><span class="delimiter">&quot;</span></span>)
    <span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">buyBook</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">public</span> <span class="predefined-type">String</span> buyBook(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">bookCode</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Code to uniquely identify the book</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> bookCode) {...}

    <span class="annotation">@RolesAllowed</span>(<span class="string"><span class="delimiter">&quot;</span><span class="content">Users</span><span class="delimiter">&quot;</span></span>)
    <span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">trackBookPrice</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">public</span> <span class="predefined-type">String</span> trackBookPrice(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">bookCode</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Code to uniquely identify the book</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> bookCode)  {...}
}</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@ApplicationScoped</span>
<span class="annotation">@PermitAll</span> <span class="comment">// PermitAll Class level Annotation applies to all class tools, unless overwritten on method level</span>
<span class="directive">public</span> <span class="type">class</span> <span class="class">PublicTools</span> {

    <span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">displayBooks</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">public</span> <span class="predefined-type">String</span> displayBooks(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">bookCode</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Code to uniquely identify the book</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> book)  {...}

    <span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">registerNewUser</span><span class="delimiter">&quot;</span></span>)
    <span class="directive">public</span> <span class="predefined-type">String</span> registerNewUser(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">userName</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">The name for the user to be registered</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> input,
                                  <span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">password</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">The password for the user to be registered</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> input)  {...}
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="steps-required">Steps required</h4>
<div class="ulist">
<ul>
<li>
<p>Create an application with <code>@ApplicationScoped</code> and expose the tools with the required annotations.</p>
</li>
<li>
<p>Create a <code>server.xml</code> file with the users.</p>
</li>
<li>
<p>Ensure that the groups map to the roles created in the tool.</p>
</li>
<li>
<p>Add users to the groups in the <code>server.xml</code> file.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The following additional configuration is required in the <code>server.xml</code> (See the comments in the XML example for details.):</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The <code>appSecurity</code> feature</p>
</li>
<li>
<p>The <code>transportSecurity</code> feature</p>
</li>
<li>
<p>Define a user registry</p>
</li>
<li>
<p>Enable TLS (Transport Layer Security) for security</p>
</li>
<li>
<p>Require TLS (Transport Layer Security) to ensure that credentials aren&#8217;t sent in cleartext</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;server</span> <span class="attribute-name">description</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Liberty server config for Security Annotations</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>

  <span class="tag">&lt;featureManager&gt;</span>
    <span class="tag">&lt;feature&gt;</span>servlet-6.0<span class="tag">&lt;/feature&gt;</span>
    <span class="tag">&lt;feature&gt;</span>cdi-4.0<span class="tag">&lt;/feature&gt;</span>
    <span class="tag">&lt;feature&gt;</span>mcpServer-1.0<span class="tag">&lt;/feature&gt;</span>
    <span class="comment">&lt;!-- The following two features are required for application security to work --&gt;</span>
    <span class="tag">&lt;feature&gt;</span>appSecurity-5.0<span class="tag">&lt;/feature&gt;</span>
    <span class="tag">&lt;feature&gt;</span>transportSecurity-1.0<span class="tag">&lt;/feature&gt;</span>
  <span class="tag">&lt;/featureManager&gt;</span>

  <span class="tag">&lt;include</span> <span class="attribute-name">location</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">../fatTestPorts.xml</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>

  <span class="comment">&lt;!-- Required for passwords to be encrypted using HTTPS --&gt;</span>
  <span class="tag">&lt;keyStore</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">defaultKeyStore</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">password</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Liberty</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span>

  <span class="comment">&lt;!-- Required to define https port for TLS (Transport Layer Security) --&gt;</span>
  <span class="tag">&lt;httpEndpoint</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">defaultHttpEndpoint</span><span class="delimiter">&quot;</span></span>
                <span class="attribute-name">httpPort</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">-1</span><span class="delimiter">&quot;</span></span>
                <span class="attribute-name">httpsPort</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">9443</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
  <span class="tag">&lt;/httpEndpoint&gt;</span>

  <span class="tag">&lt;basicRegistry</span> <span class="attribute-name">id</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">basic</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">realm</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">BasicRealm</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>

       <span class="comment">&lt;!-- Basic user authentication setup --&gt;</span>

       <span class="comment">&lt;!-- Users --&gt;</span>
       <span class="tag">&lt;user</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Sam</span><span class="delimiter">&quot;</span></span>   <span class="attribute-name">password</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">{xor}KzosKy8+LDwoMC07aw==</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
       <span class="tag">&lt;user</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Nile</span><span class="delimiter">&quot;</span></span>  <span class="attribute-name">password</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">{xor}KzosKy8+LRwoMC07aw==</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
       <span class="tag">&lt;user</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Cloe</span><span class="delimiter">&quot;</span></span>  <span class="attribute-name">password</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">{xor}KzosKy8+LEwoMC07aw==</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
       <span class="tag">&lt;user</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Vick</span><span class="delimiter">&quot;</span></span>  <span class="attribute-name">password</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">{xor}KzosKy8+LFwoMC07aw==</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>

       <span class="comment">&lt;!-- Moderators --&gt;</span>
       <span class="tag">&lt;user</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Sally</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">password</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">{xor}KzosKy8+LCwoMC07bQ==</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
       <span class="tag">&lt;user</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Harry</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">password</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">{xor}KzosKy8+LCwoMC07bQ==</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>

       <span class="comment">&lt;!-- Admins --&gt;</span>
       <span class="tag">&lt;user</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Bob</span><span class="delimiter">&quot;</span></span>   <span class="attribute-name">password</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">{xor}KzosKy8+LCwoMC07bA==</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
       <span class="tag">&lt;user</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Noah</span><span class="delimiter">&quot;</span></span>  <span class="attribute-name">password</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">{xor}KzosKy8+LCwoMC07aw==</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>


       <span class="comment">&lt;!-- Mapping users to groups for the RolesAllowed annotation (a group is equivalent to a role) --&gt;</span>

       <span class="tag">&lt;group</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Users</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
           <span class="tag">&lt;member</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Nile</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
           <span class="tag">&lt;member</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Sam</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
           <span class="tag">&lt;member</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Cloe</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
           <span class="tag">&lt;member</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Vick</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
       <span class="tag">&lt;/group&gt;</span>

       <span class="tag">&lt;group</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Moderators</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
           <span class="tag">&lt;member</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Sally</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
           <span class="tag">&lt;member</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Harry</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
       <span class="tag">&lt;/group&gt;</span>

       <span class="tag">&lt;group</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Admins</span><span class="delimiter">&quot;</span></span><span class="tag">&gt;</span>
           <span class="tag">&lt;member</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Bob</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
           <span class="tag">&lt;member</span> <span class="attribute-name">name</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Noah</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span>
       <span class="tag">&lt;/group&gt;</span>

  <span class="tag">&lt;/basicRegistry&gt;</span>
<span class="tag">&lt;/server&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>It is also possible to add multiple roles to tools: <code>@RolesAllowed("Admins, Moderators")</code>. Doing so grants access to users who have either role.</p>
</div>
<div class="paragraph">
<p>If a role that is used in <code>@RolesAllowed</code> annotation is not mentioned in the <code>server.xml</code> file, that just means that no user has that role. If it is the only role that is allowed to call the tool, then no users can call the tool.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="mcp-tools-can-access-metadata-that-the-client-sends-in-the-_meta-field">MCP: Tools can access metadata that the client sends in the _meta field.</h3>
<div class="paragraph">
<p>The <a href="https://modelcontextprotocol.io/specification/2025-06-18/basic/index#meta">MCP specification</a> reserves the <code>_meta</code> property or parameter so clients and servers can attach additional metadata to their interactions.
Key name format: valid <code>_meta</code> key names have two segments:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>An optional prefix (e.g. "example.com/") and</p>
</li>
<li>
<p>A name ("myKey")</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The whole <code>_meta</code> key is seen as "example.com/myKey"</p>
</div>
<div class="sect3">
<h4 id="adding-a-tool-meta-parameter">Adding a Tool Meta parameter</h4>
<div class="paragraph">
<p>The following code shows an example metaKey used to retrieve the value of the metadata. In the example, the metakey is "example.org/location"</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">noArgsRequest</span><span class="delimiter">&quot;</span></span>,
          title = <span class="string"><span class="delimiter">&quot;</span><span class="content">call tool without providing arguments in params</span><span class="delimiter">&quot;</span></span>,
          description = <span class="string"><span class="delimiter">&quot;</span><span class="content">return string made from args and metadata</span><span class="delimiter">&quot;</span></span>,
          structuredContent = <span class="predefined-constant">false</span>)
    <span class="directive">public</span> <span class="predefined-type">String</span> noArgsRequest(Meta meta) {
        Jsonb jsonb = JsonbBuilder.create();
        <span class="predefined-type">String</span> location = (<span class="predefined-type">String</span>) meta.getValue(MetaKey.from(<span class="string"><span class="delimiter">&quot;</span><span class="content">example.org/location</span><span class="delimiter">&quot;</span></span>));
        <span class="predefined-type">BigDecimal</span> timestamp = (<span class="predefined-type">BigDecimal</span>) meta.getValue(MetaKey.from(<span class="string"><span class="delimiter">&quot;</span><span class="content">timestamp</span><span class="delimiter">&quot;</span></span>));
        <span class="predefined-type">String</span> result = <span class="string"><span class="delimiter">&quot;</span><span class="content">You have called this tool from </span><span class="delimiter">&quot;</span></span> + location + <span class="string"><span class="delimiter">&quot;</span><span class="content"> at timestamp </span><span class="delimiter">&quot;</span></span> + timestamp.toString();
        <span class="keyword">return</span> result;
    }</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="returning-metadata-in-a-tool-response">Returning metadata in a tool response</h4>
<div class="paragraph">
<p>A method can return any metadata by using the <code>ToolResponse</code> object:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">   <span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">addPersonToListToolResponse</span><span class="delimiter">&quot;</span></span>,
         title = <span class="string"><span class="delimiter">&quot;</span><span class="content">adds person to people list</span><span class="delimiter">&quot;</span></span>,
         description = <span class="string"><span class="delimiter">&quot;</span><span class="content">adds person to people list</span><span class="delimiter">&quot;</span></span>,
         structuredContent = <span class="predefined-constant">true</span>)
    <span class="directive">public</span> <span class="annotation">@Schema</span>(value = <span class="string"><span class="delimiter">&quot;</span><span class="content">{ ... }</span><span class="delimiter">&quot;</span></span>,description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Returns list of person object</span><span class="delimiter">&quot;</span></span>)
    ToolResponse addPersonToListToolResponse(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">employeeList</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">List of people</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">List</span>&lt;Person&gt; employeeList,
                                             <span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">person</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Person object</span><span class="delimiter">&quot;</span></span>) Optional&lt;Person&gt; person) {
        Person personInstance = person.get();
        employeeList.add(personInstance);
        Jsonb jsonb = JsonbBuilder.create();
        <span class="predefined-type">Map</span>&lt;MetaKey, <span class="predefined-type">Object</span>&gt; _meta = <span class="keyword">new</span> <span class="predefined-type">HashMap</span>&lt;&gt;();
        _meta.put(MetaKey.from(<span class="string"><span class="delimiter">&quot;</span><span class="content">timestamp</span><span class="delimiter">&quot;</span></span>), <span class="integer">1762860699</span>);
        _meta.put(MetaKey.from(<span class="string"><span class="delimiter">&quot;</span><span class="content">example.org/location</span><span class="delimiter">&quot;</span></span>), <span class="string"><span class="delimiter">&quot;</span><span class="content">Hursley</span><span class="delimiter">&quot;</span></span>);
        _meta.put(MetaKey.from(<span class="string"><span class="delimiter">&quot;</span><span class="content">example.org/person</span><span class="delimiter">&quot;</span></span>), personInstance);
        <span class="keyword">return</span> <span class="keyword">new</span> ToolResponse(<span class="predefined-constant">false</span>, <span class="predefined-type">List</span>.of(<span class="keyword">new</span> TextContent(jsonb.toJson(employeeList))), employeeList, _meta);
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>_meta</code> field enables protocol extensions without breaking compatibility. The following examples illustrate common use cases:</p>
</div>
</div>
<div class="sect3">
<h4 id="1-cost-tracking-extension">1) Cost Tracking Extension</h4>
<div class="paragraph">
<p>Track API costs for expensive operations.</p>
</div>
<div class="paragraph">
<p><strong>How it works:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Server reports the cost of executing a tool in the result metadata.</p>
</li>
<li>
<p>Client tracks total spending across operations.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="2-rate-limiting-extension">2) Rate Limiting Extension</h4>
<div class="paragraph">
<p>Prevent resource exhaustion and ensure fair access.</p>
</div>
<div class="paragraph">
<p><strong>How it works:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Metadata shows the remaining quota before each call for time window</p>
</li>
<li>
<p>If limit is exceeded, the error includes retry time in <code>_meta</code></p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="3-caching-hints-extension">3) Caching Hints Extension</h4>
<div class="paragraph">
<p>Optimize performance through intelligent caching.</p>
</div>
<div class="paragraph">
<p><strong>How it works:</strong></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Server includes caching information in the tool call result</p>
</li>
<li>
<p>Client can implement client-side caching</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="4-bringing-it-all-together">4) Bringing it all together</h4>
<div class="paragraph">
<p>All three of the preceding extensions might be built into your MCP server as extensions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="json">{
  <span class="key"><span class="delimiter">&quot;</span><span class="content">name</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">ToolForMetaDataExample</span><span class="delimiter">&quot;</span></span>,
  <span class="key"><span class="delimiter">&quot;</span><span class="content">description</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">ToolDescription</span><span class="delimiter">&quot;</span></span>,
  <span class="key"><span class="delimiter">&quot;</span><span class="content">inputSchema</span><span class="delimiter">&quot;</span></span>: { <span class="error">.</span><span class="error">.</span><span class="error">.</span> },
  <span class="key"><span class="delimiter">&quot;</span><span class="content">_meta</span><span class="delimiter">&quot;</span></span>: {
    <span class="error">/</span><span class="error">/</span> <span class="error">R</span><span class="error">a</span><span class="error">t</span><span class="error">e</span> <span class="error">L</span><span class="error">i</span><span class="error">m</span><span class="error">i</span><span class="error">t</span><span class="error">i</span><span class="error">n</span><span class="error">g</span> <span class="error">E</span><span class="error">x</span><span class="error">t</span><span class="error">e</span><span class="error">n</span><span class="error">s</span><span class="error">i</span><span class="error">o</span><span class="error">n</span> <span class="error">-</span> <span class="error">c</span><span class="error">o</span><span class="error">m</span><span class="error">.</span><span class="error">e</span><span class="error">x</span><span class="error">a</span><span class="error">m</span><span class="error">p</span><span class="error">l</span><span class="error">e</span><span class="error">.</span><span class="error">r</span><span class="error">a</span><span class="error">t</span><span class="error">e</span><span class="error">L</span><span class="error">i</span><span class="error">m</span><span class="error">i</span><span class="error">t</span> <span class="error">n</span><span class="error">a</span><span class="error">m</span><span class="error">e</span><span class="error">s</span><span class="error">p</span><span class="error">a</span><span class="error">c</span><span class="error">e</span>
    <span class="key"><span class="delimiter">&quot;</span><span class="content">com.example.rateLimit/requests</span><span class="delimiter">&quot;</span></span>: <span class="integer">100</span>,
    <span class="key"><span class="delimiter">&quot;</span><span class="content">com.example.rateLimit/period</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">hour</span><span class="delimiter">&quot;</span></span>,
    <span class="key"><span class="delimiter">&quot;</span><span class="content">com.example.rateLimit/remaining</span><span class="delimiter">&quot;</span></span>: <span class="integer">47</span>,
    <span class="error">/</span><span class="error">/</span> <span class="error">C</span><span class="error">o</span><span class="error">s</span><span class="error">t</span> <span class="error">T</span><span class="error">r</span><span class="error">a</span><span class="error">c</span><span class="error">k</span><span class="error">i</span><span class="error">n</span><span class="error">g</span> <span class="error">E</span><span class="error">x</span><span class="error">t</span><span class="error">e</span><span class="error">n</span><span class="error">s</span><span class="error">i</span><span class="error">o</span><span class="error">n</span> <span class="error">-</span> <span class="error">c</span><span class="error">o</span><span class="error">m</span><span class="error">.</span><span class="error">e</span><span class="error">x</span><span class="error">a</span><span class="error">m</span><span class="error">p</span><span class="error">l</span><span class="error">e</span><span class="error">.</span><span class="error">c</span><span class="error">o</span><span class="error">s</span><span class="error">t</span> <span class="error">n</span><span class="error">a</span><span class="error">m</span><span class="error">e</span><span class="error">s</span><span class="error">p</span><span class="error">a</span><span class="error">c</span><span class="error">e</span>
    <span class="key"><span class="delimiter">&quot;</span><span class="content">com.example.cost/estimatedCost</span><span class="delimiter">&quot;</span></span>: <span class="float">0.02</span>,
    <span class="key"><span class="delimiter">&quot;</span><span class="content">com.example.cost/currency</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">USD</span><span class="delimiter">&quot;</span></span>,
    <span class="error">/</span><span class="error">/</span> <span class="error">C</span><span class="error">a</span><span class="error">c</span><span class="error">h</span><span class="error">i</span><span class="error">n</span><span class="error">g</span> <span class="error">H</span><span class="error">i</span><span class="error">n</span><span class="error">t</span><span class="error">s</span> <span class="error">E</span><span class="error">x</span><span class="error">t</span><span class="error">e</span><span class="error">n</span><span class="error">s</span><span class="error">i</span><span class="error">o</span><span class="error">n</span> <span class="error">-</span> <span class="error">c</span><span class="error">o</span><span class="error">m</span><span class="error">.</span><span class="error">e</span><span class="error">x</span><span class="error">a</span><span class="error">m</span><span class="error">p</span><span class="error">l</span><span class="error">e</span><span class="error">.</span><span class="error">c</span><span class="error">a</span><span class="error">c</span><span class="error">h</span><span class="error">e</span> <span class="error">n</span><span class="error">a</span><span class="error">m</span><span class="error">e</span><span class="error">s</span><span class="error">p</span><span class="error">a</span><span class="error">c</span><span class="error">e</span>
    <span class="key"><span class="delimiter">&quot;</span><span class="content">com.example.cache/cacheable</span><span class="delimiter">&quot;</span></span>: <span class="value">true</span>,
    <span class="key"><span class="delimiter">&quot;</span><span class="content">com.example.cache/cacheKey</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">LondonWeather</span><span class="delimiter">&quot;</span></span>,
    <span class="key"><span class="delimiter">&quot;</span><span class="content">com.example.cache/ttl</span><span class="delimiter">&quot;</span></span>: <span class="integer">300</span>
  }
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="notable-bug-fixes-in-mcp-1-0">Notable bug fixes in MCP 1.0</h3>
<div class="sect3">
<h4 id="1-mcp-server-feature-used-iso-8859-1-and-did-not-handle-non-latin-characters">1) MCP Server feature used ISO-8859-1 and did not handle non-Latin characters</h4>
<div class="ulist">
<ul>
<li>
<p>MCP requests and responses are now encoded correctly using UTF-8.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="2-fix-asynchronous-mcp-tool-error-handling">2) Fix asynchronous MCP Tool error handling</h4>
<div class="ulist">
<ul>
<li>
<p>Previously, when an asynchronous tool returned a failed completion stage, the system did not verify whether the exception was a business or technical error. This resulted in all failures being reported as internal errors.</p>
</li>
<li>
<p>The system now differentiates between exception types. This categorization ensures that business errors are returned to the client, while technical errors are reported in the Liberty server log.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="displayCustomizedExceptionText">displayCustomizedExceptionText property</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This beta release adds documentation and tests for the <code>displayCustomizedExceptionText</code> configuration, which allows users to override Liberty’s default error messages (such as SRVE0218E: Forbidden and SRVE0232E: An exception occurred) with clearer, user-defined messages.</p>
</div>
<div class="paragraph">
<p>The feature is enabled through simple <code>server.xml</code> file configuration, where custom messages can be mapped to specific HTTP status codes (403 and 500).</p>
</div>
<div class="paragraph">
<p>Testing ensures that these custom messages correctly replace Liberty’s defaults across all supported platforms, confirming that the configured text is returned consistently in all scenarios.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;webContainer</span> <span class="attribute-name">displaycustomizedexceptiontext</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">Custom error message</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span></code></pre>
</div>
</div>
<div class="sect2">
<h3 id="run">Try it now</h3>
<div class="paragraph">
<p>To try out these features, update your build tools to pull the Open Liberty All Beta Features package instead of the main release. To enable the MCP server feature, follow the instructions from <a href="https://openliberty.io/blog/2025/10/23/mcp-standalone-blog.html">MCP standalone blog</a>. The beta works with Java SE 25, Java SE 21, Java SE 17, Java SE 11, and Java SE 8.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="/guides/maven-intro.html">Maven</a>, you can install the All Beta Features package using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.12.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;configuration&gt;</span>
        <span class="tag">&lt;runtimeArtifact&gt;</span>
          <span class="tag">&lt;groupId&gt;</span>io.openliberty.beta<span class="tag">&lt;/groupId&gt;</span>
          <span class="tag">&lt;artifactId&gt;</span>openliberty-runtime<span class="tag">&lt;/artifactId&gt;</span>
          <span class="tag">&lt;version&gt;</span>26.0.0.2-beta<span class="tag">&lt;/version&gt;</span>
          <span class="tag">&lt;type&gt;</span>zip<span class="tag">&lt;/type&gt;</span>
        <span class="tag">&lt;/runtimeArtifact&gt;</span>
    <span class="tag">&lt;/configuration&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You must also add dependencies to your <code>pom.xml</code> file for the beta version of the APIs that are associated with the beta features that you want to try. For example, the following block adds dependencies for two example beta APIs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>org.example.spec<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>exampleApi<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>7.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;type&gt;</span>pom<span class="tag">&lt;/type&gt;</span>
    <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
<span class="tag">&lt;/dependency&gt;</span>
<span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>example.platform<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>example.example-api<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>11.0.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
<span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Or for <a href="/guides/gradle-intro.html">Gradle</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.10.0'
    }
}
apply plugin: 'liberty'
dependencies {
    libertyRuntime group: 'io.openliberty.beta', name: 'openliberty-runtime', version: '[26.0.0.2-beta,)'
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or if you&#8217;re using <a href="/docs/latest/container-images.html">container images</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty:beta</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or take a look at our <a href="/downloads/#runtime_betas">Downloads page</a>.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="https://plugins.jetbrains.com/plugin/14856-liberty-tools">IntelliJ IDEA</a>, <a href="https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext">Visual Studio Code</a> or <a href="https://marketplace.eclipse.org/content/liberty-tools">Eclipse IDE</a>, you can also take advantage of our open source <a href="https://openliberty.io/docs/latest/develop-liberty-tools.html">Liberty developer tools</a> to enable effective development, testing, debugging and application management all from within your IDE.</p>
</div>
<div class="paragraph">
<p>For more information on using a beta release, refer to the <a href="docs/latest/installing-open-liberty-betas.html">Installing Open Liberty beta releases</a> documentation.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="feedback">We welcome your feedback</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let us know what you think on <a href="https://groups.io/g/openliberty">our mailing list</a>. If you hit a problem, <a href="https://stackoverflow.com/questions/tagged/open-liberty">post a question on StackOverflow</a>. If you hit a bug, <a href="https://github.com/OpenLiberty/open-liberty/issues">please raise an issue</a>.</p>
</div>
</div>
</div>]]></content><author><name>Navaneeth S Nair</name></author><category term="blog" /><category term="announcements" /><category term="release" /><category term="beta" /><summary type="html"><![CDATA[This beta release enhances the mcpServer-1.0 feature with role-based authorization, the new _meta field, and key bug fixes. It also adds documentation and tests for displayCustomizedExceptionText, allowing users to replace default Liberty error messages with clearer, custom text.]]></summary></entry><entry><title type="html">Take the Jakarta EE survey</title><link href="https://openliberty.io/blog/2026/02/04/take-the-jakarta-ee-survey.html" rel="alternate" type="text/html" title="Take the Jakarta EE survey" /><published>2026-02-04T00:00:00+00:00</published><updated>2026-02-04T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/02/04/take-the-jakarta-ee-survey</id><content type="html" xml:base="https://openliberty.io/blog/2026/02/04/take-the-jakarta-ee-survey.html"><![CDATA[<div class="sect1">
<h2 id="calling-java-developers-your-input-matters">Calling Java Developers. Your input matters!</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The IBM Application Development User Research team is running a quick 5-minute survey to learn about the enterprise Java and Jakarta EE specifications/frameworks/models you use. This will help us understand your needs and build better products.</p>
</div>
<div class="paragraph">
<p>Take the survey &#8594; <a href="https://ibm.co/60418Ym81" class="bare">https://ibm.co/60418Ym81</a></p>
</div>
<div class="paragraph">
<p><a href="https://www.linkedin.com/feed/update/urn:li:activity:7417951765720944640/?actorCompanyId=42933556">Open Liberty&#8217;s post on Linkedin</a></p>
</div>
</div>
</div>]]></content><author><name>Adam Yoho</name></author><category term="blog" /></entry><entry><title type="html">Log throttling and notable bug fixes in 26.0.0.1</title><link href="https://openliberty.io/blog/2026/01/27/26.0.0.1.html" rel="alternate" type="text/html" title="Log throttling and notable bug fixes in 26.0.0.1" /><published>2026-01-27T00:00:00+00:00</published><updated>2026-01-27T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/01/27/26.0.0.1</id><content type="html" xml:base="https://openliberty.io/blog/2026/01/27/26.0.0.1.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>In this release, Open Liberty introduces log throttling to automatically suppress excessive, repeated log messages, helping developers reduce noise and manage high-volume logging more effectively.</p>
</div>
<div class="paragraph">
<p>In <a href="/">Open Liberty</a> 26.0.0.1:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#logging">Log Throttling</a></p>
</li>
<li>
<p><a href="#CVEs">Security Vulnerability (CVE) Fixes</a></p>
</li>
<li>
<p><a href="#bugs">Notable bug fixes</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Along with the new features and functions added to the runtime, we’ve also made <a href="#guides">updates to our guides</a>.</p>
</div>
<div class="paragraph">
<p>View the list of fixed bugs in <a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A26001+label%3A%22release+bug%22">26.0.0.1</a>.</p>
</div>
<div class="paragraph">
<p>Check out <a href="/blog/?search=release&amp;search!=beta">previous Open Liberty GA release blog posts</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run">Develop and run your apps using 26.0.0.1</h2>
<div class="sectionbody">
<div class="paragraph">
<p>If you&#8217;re using <a href="/guides/maven-intro.html">Maven</a>, include the following in your <code>pom.xml</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.11.5<span class="tag">&lt;/version&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Or for <a href="/guides/gradle-intro.html">Gradle</a>, include the following in your <code>build.gradle</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.9.6'
    }
}
apply plugin: 'liberty'</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or if you&#8217;re using <a href="/docs/latest/container-images.html">container images</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or take a look at our <a href="/start/">Downloads page</a>.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="https://plugins.jetbrains.com/plugin/14856-liberty-tools">IntelliJ IDEA</a>, <a href="https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext">Visual Studio Code</a> or <a href="https://marketplace.eclipse.org/content/liberty-tools">Eclipse IDE</a>, you can also take advantage of our open source <a href="https://openliberty.io/docs/latest/develop-liberty-tools.html">Liberty developer tools</a> to enable effective development, testing, debugging and application management all from within your IDE.</p>
</div>
<div class="imageblock text-center">
<div class="content">
<a class="image" href="https://stackoverflow.com/tags/open-liberty"><img src="/img/blog/blog_btn_stack.svg" alt="Ask a question on Stack Overflow"></a>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="logging">Log Throttling</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Open Liberty Logging is introducing log throttling. Developers previously had no way to throttle or suppress high-volume messages. This new feature helps to prevent excessive log output when the same log events occur repeatedly within a short span of time.</p>
</div>
<div class="paragraph">
<p>Throttling is enabled by default. While enabled, Liberty tracks each messageID using a sliding window. By default, any messageID that is repeated more than 1,000 times within a five-minute interval is suppressed. A throttle warning is logged when throttling begins.</p>
</div>
<div class="paragraph">
<p>Log throttling can be configured to throttle messages based on the message or messageID by using the <code>throttleType</code> logging attribute. The number of messages allowed before throttling begins can be configured by using the <code>throttleMaxMessagesPerWindow</code> attribute.</p>
</div>
<div class="paragraph">
<p>Log Throttling is disabled by setting <code>throttleMaxMessagesPerWindow</code> to <code>0</code>.</p>
</div>
<div class="paragraph">
<p>Currently, these attributes can be configured as follows:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>In <code>server.xml</code>:</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;logging</span> <span class="attribute-name">throttleMaxMessagesPerWindow</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">5000</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">throttleType</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">messageID</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span></code></pre>
</div>
</div>
</li>
<li>
<p>In <code>bootstrap.properties</code>:</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="properties">com.ibm.ws.logging.throttle.max.messages.per.window=5000
com.ibm.ws.logging.throttle.type=messageID</code></pre>
</div>
</div>
</li>
<li>
<p>In <code>server.env</code>:</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="env">WLP_LOGGING_THROTTLE_MAX_MESSAGES_PER_WINDOW=5000
WLP_LOGGING_THROTTLE_TYPE=messageID</code></pre>
</div>
</div>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="difference-between-message-and-messageid">Difference between message and messageID:</h3>
<div class="paragraph">
<p>Consider the following example of a log event: <code>TEST0111I: Hello World!</code>.</p>
</div>
<div class="paragraph">
<p>When <code>throttleType</code> is set to <code>messageID</code>, throttling is exclusively applied based on the number of occurrences of the messageID. In this example, <code>TEST0111I</code> is used for throttling.</p>
</div>
<div class="paragraph">
<p>When <code>throttleType</code> is set to <code>message</code>, throttling is applied to the entire message. Any variation in the message content is tracked separately. In this example, <code>TEST0111I: Hello World!</code> is used for throttling.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="CVEs">Security vulnerability (CVE) fixes in this release</h2>
<div class="sectionbody">
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">CVE</th>
<th class="tableblock halign-left valign-top">CVSS Score</th>
<th class="tableblock halign-left valign-top">Vulnerability Assessment</th>
<th class="tableblock halign-left valign-top">Versions Affected</th>
<th class="tableblock halign-left valign-top">Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://www.cve.org/CVERecord?id=CVE-2025-12635">CVE-2025-12635</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">5.4</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Cross-site scripting</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">17.0.0.3-25.0.0.12</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Affects the <code>servlet-3.1</code>, <code>servlet-4.0</code>, <code>servlet-5.0</code>, and <code>servlet-6.0</code> features</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>For a list of past security vulnerability fixes, reference the <a href="/docs/latest/security-vulnerabilities.html">Security vulnerability (CVE) list</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="bugs">Notable bugs fixed in this release</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We’ve spent some time fixing bugs. The following sections describe just some of the issues resolved in this release. If you’re interested, here’s the  <a href="https://github.com/OpenLiberty/open-liberty/issues?q=label%3Arelease%3A26001+label%3A%22release+bug%22">full list of bugs fixed in 26.0.0.1</a>.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/33686">NullPointerException occurs in SocketRWChannelSelector</a></p>
</li>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/33617">IBM WebSphere Application Server Liberty is affected by cross-site scripting (CVE-2025-12635 CVSS 5.4)</a></p>
</li>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/33609">wlp passwords keys may fail to decode</a></p>
</li>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/33571">mpOpenAPI does not correctly merge x-ibm-zcon-roles-allowed</a></p>
</li>
<li>
<p><a href="https://github.com/OpenLiberty/open-liberty/issues/33561">Server package &lt;server&gt; --include=minify does not include Liberty&#8217;s FIPS properties file</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="guides">New and updated guides since the previous release</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As Open Liberty features and functionality continue to grow, we continue to add <a href="https://openliberty.io/guides/?search=new&amp;key=tag">new guides to openliberty.io</a> on those topics to make their adoption as easy as possible.</p>
</div>
<div class="paragraph">
<p>Two new guides have been published under the <a href="https://openliberty.io/guides/#observability">Observability</a> category:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://openliberty.io/guides/microprofile-telemetry-grafana-automatic.html">Enabling observability in microservices with traces, metrics, and logs using OpenTelemetry and Grafana</a></p>
</li>
<li>
<p><a href="https://openliberty.io/guides/microprofile-telemetry-grafana-custom.html">Adding custom tracing and metrics for microservice observability using OpenTelemetry and Grafana</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="get-open-liberty-26-0-0-1-now">Get Open Liberty 26.0.0.1 now</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Available through <a href="#run">Maven, Gradle, Docker, and as a downloadable archive</a>.</p>
</div>
</div>
</div>]]></content><author><name>Navaneeth S Nair</name></author><category term="blog" /><category term="announcements" /><category term="release" /><category term="monitoring" /></entry><entry><title type="html">Log Throttling and Model Context Protocol Server 1.0 updates in 26.0.0.1-beta</title><link href="https://openliberty.io/blog/2026/01/13/26.0.0.1-beta.html" rel="alternate" type="text/html" title="Log Throttling and Model Context Protocol Server 1.0 updates in 26.0.0.1-beta" /><published>2026-01-13T00:00:00+00:00</published><updated>2026-01-13T00:00:00+00:00</updated><id>https://openliberty.io/blog/2026/01/13/26.0.0.1-beta</id><content type="html" xml:base="https://openliberty.io/blog/2026/01/13/26.0.0.1-beta.html"><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>In this beta release, Open Liberty introduces log throttling to prevent excessive log output by limiting repeated high-volume messages within a short time span. It also includes updates to the <code>mcpServer-1.0</code> feature.</p>
</div>
<div class="paragraph">
<p>The <a href="/">Open Liberty</a> 26.0.0.1-beta includes the following beta features (along with <a href="/docs/latest/reference/feature/feature-overview.html">all GA features</a>):</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#logging">Log Throttling</a></p>
</li>
<li>
<p><a href="#mcp">Model Context Protocol Server 1.0 updates</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>See also <a href="/blog/?search=beta&amp;key=tag">previous Open Liberty beta blog posts</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="logging">Log Throttling</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Open Liberty Logging is introducing log throttling. Developers previously had no way to throttle or suppress high-volume messages. This new feature helps to prevent excessive log output when the same log events occur repeatedly within a short span of time.</p>
</div>
<div class="paragraph">
<p>Throttling is enabled by default. While enabled, Liberty tracks each messageID using a sliding window. By default, any messageID that is repeated more than 1,000 times within a five-minute interval is suppressed. A throttle warning is logged when throttling begins.</p>
</div>
<div class="paragraph">
<p>Log throttling can be configured to throttle messages based on the message or messageID by using the <code>throttleType</code> logging attribute. The number of messages allowed before throttling can be configured by using the <code>throttleMaxMessagesPerWindow</code> attribute.</p>
</div>
<div class="paragraph">
<p>Log Throttling is disabled by setting <code>throttleMaxMessagesPerWindow</code> to <code>0</code>.</p>
</div>
<div class="paragraph">
<p>Currently, these attributes can be configured as follows:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>In <code>server.xml</code>:</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;logging</span> <span class="attribute-name">throttleMaxMessagesPerWindow</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">5000</span><span class="delimiter">&quot;</span></span> <span class="attribute-name">throttleType</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">message</span><span class="delimiter">&quot;</span></span> <span class="tag">/&gt;</span></code></pre>
</div>
</div>
</li>
<li>
<p>In <code>bootstrap.properties</code>:</p>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="properties">com.ibm.ws.logging.throttle.max.messages.per.window=5000
com.ibm.ws.logging.throttle.type=messageID</code></pre>
</div>
</div>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="difference-between-message-and-messageid">Difference between message and messageID:</h3>
<div class="paragraph">
<p>Consider the following example of a log event: <code>TEST0111I: Hello World!</code>.</p>
</div>
<div class="paragraph">
<p>When <code>throttleType</code> is set to <code>messageID</code>, throttling is exclusively applied based on the number of occurrences of the messageID. In this example, <code>TEST0111I</code> is used for throttling.</p>
</div>
<div class="paragraph">
<p>When <code>throttleType</code> is set to <code>message</code>, throttling is applied to the entire message. Any variation in the message content is tracked separately. In this example, <code>TEST0111I: Hello World!</code> is used for throttling.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="mcp">Model Context Protocol Server 1.0 updates</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <a href="https://modelcontextprotocol.io/docs/getting-started/intro">Model Context Protocol (MCP)</a> is an open standard that enables AI applications to access real-time information from external sources. The Liberty MCP Server feature <code>mcpServer-1.0</code> allows developers to expose the business logic of their applications, allowing it to be integrated into agentic AI workflows.</p>
</div>
<div class="paragraph">
<p>This beta release of Open Liberty includes important updates to the <code>mcpServer-1.0</code> feature, including asynchronous tool support, support for stateless mode, and a few bug fixes.</p>
</div>
<div class="sect2">
<h3 id="prerequisites">Prerequisites</h3>
<div class="paragraph">
<p>To use the <code>mcpServer-1.0</code> feature, <code>Java 17</code> must be installed on the system.</p>
</div>
</div>
<div class="sect2">
<h3 id="update-on-the-mcp-jar-location">Update on the MCP JAR location</h3>
<div class="paragraph">
<p>The MCP server JAR is located in a new directory, <code>/dev/ibm/api</code>, replacing the location used in the initial beta. For complete instructions on building an MCP server in Liberty, see the <a href="https://openliberty.io/blog/2025/10/23/mcp-standalone-blog.html">set up guide</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="asynchronous-tool-execution-support">Asynchronous Tool Execution Support</h3>
<div class="paragraph">
<p>MCP tools can now run asynchronously by returning a <a href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/CompletionStage.html">CompletionStage</a>. If a tool needs to wait for something, such as for data to be returned from a remote system, running asynchronously allows it to wait without occupying a thread.</p>
</div>
<div class="paragraph">
<p>The tool method can return a <code>CompletionStage</code> quickly, but the response is not returned to the client until the <code>CompletionStage</code> completes and provides the response data.</p>
</div>
<div class="paragraph">
<p>The following example illustrates how this approach would look for a tool that calls an asynchronous Jakarta REST client:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">private</span> Client client = ClientBuilder.newClient();

<span class="annotation">@Tool</span>
<span class="directive">public</span> CompletionStage&lt;<span class="predefined-type">String</span>&gt; toolName(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>) <span class="type">int</span> value) {
    <span class="keyword">return</span> client.target(<span class="string"><span class="delimiter">&quot;</span><span class="content">https://example.com/api</span><span class="delimiter">&quot;</span></span>)
            .queryParam(<span class="string"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>, value)
            .request()
            .rx()
            .get(<span class="predefined-type">String</span>.class);
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="stateless-mode">Stateless Mode</h3>
<div class="paragraph">
<p>Parts of the Model Context Protocol require the server to store client information and reuse it for subsequent requests from the same client. This stateful behavior creates challenges when clustering MCP servers. When requests from the same client are handled by different servers, the stored information must be shared across all servers.</p>
</div>
<div class="paragraph">
<p>One way to address this problem is through session affinity. The ingress or load balancer in front of the MCP servers helps ensure that all requests from a single session are served by the same server. However, this approach requires special support for how MCP identifies sessions, and such support for MCP session affinity is not widely available yet.</p>
</div>
<div class="paragraph">
<p>This beta introduces another option, called <em>stateless mode</em>. This option disables MCP features that require state to be stored, allowing MCP servers to be clustered easily without any special logic for session affinity.</p>
</div>
<div class="paragraph">
<p>Currently, enabling stateless mode disables the client’s ability to cancel tool calls. As we add new features, we document which features are disabled or have limitations in stateless mode.</p>
</div>
<div class="paragraph">
<p>To enable stateless mode in your application, you need to add the following configuration in your <code>server.xml</code> file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;mcpServer</span> <span class="attribute-name">stateless</span>=<span class="string"><span class="delimiter">&quot;</span><span class="content">true</span><span class="delimiter">&quot;</span></span><span class="tag">/&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>One of the main differences in stateless mode is that the server does not assign a session ID to clients. As a result, subsequent client requests do not include the <code>Mcp-Session-Id</code> header.</p>
</div>
</div>
<div class="sect2">
<h3 id="working-with-structured-content-in-mcp-tools">Working with structured content in MCP Tools</h3>
<div class="paragraph">
<p>The <a href="https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content">MCP specification</a> supports returning structured content from tools.</p>
</div>
<div class="sect3">
<h4 id="returning-structured-content">Returning structured content</h4>
<div class="paragraph">
<p>It is now possible to return structured JSON from a tool method. To enable this capability, set <code>structuredContent = true</code> on the <code>@Tool</code> annotation and return a POJO from your tool method:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="directive">public</span> record Street(<span class="predefined-type">String</span> streetName, <span class="predefined-type">String</span> roadType) {}

<span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">getStreet</span><span class="delimiter">&quot;</span></span>,
      description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Look up a street by name</span><span class="delimiter">&quot;</span></span>
      structuredContent = <span class="predefined-constant">true</span>)
<span class="directive">public</span> Street getStreet(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">street</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">the street name</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> streetName){
    <span class="comment">//Get street information</span>
    <span class="keyword">return</span> <span class="keyword">new</span> Street(streetName, <span class="string"><span class="delimiter">&quot;</span><span class="content">One way Street</span><span class="delimiter">&quot;</span></span>);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Open Liberty uses <a href="https://jakarta.ee/specifications/jsonb/">Jakarta JSON Binding (JSON-B)</a> to encode the returned <code>Street</code> object into JSON and this is returned to the MCP client in the <code>structuredContent</code> field of the response. For compatibility with earlier versions and older clients that do not support <code>structuredContent</code>, the encoded JSON is also returned as <code>TextContent</code>.
In addition, Open Liberty generates a schema for the method&#8217;s return type to indicate the expected data structure to the MCP client.</p>
</div>
</div>
<div class="sect3">
<h4 id="customizing-serialization">Customizing Serialization</h4>
<div class="paragraph">
<p>Since Open Liberty uses JSON-B to encode the returned object, you can use the standard JSON-B annotations to customize how your objects are serialized.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="customizing-schemas-with-schema">Customizing schemas with <code>@Schema</code></h3>
<div class="paragraph">
<p>MCP protocol requires tools to declare schemas for their inputs and outputs. These schemas help clients to understand what to send and what to expect in return. Open Liberty generates these schemas automatically by inspecting your Java types - although you can customize them by using the <code>@Schema</code> annotation.
The simplest use of <code>@Schema</code> is to add descriptions to your types. These descriptions help clients understand the purpose of each type or field.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Schema</span>(description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Represents Street information</span><span class="delimiter">&quot;</span></span>)
<span class="directive">public</span> record Street(
    <span class="annotation">@Schema</span>(description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Name of the street</span><span class="delimiter">&quot;</span></span>)
    <span class="predefined-type">String</span> streetName,

    <span class="annotation">@Schema</span>(description = <span class="string"><span class="delimiter">&quot;</span><span class="content">type of the road and its rules</span><span class="delimiter">&quot;</span></span>)
    <span class="predefined-type">String</span> roadType
) {}

<span class="annotation">@Tool</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">getStreet</span><span class="delimiter">&quot;</span></span>,
      description = <span class="string"><span class="delimiter">&quot;</span><span class="content">Look up a street by name</span><span class="delimiter">&quot;</span></span>
      structuredContent = <span class="predefined-constant">true</span>)
<span class="directive">public</span> Street getStreet(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">street</span><span class="delimiter">&quot;</span></span>, description = <span class="string"><span class="delimiter">&quot;</span><span class="content">the street name</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> streetName) {
    <span class="comment">// Get street information</span>
    <span class="keyword">return</span> <span class="keyword">new</span> Street(streetName, <span class="string"><span class="delimiter">&quot;</span><span class="content">One way Street</span><span class="delimiter">&quot;</span></span>);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If the default schemas do not meet your needs, you can provide a complete schema override. You might need to do an override if you use JSON-B annotations to customize the serialization of the object causing the generated schema to no longer match. A schema override is performed by providing a value to the <code>@Schema</code> annotation.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Schema</span>(<span class="string"><span class="delimiter">&quot;</span><span class="delimiter">&quot;</span></span><span class="string"><span class="delimiter">&quot;</span><span class="content">
{
    </span><span class="delimiter">&quot;</span></span>type<span class="string"><span class="delimiter">&quot;</span><span class="content">: </span><span class="delimiter">&quot;</span></span>object<span class="string"><span class="delimiter">&quot;</span><span class="content">,
    </span><span class="delimiter">&quot;</span></span>required<span class="string"><span class="delimiter">&quot;</span><span class="content">: [</span><span class="delimiter">&quot;</span></span>streetName<span class="string"><span class="delimiter">&quot;</span><span class="content">],
    </span><span class="delimiter">&quot;</span></span>properties<span class="string"><span class="delimiter">&quot;</span><span class="content">: {
        </span><span class="delimiter">&quot;</span></span>streetName<span class="string"><span class="delimiter">&quot;</span><span class="content">: {
            </span><span class="delimiter">&quot;</span></span>type<span class="string"><span class="delimiter">&quot;</span><span class="content">: </span><span class="delimiter">&quot;</span></span>string<span class="string"><span class="delimiter">&quot;</span><span class="content">
        },
        </span><span class="delimiter">&quot;</span></span>roadType<span class="string"><span class="delimiter">&quot;</span><span class="content">: {
            </span><span class="delimiter">&quot;</span></span>type<span class="string"><span class="delimiter">&quot;</span><span class="content">: </span><span class="delimiter">&quot;</span></span>string<span class="string"><span class="delimiter">&quot;</span><span class="content">,
            </span><span class="delimiter">&quot;</span></span><span class="type">enum</span><span class="string"><span class="delimiter">&quot;</span><span class="content">: [
                </span><span class="delimiter">&quot;</span></span>One Way Street<span class="string"><span class="delimiter">&quot;</span><span class="content">,
                </span><span class="delimiter">&quot;</span></span>Dual Carriageway<span class="string"><span class="delimiter">&quot;</span><span class="content">,
                </span><span class="delimiter">&quot;</span></span>Motorway<span class="string"><span class="delimiter">&quot;</span><span class="content">
            ]
        }
    }
}
</span><span class="delimiter">&quot;</span></span><span class="string"><span class="delimiter">&quot;</span><span class="delimiter">&quot;</span></span>)
<span class="directive">public</span> record Street(<span class="predefined-type">String</span> streetName, <span class="predefined-type">String</span> roadType) {}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You usually also need to provide an output schema for a tool method that returns a <code>ToolResponse</code>. In this case, Open Liberty does not know what type your tool is going to return, so it cannot generate a detailed schema for it.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Schema</span>(<span class="string"><span class="delimiter">&quot;</span><span class="delimiter">&quot;</span></span><span class="string"><span class="delimiter">&quot;</span><span class="content">
{
    </span><span class="delimiter">&quot;</span></span>type<span class="string"><span class="delimiter">&quot;</span><span class="content">: </span><span class="delimiter">&quot;</span></span>object<span class="string"><span class="delimiter">&quot;</span><span class="content">,
    </span><span class="delimiter">&quot;</span></span>required<span class="string"><span class="delimiter">&quot;</span><span class="content">: [</span><span class="delimiter">&quot;</span></span>streetName<span class="string"><span class="delimiter">&quot;</span><span class="content">],
    </span><span class="delimiter">&quot;</span></span>properties<span class="string"><span class="delimiter">&quot;</span><span class="content">: {
        </span><span class="delimiter">&quot;</span></span>streetName<span class="string"><span class="delimiter">&quot;</span><span class="content">: {
            </span><span class="delimiter">&quot;</span></span>type<span class="string"><span class="delimiter">&quot;</span><span class="content">: </span><span class="delimiter">&quot;</span></span>string<span class="string"><span class="delimiter">&quot;</span><span class="content">
        },
        </span><span class="delimiter">&quot;</span></span>roadType<span class="string"><span class="delimiter">&quot;</span><span class="content">: {
            </span><span class="delimiter">&quot;</span></span>type<span class="string"><span class="delimiter">&quot;</span><span class="content">: </span><span class="delimiter">&quot;</span></span>string<span class="string"><span class="delimiter">&quot;</span><span class="content">,
            </span><span class="delimiter">&quot;</span></span><span class="type">enum</span><span class="string"><span class="delimiter">&quot;</span><span class="content">: [
                </span><span class="delimiter">&quot;</span></span>One Way Street<span class="string"><span class="delimiter">&quot;</span><span class="content">,
                </span><span class="delimiter">&quot;</span></span>Dual Carriageway<span class="string"><span class="delimiter">&quot;</span><span class="content">,
                </span><span class="delimiter">&quot;</span></span>Motorway<span class="string"><span class="delimiter">&quot;</span><span class="content">
            ]
        }
    }
}
</span><span class="delimiter">&quot;</span></span><span class="string"><span class="delimiter">&quot;</span><span class="delimiter">&quot;</span></span>)
<span class="annotation">@Tool</span>(structuredContent = <span class="predefined-constant">true</span>)
<span class="directive">public</span> ToolResponse toolName() {
    Street street = yourService.getStreetInfo();
    <span class="keyword">return</span> ToolResponse.structuredSuccess(street)
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Use <code>@Schema(description = "&#8230;&#8203;")</code> when you want to add helpful context for clients, and <code>@Schema(value = "{&#8230;&#8203;}")</code> when you have more complex types and the auto-generated schema does not reflect your actual JSON output.</p>
</div>
</div>
<div class="sect2">
<h3 id="allowing-annotations-in-mcp-content-objects">Allowing annotations in MCP Content objects</h3>
<div class="paragraph">
<p>As specified in the <a href="https://modelcontextprotocol.io/specification/2025-06-18/server/resources#annotations">MCP specification</a>, MCP annotations can be added to Content objects returned from tool methods. These annotations are not Java annotations; instead, they are additional fields that provide hints to clients about how to use and display the content.</p>
</div>
<div class="paragraph">
<p>The annotation includes the following fields:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><strong><code>audience</code> field</strong> - an enum of type <code>Role</code> that indicates the intended audience for the content.</p>
</li>
<li>
<p><strong><code>lastModified</code> field</strong> - a string containing an ISO 8601-formatted timestamp that indicates when the content object was last modified.</p>
</li>
<li>
<p><strong><code>priority</code> field</strong> - a double value between 0.0 to 1.0 that indicates the importance of the content object.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The following example shows how annotation fields can be added to tools.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Tool</span>
<span class="directive">public</span> TextContent toolName(<span class="annotation">@ToolArg</span>(name = <span class="string"><span class="delimiter">&quot;</span><span class="content">input</span><span class="delimiter">&quot;</span></span>) <span class="predefined-type">String</span> input) {
    Content.Annotations annotations = <span class="keyword">new</span> Content.Annotations(<span class="predefined-type">Role</span>.USER,
                                                              Instant.now().toString(),
                                                              <span class="float">1.0</span>);
    <span class="keyword">return</span> <span class="keyword">new</span> TextContent(<span class="string"><span class="delimiter">&quot;</span><span class="content">My Generated Text</span><span class="delimiter">&quot;</span></span>, <span class="predefined-constant">null</span>, annotations);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Result:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="json">{
    <span class="key"><span class="delimiter">&quot;</span><span class="content">id</span><span class="delimiter">&quot;</span></span>: <span class="integer">1</span>,
    <span class="key"><span class="delimiter">&quot;</span><span class="content">jsonrpc</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">2.0</span><span class="delimiter">&quot;</span></span>,
    <span class="key"><span class="delimiter">&quot;</span><span class="content">result</span><span class="delimiter">&quot;</span></span>: {
        <span class="key"><span class="delimiter">&quot;</span><span class="content">content</span><span class="delimiter">&quot;</span></span>: [
            {
                <span class="key"><span class="delimiter">&quot;</span><span class="content">annotations</span><span class="delimiter">&quot;</span></span>: {
                    <span class="key"><span class="delimiter">&quot;</span><span class="content">audience</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">user</span><span class="delimiter">&quot;</span></span>,
                    <span class="key"><span class="delimiter">&quot;</span><span class="content">lastModified</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">2025-12-11T12:31:04</span><span class="delimiter">&quot;</span></span>,
                    <span class="key"><span class="delimiter">&quot;</span><span class="content">priority</span><span class="delimiter">&quot;</span></span>: <span class="float">1.0</span>
                },
                <span class="key"><span class="delimiter">&quot;</span><span class="content">text</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">My Generated Text</span><span class="delimiter">&quot;</span></span>,
                <span class="key"><span class="delimiter">&quot;</span><span class="content">type</span><span class="delimiter">&quot;</span></span>: <span class="string"><span class="delimiter">&quot;</span><span class="content">text</span><span class="delimiter">&quot;</span></span>
            }
        ],
        <span class="key"><span class="delimiter">&quot;</span><span class="content">isError</span><span class="delimiter">&quot;</span></span>: <span class="value">false</span>
    }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="run">Try it now</h3>
<div class="paragraph">
<p>To try out these features, update your build tools to pull the Open Liberty All Beta Features package instead of the main release. To enable the MCP server feature, follow the instructions from <a href="https://openliberty.io/blog/2025/10/23/mcp-standalone-blog.html">MCP standalone blog</a>. The beta works with Java SE 25, Java SE 21, Java SE 17, Java SE 11, and Java SE 8.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="/guides/maven-intro.html">Maven</a>, you can install the All Beta Features package using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;plugin&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>io.openliberty.tools<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>liberty-maven-plugin<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>3.11.5<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;configuration&gt;</span>
        <span class="tag">&lt;runtimeArtifact&gt;</span>
          <span class="tag">&lt;groupId&gt;</span>io.openliberty.beta<span class="tag">&lt;/groupId&gt;</span>
          <span class="tag">&lt;artifactId&gt;</span>openliberty-runtime<span class="tag">&lt;/artifactId&gt;</span>
          <span class="tag">&lt;version&gt;</span>26.0.0.1-beta<span class="tag">&lt;/version&gt;</span>
          <span class="tag">&lt;type&gt;</span>zip<span class="tag">&lt;/type&gt;</span>
        <span class="tag">&lt;/runtimeArtifact&gt;</span>
    <span class="tag">&lt;/configuration&gt;</span>
<span class="tag">&lt;/plugin&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You must also add dependencies to your <code>pom.xml</code> file for the beta version of the APIs that are associated with the beta features that you want to try. For example, the following block adds dependencies for two example beta APIs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>org.example.spec<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>exampleApi<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>7.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;type&gt;</span>pom<span class="tag">&lt;/type&gt;</span>
    <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
<span class="tag">&lt;/dependency&gt;</span>
<span class="tag">&lt;dependency&gt;</span>
    <span class="tag">&lt;groupId&gt;</span>example.platform<span class="tag">&lt;/groupId&gt;</span>
    <span class="tag">&lt;artifactId&gt;</span>example.example-api<span class="tag">&lt;/artifactId&gt;</span>
    <span class="tag">&lt;version&gt;</span>11.0.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
<span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Or for <a href="/guides/gradle-intro.html">Gradle</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="gradle">buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.9.6'
    }
}
apply plugin: 'liberty'
dependencies {
    libertyRuntime group: 'io.openliberty.beta', name: 'openliberty-runtime', version: '[26.0.0.1-beta,)'
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or if you&#8217;re using <a href="/docs/latest/container-images.html">container images</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code>FROM icr.io/appcafe/open-liberty:beta</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or take a look at our <a href="/downloads/#runtime_betas">Downloads page</a>.</p>
</div>
<div class="paragraph">
<p>If you&#8217;re using <a href="https://plugins.jetbrains.com/plugin/14856-liberty-tools">IntelliJ IDEA</a>, <a href="https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext">Visual Studio Code</a> or <a href="https://marketplace.eclipse.org/content/liberty-tools">Eclipse IDE</a>, you can also take advantage of our open source <a href="https://openliberty.io/docs/latest/develop-liberty-tools.html">Liberty developer tools</a> to enable effective development, testing, debugging and application management all from within your IDE.</p>
</div>
<div class="paragraph">
<p>For more information on using a beta release, refer to the <a href="docs/latest/installing-open-liberty-betas.html">Installing Open Liberty beta releases</a> documentation.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="feedback">We welcome your feedback</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let us know what you think on <a href="https://groups.io/g/openliberty">our mailing list</a>. If you hit a problem, <a href="https://stackoverflow.com/questions/tagged/open-liberty">post a question on StackOverflow</a>. If you hit a bug, <a href="https://github.com/OpenLiberty/open-liberty/issues">please raise an issue</a>.</p>
</div>
</div>
</div>]]></content><author><name>Navaneeth S Nair</name></author><category term="blog" /><category term="announcements" /><category term="release" /><category term="beta" /><category term="monitoring" /><summary type="html"><![CDATA[In this beta release, Open Liberty introduces log throttling to prevent excessive log output by limiting repeated high-volume messages within a short time span. It also includes updates to the mcpServer-1.0 feature.]]></summary></entry></feed>