<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="https://publishpress.com/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>.Lost in Coding</title>
	<atom:link href="https://ondro.inginea.eu/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>https://ondro.inginea.eu/</link>
	<description></description>
	<lastBuildDate>Tue, 07 May 2024 13:30:55 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2.6</generator>
<site xmlns="com-wordpress:feed-additions:1">96365924</site>	<item>
		<title>New features between Java 8 and Java 19</title>
		<link>https://ondro.inginea.eu/index.php/new-features-in-java-versions-since-java-8/</link>
					<comments>https://ondro.inginea.eu/index.php/new-features-in-java-versions-since-java-8/#comments</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Sat, 08 Oct 2022 21:33:31 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<guid isPermaLink="false">http://ondro.inginea.eu/?p=769</guid>

					<description><![CDATA[<p>Since version 9, Java has new features every 6 months and it&#8217;s very hard to keep track of these new changes. Most of the information on the internet describes changes between the last 2 Java versions. However, if you&#8217;re in a similar situation as me, you&#8217;re not using one of the latest Java versions but [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/new-features-in-java-versions-since-java-8/">New features between Java 8 and Java 19</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Since version 9, Java has new features every 6 months and it&#8217;s very hard to keep track of these new changes. Most of the information on the internet describes changes between the last 2 Java versions. However, if you&#8217;re in a similar situation as me, you&#8217;re not using one of the latest Java versions but a version several releases older. </p>



<p>Then it&#8217;s useful to know which new features were added since the version you use now, or between the versions that you use now and the one you want to start using next. Therefore I&#8217;ve compiled a table with all new features added since Java 8 for each new Java version and I keep it updated for every newer Java version.</p>



<span id="more-769"></span>



<p>Below you can find tables for:</p>



<ul>
<li><a href="#language-features">New Java language features</a> &#8211; additions to the Java language or APIs</li>



<li><a href="#language-features-preview">New Java language features in preview/incubation</a> &#8211; additions to the Java language or APIs which aren&#8217;t in their final state yet</li>



<li><a href="#tools">New tools and features in OpenJDK</a> &#8211; additions outside of the language, such as command line tools or JVM improvements</li>



<li><a href="#removals">Deprecated/removed features and APIs</a></li>
</ul>



<blockquote class="wp-block-quote">
<p>Note that I didn&#8217;t include all the new features and API additions, only those that are useful for a wide range of developers, to keep the list brief.</p>
</blockquote>



<p>This article isn&#8217;t about choosing the right Java version for you to use. But I&#8217;ll at least summarize all the Java versions since Java 8 and for your convenience:</p>



<ul>
<li>Java 8 &#8211; LTS release (Long Term Support), last LTS release before JPMS (modules) were introduced in Java 9</li>



<li>Java 11 &#8211; LTS release</li>



<li>Java 17 &#8211; LTS release, the latest LTS release until September 2023</li>



<li>Java 19 &#8211; non-LTS release, the latest version released in September 2022</li>



<li>all other Java versions &#8211; non-LTS releases</li>
</ul>



<p>In most cases, you should only use LTS releases in production. That is unless you have specific needs to use the greatest and latest and are willing to upgrade to a new Java version every 6 months. To find out more about Java LTS releases, you can read <a href="https://blogs.oracle.com/javamagazine/post/java-long-term-support-lts" target="_blank" rel="noreferrer noopener">The art of long-term support and what LTS means for the Java ecosystem</a> by Oracle. </p>



<p></p>



<h2 class="wp-block-heading" id="language-features">Java language features and APIs</h2>



<figure class="wp-block-table"><table class="mtr-table mtr-tr-td"><tbody><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><strong>Feature/API</strong></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"><strong>Since</strong></div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"><strong>Preview  since</strong></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/408" target="_blank" rel="noreferrer noopener">Simple Web Server</a> (a.k.a <a href="https://docs.oracle.com/en/java/javase/18/docs/api/jdk.httpserver/com/sun/net/httpserver/SimpleFileServer.html" target="_blank" rel="noreferrer noopener">com.sun.net.httpserver</a>.<a href="https://docs.oracle.com/en/java/javase/18/docs/api/jdk.httpserver/com/sun/net/httpserver/SimpleFileServer.html" target="_blank" rel="noreferrer noopener">SimpleFileServer</a>)<br><code>SimpleFileServer.createFileServer(new InetSocketAddress(9000), path, logLevel).start();</code><br><br>Cmd Line: <code>jwebserver -p 9000</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">18</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/413" target="_blank" rel="noreferrer noopener">Code Snippets in Java API Documentation</a><br><code>{@snippet : lines of code}</code> <br>instead of <code>&lt;pre&gt;{@code lines of code }&lt;/pre&gt;</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">18</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/400" target="_blank" rel="noreferrer noopener">UTF-8 by Default</a> – instead of the charset defined by the system. <br>Run <code>javac -encoding UTF-8</code> with JDK 8-17 to check for Java source encoding issues.</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">18</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/415" target="_blank" rel="noreferrer noopener">Context-Specific Deserialization Filters</a> – allow applications to configure deserialization filters, either specify a pattern via a system property, or a filter factory via a system property or via <code>ObjectInputFilter.Config</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">17</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/409" data-type="URL" data-id="https://openjdk.java.net/jeps/409" target="_blank" rel="noreferrer noopener">Sealed classes</a> (inheritance only for allowed classes):<br><code>public abstract sealed class Shape permits Circle, Rectangle, Square {...}</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">17</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">15</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/395" target="_blank" rel="noreferrer noopener">Record type</a> – data classes with implicit getters, constructor, <code>equals</code>, <code>hashCode</code> and <code>toString</code> methods:<br><code>record Point(int x, int y) { }</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">16</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">14</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content">Static members in inner classes (part of <a href="https://openjdk.java.net/jeps/395" target="_blank" rel="noreferrer noopener">Record type</a> JEP)<br><code>new Object() { </code><br>  <code>static record MyData(String data) {};</code><br>  <code>public static final int CONSTANT = 1;</code><br><code>};</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">16</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">16</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/394" target="_blank" rel="noreferrer noopener">Pattern Matching for <code>instanceof</code></a>: <br><code>if (x instanceOf String s) { String a = s; }</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">16</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">14</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/378" target="_blank" rel="noreferrer noopener">Text blocks</a>:<br><code>String query = """</code><br>  <code>SELECT "EMP_ID", "LAST_NAME"</code><br>  <code>FROM "EMPLOYEE_TB";</code><br><code> """</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">15</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">13</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content">New String methods (<code><a href="https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/String.html#formatted(java.lang.Object...)" target="_blank" rel="noreferrer noopener">formatted</a>, stripIndent, translateEscapes</code>)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">15</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/361" target="_blank" rel="noreferrer noopener">Switch expressions</a>:<br><code>boolean isWeekend = switch (day) {   </code><br>  <code>case SATURDAY, SUNDAY -&gt; true;</code><br>  <code>default -&gt; false</code>;<br><code>};</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">14</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">12</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://www.baeldung.com/java12-string-api" target="_blank" rel="noreferrer noopener">New String methods</a> (<code>indent</code>, <code>transform</code>)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">12</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/text/CompactNumberFormat.html" target="_blank" rel="noreferrer noopener">CompactNumberFormat class</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">12</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://4comprehension.com/java-11-string-api-updates/" target="_blank" rel="noreferrer noopener">New String methods</a> (<code>repeat</code>, <code>isBlank</code>, <code>strip</code>, <code>lines</code>)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/323" target="_blank" rel="noreferrer noopener"><code>var</code> type allowed in Lambda Parameters</a>:<br><code>(@NonNull var x) -&gt; process(x)</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html" target="_blank" rel="noreferrer noopener">New HTTP client API</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/javase/9/docs/api/jdk/incubator/http/HttpClient.html">9</a></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/332" target="_blank" rel="noreferrer noopener">TLS v1.3</a> – support for a new SSL/TLS protocol version</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a rel="noreferrer noopener" href="http://openjdk.java.net/jeps/286" target="_blank"><code>var</code> type allowed for local variables</a>:<br><code>var length = str.length();</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">10</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://dev.to/ajiteshtiwari/java-9-flow-api-4e38" target="_blank" rel="noreferrer noopener">Flow API (reactive streams)</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/261" target="_blank" rel="noreferrer noopener">Java Platform Module System (modules)</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/269" target="_blank" rel="noreferrer noopener">Collection factory methods</a>:<br><code>List.of(a, b, c); Set.of(d, e, f, g);</code>  <code>Map.of(k1, v1, k2, v2)</code>;</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://www.javatpoint.com/java-9-stream-api-improvement" target="_blank" rel="noreferrer noopener">Stream API improvements</a> (<code>takeWhile</code>, <code>dropWhile</code>, <code>ofNullable</code>, <code>iterate</code> with condition)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/javase/9/docs/api/java/awt/image/MultiResolutionImage.html" target="_blank" rel="noreferrer noopener">Multi-Resolution Image API</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/259" target="_blank" rel="noreferrer noopener">Stack-Walking API</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><code>this.getClass().getPackageName()</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/102" target="_blank" rel="noreferrer noopener">Process API updates</a> (detailed info about processes, e.g. ID, onExit, destroy)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://grokonez.com/java/java-9/java-9-completablefuture-api-improvements-delay-timeout-support" target="_blank" rel="noreferrer noopener">new methods in CompletableFuture API</a> (<code>delay</code>, <code>timeout</code>)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://www.javatpoint.com/java-9-interface-private-methods" target="_blank" rel="noreferrer noopener">Interface private methods</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/277" target="_blank" rel="noreferrer noopener"><code>since</code> and <code>forRemoval</code> in @Deprecated</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://www.javatpoint.com/java-default-methods" target="_blank" rel="noreferrer noopener">Interface Default and Static Methods</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html" target="_blank" rel="noreferrer noopener">Method References</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html" target="_blank" rel="noreferrer noopener">Optional class</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html" target="_blank" rel="noreferrer noopener">Lambda expressions</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html" target="_blank" rel="noreferrer noopener">Functional interfaces</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html" target="_blank" rel="noreferrer noopener">Stream API</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://jcp.org/en/jsr/detail?id=335" target="_blank" rel="noreferrer noopener">Effectively Final Variables</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/120" target="_blank" rel="noreferrer noopener">Repeating Annotations</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://jcp.org/en/jsr/detail?id=310" target="_blank" rel="noreferrer noopener">New Date Time API </a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr></tbody></table></figure>



<div class="wp-block-group omnifish-advert has-white-color has-text-color has-background is-layout-flow" style="background-color:#0b8f9b"><div class="wp-block-group__inner-container">
<div class="wp-block-media-text alignwide has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-center has-white-color has-text-color" style="grid-template-columns:auto 15%"><div class="wp-block-media-text__content">
<p class="has-medium-font-size"><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank"><strong>Need help with GlassFish, Jakarta EE, Java in the cloud?</strong></a></p>



<p><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank">Follow me at <strong>OmniFish</strong>! </a></p>
</div><figure class="wp-block-media-text__media"><a href="https://omnifish.ee"><img decoding="async" width="300" height="178" src="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&#038;ssl=1" alt="" class="wp-image-1034 size-medium" srcset="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&amp;ssl=1 300w, https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?w=400&amp;ssl=1 400w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></figure></div>
</div></div>



<h2 class="wp-block-heading" id="language-features-preview">Java language features or APIs in preview/incubation</h2>



<figure class="wp-block-table"><table class="mtr-table mtr-tr-td"><tbody><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><strong>Feature/API</strong></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"><strong>Since</strong></div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content"><strong>Preview  since</strong></div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.org/jeps/425" target="_blank" rel="noreferrer noopener">Virtual threads</a><br><code>Thread.startVirtualThread(runnable)</code>;<br><code>Thread.ofVirtual().name("duke").unstarted(runnable);</code><br><code>Executors.newVirtualThreadPerTaskExecutor();</code><br><code>Executors.newThreadPerTaskExecutor(threadFactory); </code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">19</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.org/jeps/405" target="_blank" rel="noreferrer noopener">Record patterns</a><br><code>record Point(int x, int y) {}<br>…<br>if (o instanceof Point(int x, int y)) {<br>  System.out.println( x + y );<br>}</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">19</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/428" target="_blank" rel="noreferrer noopener">Structured concurrency</a><br><code>try (var scope = new ShutdownOnFailure()) { <br>  Future&lt;String&gt; user = scope.fork(() -&gt; findUser());<br>  Future&lt;Integer&gt; order = scope.fork(() -&gt; fetchOrder());<br>}<br>//both threads are terminated here, outside of try block </code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">19</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/427" target="_blank" rel="noreferrer noopener">Pattern Matching for switch</a> – like <code>instanceof</code> for <code>switch</code>; <code>switch</code> is an expression and can be assigned<br><code>String result = switch (o) {<br>  case null -&gt; null;</code><br><code>  case 0 -&gt; throw new RuntimeException("Cannot be 0"); // Special cases</code><br><code>  case Integer i when i &gt; 0 -&gt; "Positive number";</code><br><code>  case Integer i -&gt; "Negative number"; // 0 and positive numbers handled by above rules<br>  case String s -&gt; s;<br>  case Point p -&gt; p.toString();<br>  case int[] ia -&gt; "Array length" + ia.length;<br>  default -&gt; "Something else";<br>}</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">17</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.org/jeps/424" target="_blank" rel="noreferrer noopener">Foreign Function &amp; Memory API</a> (an alternative to JNI)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">16</div></td></tr><tr><td data-mtr-content="Feature/API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/426" target="_blank" rel="noreferrer noopener">Vector API</a> – express computations that compile to optimal hardware instructions</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Preview  since" class="mtr-td-tag"><div class="mtr-cell-content">16</div></td></tr></tbody></table></figure>



<h2 class="wp-block-heading" id="tools">New JDK tools and features since OpenJDK 8</h2>



<figure class="wp-block-table"><table class="mtr-table mtr-tr-td"><tbody><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content">Tool / feature</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">Since</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content">Experimental since</div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/343" target="_blank" rel="noreferrer noopener">Packaging Tool</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content">14</div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/318" target="_blank" rel="noreferrer noopener">Epsilon (no-op) GC</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a rel="noreferrer noopener" href="http://openjdk.java.net/jeps/317" target="_blank">Experimental Java-Based JIT Compiler</a> (Graal VM)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content">10</div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/379" target="_blank" rel="noreferrer noopener">Shenandoah GC</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">15</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content">12</div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://docs.oracle.com/en/java/javase/15/gctuning/z-garbage-collector.html" target="_blank" rel="noreferrer noopener">Z GC</a> (<a href="https://openjdk.java.net/jeps/377" target="_blank" rel="noreferrer noopener">JEP 377</a>)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">15</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/358" target="_blank" rel="noreferrer noopener">Helpful NullPointerExceptions</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">14</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/330" target="_blank" rel="noreferrer noopener">Launching Java files as scripts</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/328" target="_blank" rel="noreferrer noopener">Flight recorder</a> (data collection framework for troubleshooting)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8146115" target="_blank" rel="noreferrer noopener">Docker Container Support:</a> <br><code>-XX:-UseContainerSupport</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">10,<br>8u191</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8186248" target="_blank" rel="noreferrer noopener">Flexible heap size selection</a>:<br><code>-XX:MaxRAMPercentage</code></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">10, <br>8u191</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a rel="noreferrer noopener" href="http://openjdk.java.net/jeps/310" target="_blank">Application Class-Data Sharing</a> (CDS)</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">10</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/282" target="_blank" rel="noreferrer noopener">jlink</a> – custom JRE image, subset of JRE</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/222" target="_blank" rel="noreferrer noopener">JShell (Java REPL)</a> – run Java commands interactively</div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/238" target="_blank" rel="noreferrer noopener">Multi-Release JAR Files</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Tool / feature" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/254" target="_blank" rel="noreferrer noopener">Compact Strings</a></div></td><td data-mtr-content="Since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Experimental since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr></tbody></table></figure>



<h2 class="wp-block-heading" id="removals">Deprecated/removed features and APIs:</h2>



<figure class="wp-block-table"><table class="mtr-table mtr-tr-td"><tbody><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content">Feature / API</div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">Deprecated since</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">Removed since</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/421" target="_blank" rel="noreferrer noopener">Deprecate Finalization for Removal</a> (<code>finalize()</code> and similar methods)</div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">18</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/411" data-type="URL" data-id="https://openjdk.java.net/jeps/411" target="_blank" rel="noreferrer noopener">Deprecate the Security Manager for Removal</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">17</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/390" target="_blank" rel="noreferrer noopener">Constructors of primitive wrapper classes</a> (e.g. <code>new Integer(1)</code>)</div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">16</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/366" target="_blank" rel="noreferrer noopener">ParallelScavenge + SerialOld GC Combination</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">14</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/289" target="_blank" rel="noreferrer noopener">Applet API</a> (<a href="https://openjdk.java.net/jeps/398" target="_blank" rel="noreferrer noopener">Deprecated For Removal</a> in Java 17)</div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/407" data-type="URL" data-id="https://openjdk.java.net/jeps/407" target="_blank" rel="noreferrer noopener">RMI Activation</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">15</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">17</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a rel="noreferrer noopener" href="https://openjdk.java.net/jeps/403" target="_blank">Strongly Encapsulate JDK Internals</a> (except sun.misc.Unsafe and some more)<br>– internal JDK classes won’t be available anymore</div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">17</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/335" target="_blank" rel="noreferrer noopener">Nashorn JavaScript Engine</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">15</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/381" target="_blank" rel="noreferrer noopener">Solaris and SPARC Ports</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">14</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">15</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content">CMS GC</div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">14</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/367" target="_blank" rel="noreferrer noopener">Pack200 Tools and API</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">14</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://www.infoworld.com/article/3305073/removed-from-jdk-11-javafx-11-arrives-as-a-standalone-module.html" target="_blank" rel="noreferrer noopener">Java FX</a> (moved to <a href="https://openjfx.io/" target="_blank" rel="noreferrer noopener">OpenJFX</a>)</div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://www.oracle.com/java/technologies/javase/11-relnote-issues.html" target="_blank" rel="noreferrer noopener">Java Web Start</a> (was only in Oracle JDK)</div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/320" target="_blank" rel="noreferrer noopener">Java EE and CORBA modules</a> (JAX-WS, JAXB, JAF, Common Annotations, CORBA, JTA)<br>Look here to find <a href="https://stackoverflow.com/questions/48204141/replacements-for-deprecated-jpms-modules-with-java-ee-apis" target="_blank" rel="noreferrer noopener">replacements for the removed modules</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">11</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/313" target="_blank" rel="noreferrer noopener">javah</a> <a href="http://openjdk.java.net/jeps/313" target="_blank" rel="noreferrer noopener">Native-Header Generator</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">10</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/241" target="_blank" rel="noreferrer noopener">jhat Heap Visualizer</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/231" target="_blank" rel="noreferrer noopener">Launch-Time JRE Version Selection</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/220#Removed:-rt-jar-and-tools-jar" target="_blank" rel="noreferrer noopener">rt.jar and tools.jar</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content"></div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="https://openjdk.java.net/jeps/220#Removed:-The-extension-mechanism" target="_blank" rel="noreferrer noopener">The extension mechanism (java.ext.dirs property)</a></div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td></tr><tr><td data-mtr-content="Feature / API" class="mtr-td-tag"><div class="mtr-cell-content"><a href="http://openjdk.java.net/jeps/214" target="_blank" rel="noreferrer noopener">Rarely-Used GC Combinations</a> </div></td><td data-mtr-content="Deprecated since" class="mtr-td-tag"><div class="mtr-cell-content">8</div></td><td data-mtr-content="Removed since" class="mtr-td-tag"><div class="mtr-cell-content">9</div></td></tr></tbody></table></figure>



<p>For more details, the <a href="https://javaalmanac.io/" target="_blank" rel="noreferrer noopener">javaalmanac.io/</a> catalog is very useful to browse the changes in Java thoughout all its history. It can give you complete diff of APIs between selected Java versions, e.g. <a href="https://javaalmanac.io/jdk/11/apidiff/8/" target="_blank" rel="noreferrer noopener">between Java 8 and Java 11</a>. Very useful If you&#8217;re thinking about migrating to a specific Java version.</p>



<p>Dávid Csákvári also wrote a similar article as mine for <a rel="noreferrer noopener" href="https://advancedweb.hu/a-categorized-list-of-all-java-and-jvm-features-since-jdk-8-to-16/" target="_blank">new features between Java 8 and Java 17</a>, which is more detailed and with a lot of useful examples.</p>



<p>If you want to get started with Java 17 quickly and try out all the new features, here&#8217;s a nice article to follow to get you started fast: <a href="https://examples.javacodegeeks.com/java-17-new-features-tutorial/" target="_blank" rel="noreferrer noopener">Java 17 New Features Tutorial</a>.</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/new-features-in-java-versions-since-java-8/">New features between Java 8 and Java 19</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/new-features-in-java-versions-since-java-8/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">769</post-id>	</item>
		<item>
		<title>Introduction to concurrency and threads in Java web apps</title>
		<link>https://ondro.inginea.eu/index.php/introduction-to-concurrency-and-threads-in-java-web-apps/</link>
					<comments>https://ondro.inginea.eu/index.php/introduction-to-concurrency-and-threads-in-java-web-apps/#respond</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Sun, 03 Jul 2022 10:11:13 +0000</pubDate>
				<category><![CDATA[Jakarta EE]]></category>
		<category><![CDATA[javaee]]></category>
		<category><![CDATA[jakartaee]]></category>
		<category><![CDATA[concurrency]]></category>
		<guid isPermaLink="false">https://ondro.inginea.eu/?p=998</guid>

					<description><![CDATA[<p>Threads, concurrency, or synchronization are not very easy to understand concepts. Jakarta EE builds on standard Java features and makes them easier to understand and use, using the thread pool concept and the Jakarta Concurrency API.</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/introduction-to-concurrency-and-threads-in-java-web-apps/">Introduction to concurrency and threads in Java web apps</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Threads, concurrency, or synchronization are not very easy to understand concepts. When some concurrency is involved in our applications it&#8217;s pretty hard to avoid making mistakes. Although Java provides mechanisms to deal with parallel programming, sometimes there are just too many options. And often some essential options are missing. For web applications, Jakarta EE provides a simplified programming model to deal with parallel tasks. But in order to use it effectively and avoid mistakes, you need to understand the basic concepts which I&#8217;d like to explain here.</p>



<span id="more-998"></span>



<p>Java provides a lot of mechanisms to help working with threads and concurrent tasks. As Java evolved, some new mechanisms were added while old mechanisms stayed. And it&#8217;s often not clear which of them are better and recommended to use in new applications. Jakarta EE builds on these features and makes them easier to understand and use. The standard Jakarta EE API intentionally specifies only interfaces and essential conceptual behavior. A lot of the complexity is abstracted away and provided by Jakarta EE runtimes to keep things simple. As a result, developers have a concise set of features. Easy to learn and understand but enough to build applications.</p>



<div class="wp-block-group omnifish-advert has-white-color has-text-color has-background is-layout-flow" style="background-color:#0b8f9b"><div class="wp-block-group__inner-container">
<div class="wp-block-media-text alignwide has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-center has-white-color has-text-color" style="grid-template-columns:auto 15%"><div class="wp-block-media-text__content">
<p class="has-medium-font-size"><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank"><strong>Need help with GlassFish, Jakarta EE, Java in the cloud?</strong></a></p>



<p><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank">Follow me at <strong>OmniFish</strong>! </a></p>
</div><figure class="wp-block-media-text__media"><a href="https://omnifish.ee"><img decoding="async" loading="lazy" width="300" height="178" src="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&#038;ssl=1" alt="" class="wp-image-1034 size-medium" srcset="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&amp;ssl=1 300w, https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?w=400&amp;ssl=1 400w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></figure></div>
</div></div>



<h2 class="wp-block-heading">What is a thread pool</h2>



<p>The basic concept of threading and parallelism in Jakarta EE runtimes is a <strong>thread pool</strong>. This is connected with the request processing model, where most of the tasks originate as a <strong>request from an external caller</strong>, they are then processed sequentially in a <strong>single thread</strong>, and produce some <strong>response</strong> that is usually sent back to the caller, persisted into a database or sent as a message to another system. Many separate tasks can run in parallel, each using its own separate thread. So there&#8217;s usually a simple mapping &#8211; one request needs one thread. After a task is finished, a thread doesn&#8217;t have to be destroyed. It can be reused to run another task, in order to avoid creating and destroying threads too often.</p>



<p>Incoming tasks are not tied with any specific thread. A thread pool always makes sure there&#8217;s a thread available for a task. This is called &#8220;scheduling&#8221; and is often referred to as &#8220;thread scheduling&#8221;. Tasks are scheduled and processed either:</p>



<p>by an existing thread that is finished with its previous task</p>



<p>by a new thread if no free thread is available</p>



<p>or they are queued and wait until a thread is available if all threads are busy</p>



<p>Vice versa, threads aren&#8217;t tied to tasks either. They just take a task from a queue and process it. When threads are done with their tasks, they start processing another new task from a queue or wait for a task if the queue is empty. A group of such threads, together with the logic how they are managed and scheduled, is called a thread pool.</p>



<h2 class="wp-block-heading">Why thread pools?</h2>



<p>Thread pools are used because it&#8217;s time-consuming to dispose a thread and create a new thread later. A new thread is created only when there&#8217;s no idle thread already available. And they are disposed only when there are already too many idle threads it&#8217;s likely not going to be needed for some time.</p>



<p>Another aspect of thread pools is that their size is limited and adapts to the load. This is mainly for 3 reasons:</p>



<ul>
<li>Threads allocates some memory for their stacks and keep the memory until the threads are disposed</li>



<li>The CPU can run very small number of threads at once; having too many threads can even lead to performance degradation</li>



<li>Each task requires some heap memory; it makes sense to limit the maximum number of parallel tasks to avoid overwhelming the system</li>
</ul>



<p>The memory argument is pretty clear and often it&#8217;s evident when it becomes and issue. There&#8217;s always a limited amount of memory on the system. When threads consume a big portion of that memory, it&#8217;s easy to reach the limit. The default stack size for each thread is 1MB, which means that each thread needs 1MB of system memory. If there are 1000 threads in a JVM, they clearly need 1GB of memory on top of the Java heap size just to exist. You can probably imagine the consequences if there are even more threads. </p>



<p>The CPU argument isn&#8217;t so straightforward but is really valid. Only X amount of threads can run on a CPU at the same time (usually 8 on an 8-core CPU). With more threads, it&#8217;s more likely that a thread will be suspended and another thread will be scheduled. Switching of threads is a relatively time-consuming operation and doesn&#8217;t contribute to the computation. Therefore, having an excessive amount of threads can actually decrease performance.</p>



<p>The last argument is that executing too many tasks in parallel costs too much memory as each tasks needs to store something to the heap even if it&#8217;s waiting for an I/O operation or the CPU. As described above, more parallel tasks doesn&#8217;t not always lead to increased performance. But it definitely leads to increased memory. Therefore it&#8217;s better to limit how many tasks can run in parallel and queue other tasks to be executed later.</p>



<p>For these reasons, it&#8217;s good to have some reasonable amount of threads ready to handle new tasks immediately. It&#8217;s also necessary to limit the number of threads to a reasonable amount. And threads should also be disposed after some time if they are really not needed. With this, it&#8217;s possible to avoid system become thrashed and unusable under high load.  If there are too many requests to handle, some of them simply need to wait while others can be efficiently processed. This will make the system usable at least for some requests/users.</p>



<p>Sometimes a single request needs to be processed by multiple threads in parallel. This doesn&#8217;t fit the simplified thread-per-request model but it&#8217;s also supported by Jakarta EE runtimes. Applications can use a specialized <a href="https://jakarta.ee/specifications/concurrency/" target="_blank" rel="noreferrer noopener">concurrency API</a>, which allows splitting a task and execute each part in a separate thread. This again works on top of thread pools to retain all the advantages mentioned above. </p>



<p></p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/introduction-to-concurrency-and-threads-in-java-web-apps/">Introduction to concurrency and threads in Java web apps</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/introduction-to-concurrency-and-threads-in-java-web-apps/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">998</post-id>	</item>
		<item>
		<title>Get logged-in user info in Jakarta EE &#8211; the simplest way</title>
		<link>https://ondro.inginea.eu/index.php/get-user-info-in-jakarta-ee/</link>
					<comments>https://ondro.inginea.eu/index.php/get-user-info-in-jakarta-ee/#respond</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Sat, 13 Nov 2021 20:06:13 +0000</pubDate>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[javaee]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">https://ondro.inginea.eu/?p=931</guid>

					<description><![CDATA[<p>The security before Java EE 8 / Jakarta EE 8 used to be a bit complicated and confusing. Every specification provided its own way to retrieve information about the logged-in user. The situation greatly improved with the introduction of the Security API that provides a unified way to do that &#8211; simply inject the SecurityContext [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/get-user-info-in-jakarta-ee/">Get logged-in user info in Jakarta EE &#8211; the simplest way</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>The security before Java EE 8 / Jakarta  EE 8 used to be a bit complicated and confusing. Every specification provided its own way to retrieve information about the logged-in user. The situation greatly improved with the introduction of the <a href="https://jakarta.ee/specifications/security/">Security API</a> that provides a unified way to do that &#8211; simply inject the SecurityContext CDI bean. </p>



<span id="more-931"></span>



<p>There&#8217;s still a small catch &#8211; this only works in the servlet context and EJB context. Or, in other words, when processing an HTTP request or inside any type of EJB. The good thing is that this covers most of the cases in which you&#8217;ll ever need to retrieve user information. In the other rare cases, you need to use one of the APIs which I also describe in this post.</p>



<div class="wp-block-group omnifish-advert has-white-color has-text-color has-background is-layout-flow" style="background-color:#0b8f9b"><div class="wp-block-group__inner-container">
<div class="wp-block-media-text alignwide has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-center has-white-color has-text-color" style="grid-template-columns:auto 15%"><div class="wp-block-media-text__content">
<p class="has-medium-font-size"><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank"><strong>Need help with GlassFish, Jakarta EE, Java in the cloud?</strong></a></p>



<p><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank">Follow me at <strong>OmniFish</strong>! </a></p>
</div><figure class="wp-block-media-text__media"><a href="https://omnifish.ee"><img decoding="async" loading="lazy" width="300" height="178" src="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&#038;ssl=1" alt="" class="wp-image-1034 size-medium" srcset="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&amp;ssl=1 300w, https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?w=400&amp;ssl=1 400w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></figure></div>
</div></div>



<h2 class="wp-block-heading">Unified access to user info using Security API</h2>



<p>With the Security API, retrieving information about the current user is pretty easy straightforward:</p>



<ul>
<li>Inject <a href="https://jakarta.ee/specifications/security/2.0/jakarta-security-spec-2.0.html#security-context">SecurityContext</a></li>



<li>Get the name of the user<ul><li>Call the method <code>getCallerPrincipal()</code></li></ul>
<ul>
<li>If the result is <code>null</code>, no user is logged in</li>



<li>Otherwise, call the method <code>getName()</code> to get the name of the logged-in user</li>
</ul>
</li>



<li>Verify that a user has a specific role (permission)
<ul>
<li>Call the method <code>isCallerInRole(roleName)</code></li>
</ul>
</li>
</ul>



<p>Full example of a servlet that prints user&#8217;s name and whether the user is in role &#8220;admin&#8221;:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-4" data-shcb-language-name="Java" data-shcb-language-slug="java"><span><code class="hljs language-java shcb-code-table shcb-wrap-lines"><span class='shcb-loc'><span><span class="hljs-meta">@WebServlet</span>(urlPatterns = <span class="hljs-string">"/servlet"</span>)
</span></span><span class='shcb-loc'><span><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserInfoServlet</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> </span>{
</span></span><span class='shcb-loc'><span>
</span></span><mark class='shcb-loc'><span>    <span class="hljs-meta">@Inject</span>
</span></mark><mark class='shcb-loc'><span>    SecurityContext userContext;
</span></mark><span class='shcb-loc'><span>    
</span></span><span class='shcb-loc'><span>    <span class="hljs-meta">@Override</span>
</span></span><span class='shcb-loc'><span>    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doGet</span><span class="hljs-params">(HttpServletRequest req, HttpServletResponse resp)</span> <span class="hljs-keyword">throws</span> ServletException, IOException </span>{
</span></span><span class='shcb-loc'><span>
</span></span><mark class='shcb-loc'><span>        <span class="hljs-comment">// retrieve the principal and later check whether it's null or not</span>
</span></mark><mark class='shcb-loc'><span>        Principal callerPrincipal = userContext.getCallerPrincipal();
</span></mark><span class='shcb-loc'><span>
</span></span><span class='shcb-loc'><span>        resp.getOutputStream().println(String.format(
</span></span><span class='shcb-loc'><span>                <span class="hljs-string">"&lt;html&gt;&lt;body&gt;"</span>
</span></span><span class='shcb-loc'><span>                + <span class="hljs-string">"&lt;p&gt;User: %s&lt;/p&gt;"</span>
</span></span><span class='shcb-loc'><span>                + <span class="hljs-string">"&lt;p&gt;Is admin: %s&lt;/p&gt;"</span>
</span></span><span class='shcb-loc'><span>              + <span class="hljs-string">"&lt;/body&gt;&lt;/html&gt;"</span>, 
</span></span><span class='shcb-loc'><span>
</span></span><mark class='shcb-loc'><span>        <span class="hljs-comment">// print user's name only if the user is logger in and principal is not null</span>
</span></mark><mark class='shcb-loc'><span>                callerPrincipal != <span class="hljs-keyword">null</span> ? callerPrincipal.getName() : <span class="hljs-string">"not logged in"</span>,
</span></mark><mark class='shcb-loc'><span>        <span class="hljs-comment">// true if user has admin role</span>
</span></mark><mark class='shcb-loc'><span>                userContext.isCallerInRole(<span class="hljs-string">"admin"</span>)));
</span></mark><span class='shcb-loc'><span>    }
</span></span><span class='shcb-loc'><span>    
</span></span><span class='shcb-loc'><span>}
</span></span><span class='shcb-loc'><span>
</span></span></code></span><small class="shcb-language" id="shcb-language-4"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">Java</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">java</span><span class="shcb-language__paren">)</span></small></pre>


<h2 class="wp-block-heading">Alternative ways to access user info</h2>



<p>In case you can&#8217;t use the Security API, you can still use one of the other APIs that provide similar access to user information. A lot of other specification APIs provide similar methods to retrieve the name of the logged-in user and to check whether the user is in a specific role. Below is a summary of all possible ways:</p>



<figure class="wp-block-table"><table class="mtr-table mtr-tr-td"><tbody><tr><td data-mtr-content="Specification API" class="mtr-td-tag"><div class="mtr-cell-content">Specification API</div></td><td data-mtr-content="Methods to call" class="mtr-td-tag"><div class="mtr-cell-content">Methods to call</div></td><td data-mtr-content="How to retrieve the user context" class="mtr-td-tag"><div class="mtr-cell-content">How to retrieve the user context</div></td></tr><tr><td data-mtr-content="Specification API" class="mtr-td-tag"><div class="mtr-cell-content">Servlet</div></td><td data-mtr-content="Methods to call" class="mtr-td-tag"><div class="mtr-cell-content"><strong>User name: </strong><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/servlet/http/HttpServletRequest.html#getUserPrincipal--" data-type="URL" data-id="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/servlet/http/HttpServletRequest.html#getUserPrincipal--" target="_blank"><code>HttpServletRequest.getUserPrincipal</code>()</a><br><br>Returns <code>null</code> if not logged in.<br><br><strong>In role: </strong><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/servlet/http/HttpServletRequest.html#isUserInRole-java.lang.String-" target="_blank"><code>HttpServletRequest.isUserInRole</code>()</a></div></td><td data-mtr-content="How to retrieve the user context" class="mtr-td-tag"><div class="mtr-cell-content"><code>@Inject<br>HttpServletRequest request;</code><br><br><code>HttpServletRequest</code> is also passed to servlet’s methods</div></td></tr><tr><td data-mtr-content="Specification API" class="mtr-td-tag"><div class="mtr-cell-content">EJB</div></td><td data-mtr-content="Methods to call" class="mtr-td-tag"><div class="mtr-cell-content"><strong>User name: </strong><code><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/ejb/EJBContext.html#getCallerPrincipal--" data-type="URL" data-id="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/ejb/EJBContext.html#getCallerPrincipal--" target="_blank">EJBContext.getCallerPrincipal()</a></code><br><br>If not logged in, returns a <code>Principal</code> with <code>getName() == "ANONYMOUS"</code> instead of <code>null</code><br><br><strong>In role: </strong><br><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/ejb/EJBContext.html#isCallerInRole-java.lang.String-" target="_blank">EJBContext.isCallerInRole()</a></div></td><td data-mtr-content="How to retrieve the user context" class="mtr-td-tag"><div class="mtr-cell-content"><code>EJBContext</code> or any of its subinterfaces can be injected in an EJB or retrieved via JNDI:<br><br><code>@Resource<br>EJBContext ejbContext;</code><br><br><code>(EJBContext)new InitialContext()</code><br>    <code>.lookup("java:comp/EJBContext")</code></div></td></tr><tr><td data-mtr-content="Specification API" class="mtr-td-tag"><div class="mtr-cell-content">REST</div></td><td data-mtr-content="Methods to call" class="mtr-td-tag"><div class="mtr-cell-content"><strong>User name:</strong><br><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/ws/rs/core/SecurityContext.html#getUserPrincipal--" data-type="URL" data-id="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/ws/rs/core/SecurityContext.html#getUserPrincipal--" target="_blank"><code>SecurityContext.getUserPrincipal()</code></a><br><br>Returns <code>null</code> if not logged in.<br><br><strong>In role:</strong><br><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/ws/rs/core/SecurityContext.html#isUserInRole-java.lang.String-" target="_blank"><code>SecurityContext.isUserInRole()</code></a></div></td><td data-mtr-content="How to retrieve the user context" class="mtr-td-tag"><div class="mtr-cell-content"><code>@Context<br>SecurityContext security;</code></div></td></tr><tr><td data-mtr-content="Specification API" class="mtr-td-tag"><div class="mtr-cell-content">JSF</div></td><td data-mtr-content="Methods to call" class="mtr-td-tag"><div class="mtr-cell-content"><strong>User name:</strong><br><code><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/faces/context/ExternalContext.html#getUserPrincipal--" data-type="URL" data-id="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/faces/context/ExternalContext.html#getUserPrincipal--" target="_blank">ExternalContext.getUserPrincipal()</a></code><br><br>Returns <code>null</code> if not logged in.<br><br><strong>In role:</strong><br><code><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/faces/context/ExternalContext.html#isUserInRole-java.lang.String-" target="_blank">ExternalContext.isUserInRole()</a></code></div></td><td data-mtr-content="How to retrieve the user context" class="mtr-td-tag"><div class="mtr-cell-content"><code>@Inject <br>ExternalContext externalContext;</code><br><br><code>FacesContext.getCurrentInstance()</code><br>    <code>.getExternalContext()</code></div></td></tr><tr><td data-mtr-content="Specification API" class="mtr-td-tag"><div class="mtr-cell-content">CDI</div></td><td data-mtr-content="Methods to call" class="mtr-td-tag"><div class="mtr-cell-content"><strong>User name:</strong><br><code><a rel="noreferrer noopener" href="https://docs.oracle.com/javase/8/docs/api/java/security/Principal.html" data-type="URL" data-id="https://docs.oracle.com/javase/8/docs/api/java/security/Principal.html" target="_blank">@Inject Principal principal;</a></code><br><br>If not logged in, injects a <code>Principal</code> with <code>getName() == "ANONYMOUS"</code>, similar to EJB<br><br><strong>In role:</strong>  Not available</div></td><td data-mtr-content="How to retrieve the user context" class="mtr-td-tag"><div class="mtr-cell-content"><code>@Inject Principal principal;</code></div></td></tr><tr><td data-mtr-content="Specification API" class="mtr-td-tag"><div class="mtr-cell-content">WebSocket</div></td><td data-mtr-content="Methods to call" class="mtr-td-tag"><div class="mtr-cell-content"><strong>User name:</strong><br><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/websocket/Session.html#getUserPrincipal--" data-type="URL" data-id="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/websocket/Session.html#getUserPrincipal--" target="_blank"><code>Session.getUserPrincipal()</code></a><br><br>Returns <code>null</code> if not logged in.<br><br><strong>In role:</strong>  Not available</div></td><td data-mtr-content="How to retrieve the user context" class="mtr-td-tag"><div class="mtr-cell-content"><code>Session</code> is passed as an argument to handlers of WebSocket events</div></td></tr><tr><td data-mtr-content="Specification API" class="mtr-td-tag"><div class="mtr-cell-content">XML Web Services</div></td><td data-mtr-content="Methods to call" class="mtr-td-tag"><div class="mtr-cell-content"><strong>User name:</strong><br><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/xml/ws/WebServiceContext.html#getUserPrincipal--" data-type="URL" data-id="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/xml/ws/WebServiceContext.html#getUserPrincipal--" target="_blank"><code>WebServiceContext.getUserPrincipal()</code></a><br><br>Returns <code>null</code> if not logged in.<br><br><strong>In role:</strong><br><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/9/apidocs/jakarta/xml/ws/WebServiceContext.html#isUserInRole-java.lang.String-" target="_blank"><code>WebServiceContext.isUserInRole()</code></a></div></td><td data-mtr-content="How to retrieve the user context" class="mtr-td-tag"><div class="mtr-cell-content"><code>WebServiceContext</code> can be injected in a WS endpoint:<br><br><code>@Resource<br>WebServiceContext wsContext;</code></div></td></tr></tbody></table></figure>



<p></p>



<p>The Security specification also provides a summary of all the available methods to retrieve user&#8217;s name and role information in <a href="https://jakarta.ee/specifications/security/2.0/jakarta-security-spec-2.0.html#relationship-to-other-specifications-3">4.5. Relationship to Other Specifications</a>.</p>



<h2 class="wp-block-heading">What&#8217;s the best way?</h2>



<p>I&#8217;d certainly <strong>recommend using only the Security API&#8217;s <a href="https://jakarta.ee/specifications/security/2.0/jakarta-security-spec-2.0.html#security-context">SecurityContext</a></strong> whenever possible, for the following reasons:</p>



<ul>
<li>It&#8217;s a unified API so you can learn and remember a single way to access user information</li>



<li>It&#8217;s easy to use, just inject it as a CDI bean</li>



<li>It provides all the information provided by any of the other APIs</li>



<li>It&#8217;s cleaner in case the user isn&#8217;t logged &#8211; returns <code>null</code> Principal instead of a Principal with a default name</li>
</ul>



<p>The only drawback is that currently it only works in Servlet and EJB contexts. Even though these 2 contexts are the most widely used, it&#8217;s still possible that in some rare cases the Security API can&#8217;t be used. Hopefully, the future versions of the Security specification will also cover other contexts. And even if not, the contexts where it wouldn&#8217;t work are related to some legacy and old Jakarta APIs and are nowadays very rarely used. In fact so rarely that you will probably not use any of them ever.</p>



<p></p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/get-user-info-in-jakarta-ee/">Get logged-in user info in Jakarta EE &#8211; the simplest way</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/get-user-info-in-jakarta-ee/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">931</post-id>	</item>
		<item>
		<title>How to properly inject CDI beans into JAX-RS sub-resources</title>
		<link>https://ondro.inginea.eu/index.php/portable-cdi-injection-into-jax-rs-sub-resources/</link>
					<comments>https://ondro.inginea.eu/index.php/portable-cdi-injection-into-jax-rs-sub-resources/#respond</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Tue, 26 Oct 2021 15:24:12 +0000</pubDate>
				<category><![CDATA[REST]]></category>
		<guid isPermaLink="false">https://ondro.inginea.eu/?p=910</guid>

					<description><![CDATA[<p>Jakarta REST (JAX-RS) defines it&#8217;s own dependency injection using the @Context annotation. REST resources also support CDI injection if you enable CDI on the REST resource class (e.g. using a bean-defining annotation like @RequestScoped). But injection doesn&#8217;t work out of the box on JAX-RS sub-resources. How to create sub-resources so that both injection mechanisms work [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/portable-cdi-injection-into-jax-rs-sub-resources/">How to properly inject CDI beans into JAX-RS sub-resources</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Jakarta REST (JAX-RS) defines it&#8217;s own dependency injection using the <a href="https://jakarta.ee/specifications/platform/8/apidocs/javax/ws/rs/core/Context.html" target="_blank" rel="noreferrer noopener"><code>@Context</code></a> annotation. REST resources also support <a href="https://jakarta.ee/specifications/cdi/" target="_blank" rel="noreferrer noopener"><code>CDI injection</code></a> if you enable CDI on the REST resource class (e.g. using a bean-defining annotation like <a href="https://jakarta.ee/specifications/platform/8/apidocs/javax/enterprise/context/requestscoped" target="_blank" rel="noreferrer noopener"><code>@RequestScoped</code></a>). </p>



<p>But injection doesn&#8217;t work out of the box on JAX-RS <a href="https://jakarta.ee/specifications/restful-ws/3.0/jakarta-restful-ws-spec-3.0.html#sub_resources" target="_blank" rel="noreferrer noopener">sub-resources</a>. How to create sub-resources so that both injection mechanisms work also in sub-resources? I&#8217;ll show you, it&#8217;s very easy.</p>



<span id="more-910"></span>



<h2 class="wp-block-heading">How to do it (for the impatient)</h2>



<ul>
<li>Inject the sub-resource into the JAX-RS resource via the <code>@Inject</code> annotation</li>



<li>Initialize the sub-resource using the <a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/8/apidocs/javax/ws/rs/container/ResourceContext.html" target="_blank">ResourceContext</a> object injected via the <code>@Context</code> annotation</li>
</ul>


<pre class="wp-block-code" aria-describedby="shcb-language-5" data-shcb-language-name="CSS" data-shcb-language-slug="css"><span><code class="hljs language-css"><span class="hljs-keyword">@Path</span>("request")
@RequestScoped
public class RestResource {

    <span class="hljs-keyword">@Inject</span> // inject subresource as CDI bean
    SubResource subResource;
    
    <span class="hljs-keyword">@Context</span> // inject from JAX-RS container
    ResourceContext resourceContext;
    
    <span class="hljs-keyword">@Path</span>("subresource")
    public SubResource getSubresource() {
        <span class="hljs-selector-tag">return</span> <span class="hljs-selector-tag">resourceContext</span><span class="hljs-selector-class">.initResource</span>(<span class="hljs-selector-tag">subResource</span>);
    }
}</code></span><small class="shcb-language" id="shcb-language-5"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">CSS</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">css</span><span class="shcb-language__paren">)</span></small></pre>


<div class="wp-block-group omnifish-advert has-white-color has-text-color has-background is-layout-flow" style="background-color:#0b8f9b"><div class="wp-block-group__inner-container">
<div class="wp-block-media-text alignwide has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-center has-white-color has-text-color" style="grid-template-columns:auto 15%"><div class="wp-block-media-text__content">
<p class="has-medium-font-size"><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank"><strong>Need help with GlassFish, Jakarta EE, Java in the cloud?</strong></a></p>



<p><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank">Follow me at <strong>OmniFish</strong>! </a></p>
</div><figure class="wp-block-media-text__media"><a href="https://omnifish.ee"><img decoding="async" loading="lazy" width="300" height="178" src="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&#038;ssl=1" alt="" class="wp-image-1034 size-medium" srcset="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&amp;ssl=1 300w, https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?w=400&amp;ssl=1 400w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></figure></div>
</div></div>



<h2 class="wp-block-heading">Full story</h2>



<p>First, let&#8217;s briefly explain what a sub-resource is. It&#8217;s a class that looks similar to a usual JAX-RS resource but it&#8217;s not used standalone. Instead, an instance of this class can be returned from a JAX-RS resource to map it to a subpath of that resource. Therefore a JAX-RS resource can delegate processing of a specific subpath to another class. Sub resources look like any other JAX-RS resources but don&#8217;t specify the <code><a rel="noreferrer noopener" href="https://jakarta.ee/specifications/platform/8/apidocs/javax/ws/rs/Path.html" target="_blank">@Path</a></code> annotation. The path is defined on the resource method that returns the sub resource:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-7" data-shcb-language-name="PHP" data-shcb-language-slug="php"><span><code class="hljs language-php"><span class="hljs-comment">// Sub-resource - no @Path annotation on the class</span>
@RequestScoped
@Produces(MediaType.TEXT_PLAIN)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SubResource</span> </span>{
    
    @GET
    <span class="hljs-keyword">public</span> String getMessage() {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"This is a sub-resource."</span>;
    }
}</code></span><small class="shcb-language" id="shcb-language-7"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">PHP</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">php</span><span class="shcb-language__paren">)</span></small></pre>

<pre class="wp-block-code" aria-describedby="shcb-language-8" data-shcb-language-name="PHP" data-shcb-language-slug="php"><span><code class="hljs language-php">@Path(<span class="hljs-string">"request"</span>) <span class="hljs-comment">// defines the path "request" for this resource</span>
@RequestScoped
@Produces(MediaType.TEXT_PLAIN)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RestResource</span> </span>{

    @GET
    <span class="hljs-keyword">public</span> String getMessage() {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"This is a JAX-RS resource."</span>;
    }

    @Path(<span class="hljs-string">"subresource"</span>) <span class="hljs-comment">// defines the subpath for the sub-resource: "request/subresource"</span>
    <span class="hljs-keyword">public</span> SubResource getSubresource() {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> SubResource();
    }
}</code></span><small class="shcb-language" id="shcb-language-8"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">PHP</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">php</span><span class="shcb-language__paren">)</span></small></pre>


<p>If you access path <code>/request</code>, the response will contain &#8220;This is a JAX-RS resource.&#8221;</p>



<p>If you access path <code>/request/subresource</code>, the response will contain &#8220;This is a sub-resource.&#8221;</p>



<p>However, the catch is that with the simple example above, <strong>no injection works in the subresource</strong>. it&#8217;s not possible to inject anything into the SubResource class, any atempt to do so will result in <code>null</code> values for injected fields. It&#8217;s created as a plain Java object in the <code>getSubresource()</code> method and thus it&#8217;s not managed by any container. The <code><a href="https://jakarta.ee/specifications/platform/8/apidocs/javax/enterprise/context/RequestScoped.html" target="_blank" rel="noreferrer noopener">@RequestScoped</a></code> annotation is ignored in this case and anything marked with the <code>@Inject</code> or <code>@Context</code> annotation would be also ignored and remain <code>null</code>.</p>



<p>Injection works on JAX-RS resources because they are created by the JAX-RS container and not using the <code>new</code> keyword. If CDI is also enabled on the resource class, Jakarta EE runtime will first create the JAX-RS resource as a CDI bean and then pass it to the JAX-RS container, which then does its own injection. </p>



<p>None of this happens if a sub resource is created using <code>new</code>, therefore we must create it in a different way.</p>



<h2 class="wp-block-heading">Solution</h2>



<p>2 simple steps are needed to add support for both types of injection in JAX-RS sub-resources:</p>



<ul>
<li>Inject the sub-resource into the JAX-RS resource. This enables the CDI injection</li>



<li>Initialize the sub-resource using the <a href="https://jakarta.ee/specifications/platform/8/apidocs/javax/ws/rs/container/ResourceContext.html" target="_blank" rel="noreferrer noopener">ResourceContext</a> object provided by the JAX-RS container. This enables JAX-RS injection for values annotated with <code>@Context</code></li>
</ul>



<p>This is how the <code>RestResource</code> class should look like to create the sub-resource properly:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-9" data-shcb-language-name="PHP" data-shcb-language-slug="php"><span><code class="hljs language-php">@Path(<span class="hljs-string">"request"</span>)
@RequestScoped
@Produces(MediaType.TEXT_PLAIN)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RestResource</span> </span>{

    @Inject <span class="hljs-comment">// inject subresource as CDI bean</span>
    SubResource subResource;
    
    @Context <span class="hljs-comment">// inject from JAX-RS container</span>
    ResourceContext resourceContext;
    
    @GET
    <span class="hljs-keyword">public</span> String getMessage() {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"This is a JAX-RS resource."</span>;
    }

    @Path(<span class="hljs-string">"subresource"</span>)
    <span class="hljs-keyword">public</span> SubResource getSubresource() {
        <span class="hljs-keyword">return</span> resourceContext.initResource(subResource);
    }
}</code></span><small class="shcb-language" id="shcb-language-9"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">PHP</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">php</span><span class="shcb-language__paren">)</span></small></pre>


<blockquote class="wp-block-quote">
<p>NOTE: You need to use the <code>initResource</code> method of <code>ResourceContext</code> and not the <code>getResource</code> method. The <code>getResource</code> method creates a new JAX-RS sub-resource from a class but it&#8217;s not guaranteed that it also enables CDI injection for it. Although some Jakarta EE runtimes will enable CDI injection if you call the <code>getResource</code> method, it&#8217;s known that some of them like <a rel="noreferrer noopener" href="https://github.com/OpenLiberty/open-liberty/issues/7422" target="_blank">OpenLiberty</a> and <a rel="noreferrer noopener" href="https://github.com/payara/Payara/issues/5467" target="_blank">Payara</a> don&#8217;t do it. In the future, this will very probably be improved when the @Context injection will be replaced by CDI injection, which is <a rel="noreferrer noopener" href="https://github.com/eclipse-ee4j/jaxrs-api/issues/951" target="_blank">already planned</a>.</p>
</blockquote>



<p>Now you can use both types of injection and all will work as expected:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-10" data-shcb-language-name="CSS" data-shcb-language-slug="css"><span><code class="hljs language-css"><span class="hljs-keyword">@RequestScoped</span>
@Produces(MediaType.TEXT_PLAIN)
public class SubResource {

    <span class="hljs-keyword">@Inject</span>
    SomeCdiBean bean;

    <span class="hljs-keyword">@Context</span>
    UriInfo uriInfo
    
    @GET
    public String getMessage() {
        <span class="hljs-selector-tag">return</span> <span class="hljs-selector-tag">bean</span><span class="hljs-selector-class">.getMessage</span>() + ", <span class="hljs-selector-tag">path</span>: " + <span class="hljs-selector-tag">uriInfo</span><span class="hljs-selector-class">.getPath</span>();
    }
}</code></span><small class="shcb-language" id="shcb-language-10"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">CSS</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">css</span><span class="shcb-language__paren">)</span></small></pre>


<p></p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/portable-cdi-injection-into-jax-rs-sub-resources/">How to properly inject CDI beans into JAX-RS sub-resources</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/portable-cdi-injection-into-jax-rs-sub-resources/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">910</post-id>	</item>
		<item>
		<title>Jakarta EE experts at EclipseCon 2021</title>
		<link>https://ondro.inginea.eu/index.php/jakarta-ee-experts-at-eclipsecon-2021/</link>
					<comments>https://ondro.inginea.eu/index.php/jakarta-ee-experts-at-eclipsecon-2021/#respond</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Mon, 23 Aug 2021 21:00:25 +0000</pubDate>
				<category><![CDATA[Events & Conferences]]></category>
		<category><![CDATA[EclipseFoundation]]></category>
		<category><![CDATA[JakartaEE]]></category>
		<guid isPermaLink="false">https://ondro.inginea.eu/?p=877</guid>

					<description><![CDATA[<p>EclipseCon conference is a great event for all Java developers, especially those who are passionate about and believe in opensource. The conference is scheduled for 26-28 October 2021. I wholeheartedly recommend to attend it. It&#8217;s a free online event, you just need to register to attend: https://www.eclipsecon.org/2021 Specifically for users of Jakarta EE it might [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/jakarta-ee-experts-at-eclipsecon-2021/">Jakarta EE experts at EclipseCon 2021</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>EclipseCon conference is a great event for all Java developers, especially those who are passionate about and believe in opensource. The conference is scheduled for 26-28 October 2021. I wholeheartedly recommend to attend it. It&#8217;s a free online event, you just need to register to attend: <a href="https://www.eclipsecon.org/2021">https://www.eclipsecon.org/2021</a></p>



<p>Specifically for users of Jakarta EE it might be even more interesting to attend the Jakarta EE Community Day, which happens the day before the main conference on 25 October 2021. It&#8217;s open to all people that register for the main EclipseCon event. There&#8217;s a packed agenda centered on the Jakarta EE, MicroProfile and Cloud Native Java communities, including topics like the present and future of MicroProfile and Jakarta EE, and upcoming features in Jakarta Security, Jakarta Concurrency, Jakarta REST, and Jakarta NoSQL.</p>



<p>If you&#8217;re interested, I recommend reading an article of Reza Rahman about what&#8217;s happening at the <a href="https://reza-rahman.me/2021/08/07/why-you-should-join-eclipsecon-2021-community-day/">Community Day and why to attend it</a>. Or simply go ahead and <a href="https://www.eclipsecon.org/2021">register for EclipseCon 2021</a>!</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/jakarta-ee-experts-at-eclipsecon-2021/">Jakarta EE experts at EclipseCon 2021</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/jakarta-ee-experts-at-eclipsecon-2021/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">877</post-id>	</item>
		<item>
		<title>Possible ways to use Arquillian in Jakarta EE TCKs</title>
		<link>https://ondro.inginea.eu/index.php/possible-ways-to-use-arquillian-in-jakarta-ee-tcks/</link>
					<comments>https://ondro.inginea.eu/index.php/possible-ways-to-use-arquillian-in-jakarta-ee-tcks/#respond</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Sun, 12 Apr 2020 13:49:42 +0000</pubDate>
				<category><![CDATA[Jakarta EE]]></category>
		<category><![CDATA[javaee]]></category>
		<category><![CDATA[Payara]]></category>
		<category><![CDATA[JakartaEE]]></category>
		<category><![CDATA[TCK]]></category>
		<category><![CDATA[Arquillian]]></category>
		<category><![CDATA[JUnit5]]></category>
		<guid isPermaLink="false">http://ondro.inginea.eu/?p=806</guid>

					<description><![CDATA[<p>Recently, we had a discussion how to create a standalone Jakarta Batch test kit (TCK). For most of the committers, it&#8217;s pretty natural to use Arquillian to abstracts tests away from how they are executed on an implementation. But Romain proposed an intriguing idea to use plain JUnit5 that got me thinking. And it didn&#8217;t [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/possible-ways-to-use-arquillian-in-jakarta-ee-tcks/">Possible ways to use Arquillian in Jakarta EE TCKs</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Recently, we had <a href="https://www.eclipse.org/lists/jakartabatch-dev/msg00053.html">a discussion</a> how to create a standalone Jakarta Batch test kit (TCK). For most of the committers, it&#8217;s pretty natural to use <a href="http://arquillian.org/">Arquillian</a> to abstracts tests away from how they are executed on an implementation. But <a href="https://twitter.com/rmannibucau">Romain</a> proposed an intriguing idea to use plain JUnit5 that got me thinking. And it didn&#8217;t stop with thinking. After a few hours of hacking, I&#8217;m now able to present a proof of concept and suggest how we could use plain JUnit5 for the TCK and also how containers can be integrated with it using good old Arquillian to avoid reinventing the wheel.</p>



<span id="more-806"></span>



<blockquote class="wp-block-quote"><p>UPDATE: The Arquillian project has moved forward and it now supports JUnit5 with <a href="https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.jboss.arquillian.junit5%22">an official extension</a>. This makes it even easier to combine Arqullian with JUnit5. I&#8217;ve updated my article to refer to this official extension.</p></blockquote>



<p>The problem with the current standalone Batch TCK is that it&#8217;s based on <a href="https://testng.org/">TestNG</a> and only supports Batch implementations that run on the same classpath as the test suite. Therefore it doesn&#8217;t support running tests in Java containers like application servers. Such containers are now supported only by the Jakarta test suite (CTS) which contains a copy of Batch TCK tests uses a proprietary technology to run tests in containers.</p>



<p>There are other Jakarta EE specifications with a standalone TCK or with plans to create it:</p>



<ul><li><a href="https://github.com/eclipse-ee4j/cdi-tck">CDI TCK</a> &#8211; uses TestNG with Arquillian</li><li><a href="https://github.com/eclipse-ee4j/beanvalidation-tck">Bean Validation</a> &#8211; uses TestNG with Arquillian</li><li><a href="https://github.com/eclipse-ee4j/jsonb-api/tree/master/tck">JSON-B</a> &#8211; in progress, uses JUnit 4 with Arquillian</li><li><a href="https://github.com/eclipse-ee4j/injection-tck/">DI TCK</a> &#8211; JUnit 4</li></ul>



<p>It&#8217;s clear that Arquillian is pretty popular among them. Only DI TCK doesn&#8217;t use it. But DI TCK also doesn&#8217;t support execution in a remote container natively, it only supports setting up a local container, e.g. using the CDI SE API if the implementation supports it.</p>



<p>I had 3 goals with my proof of concept:</p>



<ol><li>improve the TCK to make it possible to integrate with a Java container</li><li>adapt the existing example project to run JBatch with the TCK</li><li>create another example of integrating the TCK with a typical Jakarta EE server such as Payara Server</li></ol>



<p>I prefer gradual evolution rather than big bang development if it makes sense. And I realized that I will probably need Arquillian to integrate with Payara Server for my third goal anyway, even if I find a solution using JUnit 5. So I started with adding support for Arquillian into the current Batch TCK and later I hoped to reuse it to integrate Payara Server with JUnit 5. It turned out that it was a good approach and no code went to waste.</p>



<h2 class="wp-block-heading">Adding support for Arqullian</h2>



<p>Adding support for Arquillian into the Batch TCK was pretty straightforward because the tests already use TestNG and Arquillian supports TestNG out of the box. The only tricky part was to create a deployment package for each test which is required by Arquillian. In the end, this was pretty easy and required no modification of the test sources. Arquillian allows to create an extension to define a deployment package for each test so I was able to move creation of a deployment package to a separate extension. This extension can be used by implementations that need to run the tests in a container but it&#8217;s not needed in the TCK itself.</p>



<p>The only change needed in the TCK was to change each test to extend the Arquillian TestNG base class and that was it. </p>



<p>On top of the test suite, the Batch TCK contains an example TCK runner project that runs the TCK against the <a href="https://github.com/WASdev/standards.jsr352.jbatch">JBatch</a> implementation. This also needed to be changed slightly. I added Arquillian Weld SE connector, which runs the Arquillian TestNG tests in a Weld CDI container. This means the tests are executed on the same classpath as the test suite and no Arquillian deployment is needed. </p>



<p>You can see the end result in my fork here: <a href="https://github.com/OndroMih/batch-tck/pull/4">https://github.com/OndroMih/batch-tck/pull/4</a>. In summary, I added a single line of code to each TCK test and modified pom.xml of the Batch TCK and the TCK runner for JBatch.</p>



<p>This allowed me to create <a href="https://github.com/OndroMih/Payara-Batch-TCK-Runner/tree/poc-arquillian">an example project</a> for running the TCK with a remote server like Payara Server. This example project contains the Arquillian extension I mentioned above. This extension uses Maven resolver library to resolve JAR dependencies from the project&#8217;s pom.xml file and package them into a WAR deployment for Arquillian. It&#8217;s not complicated, it requires just a few lines of code: <a href="https://github.com/OndroMih/Payara-Batch-TCK-Runner/blob/poc-arquillian/jbatch-arquillian-extension/src/main/java/jbatch/arquillian/extension/MavenTestDependenciesDeploymentPackager.java">MavenTestDependenciesDeploymentPackager.java</a></p>



<h2 class="wp-block-heading">Converting the TCK to JUnit5</h2>



<p>Converting a TestNG-based TCK to JUnit 5 was pretty straightforward. Besides replacing all TestNG annotations with JUnit 5 equivalents, I also needed to replace TestNG reporting with the standard Java JUL logging. At that time, I didn&#8217;t know that JUnit 5 also supports reporting from tests via <a href="https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/TestReporter.html">TestReporter</a>. For a final solution, I would use that instead of JUL logging.</p>



<p>You can see the final result of my conversion here: <a href="https://github.com/OndroMih/batch-tck/pull/3">https://github.com/OndroMih/batch-tck/pull/3</a>. The TCK is changed and the JBatch runner project also uses it and runs without test failures. This solves my first 2 goals.</p>



<p>The hardest thing was to connect a JUnit 5 test suite with Payara Server to meet my 3rd goal. For that, I needed to solve the following problems:</p>



<ul><li>create a deployment package to deploy tests to Payara Server</li><li>create a JUnit 5 extension to run the tests in Payara Server and report the results back </li></ul>



<p>I already solved the first problem with an Arquillian extension in the previous step. And it seems there&#8217;s an unofficial JUnit 5 extension to run Arquillian tests. And yes, it worked, I was able to merge all this to a final solution for all of my 3 goals.</p>



<h2 class="wp-block-heading">Running the JUnit 5 TCK with Arquillian</h2>



<p>Luckily, the Arquillian community has been working on <a href="https://github.com/arquillian/arquillian-core/issues/137">support for JUnit 5</a>. Although this effort was stuck for a while waiting for an essential extension point only added in JUnit 5.5, there&#8217;s now an unofficial <a href="https://github.com/zforgo/arquillian-junit5-extension">arquillian-junit5-extension</a> with some fixes in <a href="https://github.com/dmatej/arquillian-junit5-extension">this fork</a>.</p>



<blockquote class="wp-block-quote"><p>UPDATE: Arquillian now provides an official <a href="https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.jboss.arquillian.junit5%22">JUnit 5 extension</a>, which can be used instead. It&#8217;s based on the unofficial extension that I used but is available in Maven Central and contains some additional fixes.</p></blockquote>



<p>So I tried to pull all what I already had together to try if I can get the converted JUnit 5 Batch TCK running against Payara Server:</p>



<ul><li>use the JUnit 5 Batch TCK as a dependency</li><li>add the arquillian-junit5-extension</li><li>add the Arquillian deployment extension I created earlier</li><li>configured Arquillian to run with the Payara connector as I did earlier</li></ul>



<p>So I did it, started Payara Server, configured the necessary JDBC resources, and executed the following:</p>


<pre class="wp-block-code"><span><code class="hljs">mvn verify</code></span></pre>


<p>&#8230; and prayed.</p>



<p>After a few minues:</p>


<pre class="wp-block-code"><span><code class="hljs">Results: 
Tests run: 164, Failures: 0, Errors: 0, Skipped: 3</code></span></pre>


<p>All worked! This includes all TCK tests, including the tests that require other Jakarta EE functionality and which are not run for standalone Batch implementations like JBatch. Those 3 skipped tests are currently being skipped by the TCK and not by my configuration.</p>



<h2 class="wp-block-heading">Summary</h2>



<p>I was able to demonstrate there are multiple ways to improve existing standalone Jakarta EE TCKs or create new ones from the full Jakarta CTS suite in a modern way. </p>



<p>One of them is an already proven way of adding Arquillian into a JUnit 4 or TestNG test suite and expect that all implementations provide an Arquillian container to run the tests with them. As demonstrated, this is pretty easy with a few lines of code, writing a simlple Arquillian extension to define deployments for all tests.</p>



<p>But there&#8217;s also an interesting new way which uses JUnit 5, one of the most modern test frameworks for Java. JUnit 5 provides enough extension points and also allows enabling extensions globally for all tests. This means that the tests don&#8217;t need to include any boiler-plate code required to enable the extensions. Implementers can use Arquillian to run the tests via an existing JUnit 5 Arquillian extension once it&#8217;s officially released, or they can create their own JUnit 5 extension to connect the tests with their implementation. Or they are free to use the existing unofficial JUnit 5 Arquillian extension already and even modify it if needed because they can really use anything they want.</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/possible-ways-to-use-arquillian-in-jakarta-ee-tcks/">Possible ways to use Arquillian in Jakarta EE TCKs</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/possible-ways-to-use-arquillian-in-jakarta-ee-tcks/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">806</post-id>	</item>
		<item>
		<title>Speed Up Services With Reactive API in Java EE 8</title>
		<link>https://ondro.inginea.eu/index.php/speed-up-services-with-reactive-api-in-java-ee-8/</link>
					<comments>https://ondro.inginea.eu/index.php/speed-up-services-with-reactive-api-in-java-ee-8/#respond</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Wed, 27 Jun 2018 01:02:02 +0000</pubDate>
				<category><![CDATA[REST]]></category>
		<category><![CDATA[reactive]]></category>
		<category><![CDATA[microservices]]></category>
		<guid isPermaLink="false">http://itblog.inginea.eu/?p=678</guid>

					<description><![CDATA[<p>Services can often be optimized with asynchronous processing even without changing their behavior towards the outside world. The reason why some services aren&#8217;t efficient is that they need to wait for other services to provide a result to continue further. Let&#8217;s look how to call external REST services without waiting for them and also do [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/speed-up-services-with-reactive-api-in-java-ee-8/">Speed Up Services With Reactive API in Java EE 8</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Services can often be optimized with asynchronous processing even without changing their behavior towards the outside world. The reason why some services aren&#8217;t efficient is that they need to wait for other services to provide a result to continue further. Let&#8217;s look how to call external REST services without waiting for them and also do multiple parallel calls independently and combine their results later with a reactive pipeline in Java EE 8.</p>



<span id="more-678"></span>



<blockquote class="wp-block-quote"><p>This topic and much more will be described in more detail in my upcoming book <a rel="noopener" href="https://www.amazon.com/Java-EE-Microservices-Mert-%C3%87aliskan/dp/1788475143/ref=sr_1_1?ie=UTF8&amp;qid=1524472047&amp;sr=8-1&amp;keywords=Java+EE+8+Microservices" target="_blank">Java EE 8 Microservices</a>, which I co-author with Mert Çaliskan and Pavel Pscheidl</p></blockquote>



<p>If our service calls multiple microservices and waits for each call to finish and return results before doing another call, it&#8217;s a good candidate to refactor using reactive API. In order to make the service more efficient, it could do all the calls to external services&nbsp;in parallel if they don&#8217;t depend on each other. This would decrease the time spent waiting and thus speed up the microservice.</p>



<p>In order to call REST services in parallel, we&#8217;ll use the new reactive client API in JAX-RS. We&#8217;ll combine it with the RxJava library to combine their results when available. This combination will allow us to write clean and efficient code. And with an additional benefit that the current thread can be released for further processing while waiting for results from remote calls.</p>



<p>We&#8217;ll build a pipeline which processes the results as they arrive and finally merges them into a single response. The first part of the pipeline will call each remote service. Instead of waiting for the results, we&#8217;ll specify what to do with each received result and continue with calling other services. Using the rx() method on the JAX-RS client request builder allows us to call a version of the <code>get()</code> method, which immediately returns instead of waiting for the result. In order to process results when they arrive, we can chain method handlers onto a <code>CompletionStage</code> returned from the <code>rx</code> version of the <code>get()&nbsp;</code> method:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-11" data-shcb-language-name="HTML, XML" data-shcb-language-slug="xml"><span><code class="hljs language-xml">CompletionStage<span class="hljs-tag">&lt;<span class="hljs-name">Forecast</span>&gt;</span> stage = temperatureServiceTarget
  .request()
  .rx()
  .get(Temperature.class)
  .thenApply(temperature -&gt; new Forecast(temperature));</code></span><small class="shcb-language" id="shcb-language-11"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">HTML, XML</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">xml</span><span class="shcb-language__paren">)</span></small></pre>


<p id="block-46df34cf-9a60-4ae2-b3f9-bcc3f0c56c9a">The above code will call a temperature service and then register a lambda expression to process the resulting temperature when it arrives. This maps the temperature to a forecast object, which can be accessed with the stage&nbsp; variable later.</p>



<p>However, we want to use another variant of the <code>get()</code>&nbsp; method together with an RxJava Flowable Invoker from the Jersey project to get a <code>Flowable</code>&nbsp; from RxJava instead of a <code>CompletionStage</code>. The <a rel="noreferrer noopener" href="http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html" target="_blank">Flowable</a> interface makes it easier to combine multiple asynchronous results with much simpler code than <code>CompletionStage</code> and also more efficiently.</p>



<p>With the following code, we will call an external service and return a Flowable:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-12" data-shcb-language-name="HTML, XML" data-shcb-language-slug="xml"><span><code class="hljs language-xml">Flowable<span class="hljs-tag">&lt;<span class="hljs-name">Forecast</span>&gt;</span> flowable = temperatureServiceTarget
  .register(RxFlowableInvokerProvider.class)
  .request()
  .rx(RxFlowableInvoker.class)
  .get(Temperature.class)
  .map(temperature -&gt; new Forecast(temperature);</code></span><small class="shcb-language" id="shcb-language-12"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">HTML, XML</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">xml</span><span class="shcb-language__paren">)</span></small></pre>


<p>We register additional <code>RxFlowableInvokerProvider</code>, which allows to request <code>RxFlowableInvoker</code>&nbsp; later. This invoker then gives us the <code>Flowable</code>&nbsp; return type from RxJava. These classes are not in the JAX-RS API and we must add them with the Jersey RxJava2 library:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-13" data-shcb-language-name="HTML, XML" data-shcb-language-slug="xml"><span><code class="hljs language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.glassfish.jersey.ext.rx<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>jersey-rx-client-rxjava2<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.26<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span></code></span><small class="shcb-language" id="shcb-language-13"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">HTML, XML</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">xml</span><span class="shcb-language__paren">)</span></small></pre>


<p>On the first sight it seems we made the code more complicated while doing the same thing. But a <code>Flowable</code> instance allows us to combine multiple calls easily:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-14" data-shcb-language-name="PHP" data-shcb-language-slug="php"><span><code class="hljs language-php">Flowable.concat(flowable1, flowable2)
  .doOnNext(forecast -&gt; {
    forecasts.add(forecast);
  })
  .doOnComplete(() -&gt; {
    asyncResponse.resume(Response.ok(forecasts).build());
  })
  .doOnError(asyncResponse::resume)
  .subscribe();
}</code></span><small class="shcb-language" id="shcb-language-14"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">PHP</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">php</span><span class="shcb-language__paren">)</span></small></pre>


<p>For each forecast received from any flowable, we add it to a list of forecasts. Finally, we send the list of forecasts as a response or send an error response. The final call to <code>subscribe()</code>&nbsp; is necessary to register the listeners, otherwise they would be ignored.</p>



<p>You may have also noticed the <code>asyncResponse</code>&nbsp; variable used to send the final response or signal an error. This is a JAX-RS asynchronous response instance, which is used to complete a REST response at later time, when the data is available, without blocking the initial processing thread. Using the asynchronous response helps us save thread resources while waiting for results from external REST services. In order to turn on asynchronous processing in our REST endpoint, we will inject <a rel="noreferrer noopener" href="https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/container/AsyncResponse.html" target="_blank">javax.ws.rs.container.AsyncResponse</a> as the REST method argument, together with the <a rel="noreferrer noopener" href="https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/container/Suspended.html" target="_blank">@Suspended</a> annotation. We will also change the return type to <code>void</code> because we&#8217;ll be building the response using the <code>AsyncResponse</code> instance:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-15" data-shcb-language-name="CSS" data-shcb-language-slug="css"><span><code class="hljs language-css"><span class="hljs-keyword">@GET</span>
@Produces(MediaType.APPLICATION_JSON)
public void getForecasts(@Suspended AsyncResponse asyncResponse) {
  <span class="hljs-comment">/* ...here come some asynchronous calls to REST services... */</span>
  <span class="hljs-selector-tag">asyncResponse</span><span class="hljs-selector-class">.resume</span>(...)
}</code></span><small class="shcb-language" id="shcb-language-15"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">CSS</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">css</span><span class="shcb-language__paren">)</span></small></pre>


<h2 class="wp-block-heading">Final code example</h2>



<p>The following code will:</p>



<ul><li>turn on asynchronous processing of REST requests in the <code>getForecasts</code> method</li><li>set 5 minute timeout on the asynchronous response</li><li>execute the temperature service twice, for London and Beijing, without waiting for results</li><li>combine the results into a sequence of forecasts</li><li>add every forecast in the sequence into a list</li><li>send the complete list when all results processed</li><li>send an error result in case of an exception</li><li>register the handlers with the <code>subscribe</code> method</li></ul>


<pre class="wp-block-code" aria-describedby="shcb-language-16" data-shcb-language-name="JavaScript" data-shcb-language-slug="javascript"><span><code class="hljs language-javascript">private Flowable&lt;Forecast&gt; getTemperature(<span class="hljs-built_in">String</span> location) {
  <span class="hljs-keyword">return</span> temperatureTarget
    .register(RxFlowableInvokerProvider.class)
    .resolveTemplate(<span class="hljs-string">"city"</span>, location)
    .request()
    .rx(RxFlowableInvoker.class)
    .get(Temperature.class)
    .map(temperature -&gt; <span class="hljs-keyword">new</span> Forecast(location, temperature));
}

@GET
@Produces(MediaType.APPLICATION_JSON)
public <span class="hljs-keyword">void</span> getForecasts(@Suspended AsyncResponse asyncResponse) {
  List&lt;Forecast&gt; forecasts = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
  asyncResponse.setTimeout(<span class="hljs-number">5</span>, TimeUnit.MINUTES);
  Flowable.concat(getTemperature(<span class="hljs-string">"London"</span>), getTemperature(<span class="hljs-string">"Beijing"</span>))
    .doOnNext(forecast -&gt; {
      forecasts.add(forecast);
    })
  .doOnComplete(() -&gt; {
    asyncResponse.resume(Response.ok(forecasts).build());
  })
  .doOnError(asyncResponse::resume)
  .subscribe();
}</code></span><small class="shcb-language" id="shcb-language-16"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">JavaScript</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">javascript</span><span class="shcb-language__paren">)</span></small></pre>


<h2 class="wp-block-heading">Republished at</h2>



<ul><li><a href="https://dzone.com/articles/speed-up-services-with-reactive-api-in-java-ee-8">DZone.com</a></li><li><a href="https://www.javacodegeeks.com/2018/06/speed-services-reactive-api.html">JavaCodeGeeks.com</a></li></ul>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/speed-up-services-with-reactive-api-in-java-ee-8/">Speed Up Services With Reactive API in Java EE 8</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/speed-up-services-with-reactive-api-in-java-ee-8/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<series:name><![CDATA[Java EE 8 Microservices]]></series:name>
<post-id xmlns="com-wordpress:feed-additions:1">678</post-id>	</item>
		<item>
		<title>Configure Payara Server passwords in Docker</title>
		<link>https://ondro.inginea.eu/index.php/configure-passwords-in-payara-server-and-glassfish/</link>
					<comments>https://ondro.inginea.eu/index.php/configure-passwords-in-payara-server-and-glassfish/#comments</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Thu, 23 Nov 2017 11:25:22 +0000</pubDate>
				<category><![CDATA[Payara]]></category>
		<category><![CDATA[passwords]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[docker]]></category>
		<guid isPermaLink="false">http://itblog.inginea.eu/?p=567</guid>

					<description><![CDATA[<p>Answering Stackoverflow questions provides a great feedback for finding out gaps in the official documentation of my favourite opensource tools. One of the questions which I answered here was how to change Payara Server master password in docker container. Obviously, in a standard server installation, this is simple &#8211; just use the&#160;asadmin change-master-password&#160; command, then [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/configure-passwords-in-payara-server-and-glassfish/">Configure Payara Server passwords in Docker</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Answering Stackoverflow questions provides a great feedback for finding out gaps in the official documentation of my favourite opensource tools. One of the questions which I answered here was how to <a href="https://stackoverflow.com/a/47453368/784594">change Payara Server master password in docker container</a>. Obviously, in a standard server installation, this is simple &#8211; just use the&nbsp;<span class="lang:java decode:true crayon-inline ">asadmin change-master-password</span>&nbsp; command, then type the old and new password in to the console and it&#8217;s done. Not in docker though, where the configuration has to be automated by a script. The same applies to all infrastructure-as-a-code solutions like Chef or Puppet. So I had to dig deeper into the documentation and experiment a bit.</p>



<span id="more-567"></span>



<h2 class="wp-block-heading">Specifying passwords from file</h2>



<p>The key thing in working with passwords in scripts is to provide them in a file. Each asadmin command accepts argument <span class="lang:java decode:true crayon-inline"><code>--passwordfile</code></span>&nbsp; to instruct it to read all the necessary passwords from it to avoid asking for passwords interactively. But it&#8217;s a bit tricky to find out how to define passwords in this password file, because it&#8217;s used for multiple types of passwords. Oracle documentation for GlassFish v3 which also applies to GlassFish v4 and v5 and Payara v4 and v5 <a href="https://docs.oracle.com/cd/E18930_01/html/821-2435/ghgrp.html#ghytn">documents 4 types of passwords</a>. Each type of password can be specified in the password file with a variable that starts with the <span class="lang:java decode:true crayon-inline">AS_ADMIN_</span>&nbsp; prefix.</p>



<ul>
<li>admin password with prefix <span class="lang:java decode:true crayon-inline"><code>AS_ADMIN_PASSWORD</code></span>, default is empty password</li>



<li>master password with prefix <span class="lang:java decode:true crayon-inline"><code>AS_ADMIN_MASTERPASSWORD</code></span> , default is &#8220;changeit&#8221;</li>



<li>user password with prefix <span class="lang:java decode:true crayon-inline"><code>AS_ADMIN_USERPASSWORD</code></span></li>



<li>alias password with prefix <span class="lang:java decode:true crayon-inline"><code>AS_ADMIN_ALIASPASSWORD</code></span></li>
</ul>



<p>So for example, if we need to run a command with admin password &#8220;mypassword&#8221;, the following line has to be in the password file:</p>


<pre class="wp-block-code lang:java decode:true"><span><code class="hljs">AS_ADMIN_PASSWORD=mypassword</code></span></pre>


<p>And then we can use the password with the&nbsp;<span class="lang:java decode:true crayon-inline "><code>--passwordfile</code></span> argument, like this:</p>


<pre class="wp-block-code lang:java decode:true" aria-describedby="shcb-language-17" data-shcb-language-name="PHP" data-shcb-language-slug="php"><span><code class="hljs language-php">asadmin <span class="hljs-keyword">list</span>-applications --passwordfile=mypasswordfile</code></span><small class="shcb-language" id="shcb-language-17"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">PHP</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">php</span><span class="shcb-language__paren">)</span></small></pre>


<p>The above command won&#8217;t wait for typing the password but will immediately list all applications on the server. If the password is incorrect, the command would fail.</p>



<div class="wp-block-group omnifish-advert has-white-color has-text-color has-background is-layout-flow" style="background-color:#0b8f9b"><div class="wp-block-group__inner-container">
<div class="wp-block-media-text alignwide has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-center has-white-color has-text-color" style="grid-template-columns:auto 15%"><div class="wp-block-media-text__content">
<p class="has-medium-font-size"><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank"><strong>Need help with GlassFish, Jakarta EE, Java in the cloud?</strong></a></p>



<p><a rel="noreferrer noopener" href="https://omnifish.ee" data-type="URL" data-id="https://omnifish.ee" target="_blank">Follow me at <strong>OmniFish</strong>! </a></p>
</div><figure class="wp-block-media-text__media"><a href="https://omnifish.ee"><img decoding="async" loading="lazy" width="300" height="178" src="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&#038;ssl=1" alt="" class="wp-image-1034 size-medium" srcset="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?resize=300%2C178&amp;ssl=1 300w, https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2022/07/omnifish-logo-transparent-400px.png?w=400&amp;ssl=1 400w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></figure></div>
</div></div>



<h2 class="wp-block-heading">Changing passwords non-interactively from script</h2>



<p>So far, all was documented at least in the old GlassFish v3 documentation. What&#8217;s missing in the documentation though is how to specify a new password from file if we want to change it from a script. When we execute a command to change any password (e.g. admin password or master password) without a password file, the command would ask for 2 passwords &#8211; the old one and the new one. Therefore we need to specify 2 passwords in a file.</p>



<p>The solution is to add another variable for a new password into the same password file. Variables for new passwords are prefixed with <span class="lang:java decode:true crayon-inline">AS_ADMIN_NEW</span>&nbsp; prefix. Therefore to change the master password, we need the following 2 lines in our password file:</p>


<pre class="wp-block-code lang:java decode:true"><span><code class="hljs">AS_ADMIN_MASTERPASSWORD=oldmasterpassword
AS_ADMIN_NEWMASTERPASSWORD=newmasterpassword</code></span></pre>


<p>And then we can use the 2 passwords with the&nbsp;<span class="lang:java decode:true crayon-inline ">&#8211;passwordfile</span> argument, like this:</p>


<pre class="wp-block-code lang:java decode:true"><span><code class="hljs">asadmin change-master-password --passwordfile=mypasswordfile</code></span></pre>


<p>The above command won&#8217;t wait for typing or retyping any password but will immediately change the master password on the server to <span class="lang:java decode:true crayon-inline ">newmasterpassword</span>&nbsp;. If the old password is incorrect, the command would fail.</p>



<h2 class="wp-block-heading">Changing passwords in docker image</h2>



<p>In Docker, the preferred way is to configure the server in the image so that when a container is executed, the configuration is applied automatically. Avoid configuring containers because it&#8217;s not easy to run asadmin commands in a container and changing some passwords, such as master password, requires server restart.</p>



<p>The default <a href="https://hub.docker.com/r/payara/server-full/~/dockerfile/">Payara Server Docker image</a> already contains asadmin commands which change the admin password. You can copy the lines that create&nbsp;<span class="lang:java decode:true crayon-inline ">/opt/tmpfile</span>&nbsp; and use it with the&nbsp;<span class="lang:java decode:true crayon-inline ">change-admin-password</span>&nbsp; command to change the admin password.</p>



<p>The same can be done to change the master password. Below is an example custom Dockerfile to change the master password to <span class="lang:java decode:true crayon-inline ">newpassword</span>&nbsp;:</p>


<pre class="wp-block-code" aria-describedby="shcb-language-19" data-shcb-language-name="Dockerfile" data-shcb-language-slug="dockerfile"><span><code class="hljs language-dockerfile"><span class="hljs-keyword">FROM</span> payara/server-full
<span class="hljs-comment"># specify a new master password "newpassword" instead of the default password "changeit"</span>
<span class="hljs-keyword">RUN</span><span class="bash"> <span class="hljs-built_in">echo</span> <span class="hljs-string">'AS_ADMIN_MASTERPASSWORD=changeit\nAS_ADMIN_NEWMASTERPASSWORD=newpassword'</span> &gt;&gt; /opt/masterpwdfile</span>

<span class="hljs-comment"># execute asadmin command to apply the new master password</span>
<span class="hljs-keyword">RUN</span><span class="bash"> <span class="hljs-variable">${PAYARA_PATH}</span>/bin/asadmin change-master-password --passwordfile=/opt/masterpwdfile</span></code></span><small class="shcb-language" id="shcb-language-19"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">Dockerfile</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">dockerfile</span><span class="shcb-language__paren">)</span></small></pre>


<p>With the above Dockerfile in your current directory, you can build your custom docker image with:</p>


<pre class="wp-block-code lang:java decode:true"><span><code class="hljs">docker build -t my-payara/server-full .</code></span></pre>


<p>And then run <span class="lang:java decode:true crayon-inline ">my-payara/server-full</span>&nbsp; instead of payara/server-full.</p>



<p>You can verify that the master password is changed in the docker container when you run it with:</p>


<pre class="wp-block-code lang:java decode:true" aria-describedby="shcb-language-20" data-shcb-language-name="PHP" data-shcb-language-slug="php"><span><code class="hljs language-php">docker run -t -i --entrypoint keytool payara/server-full:masterpwd -<span class="hljs-keyword">list</span> -keystore /opt/payara41/glassfish/domains/domain1/config/keystore.jks</code></span><small class="shcb-language" id="shcb-language-20"><span class="shcb-language__label">Code language:</span> <span class="shcb-language__name">PHP</span> <span class="shcb-language__paren">(</span><span class="shcb-language__slug">php</span><span class="shcb-language__paren">)</span></small></pre>


<p>If you type the new master password, you should see the contents of the key store with the list of certifictes.</p>



<p><strong>NOTE: </strong>After you change the master password, the Docker image will still run Payara with the old master password, which is not the correct password and Payara will not start. After you change the master password, you also need to update the value of <code>AS_ADMIN_MASTERPASSWORD</code> in the file <code>${PASSWORD_FILE}</code> (<code>/opt/payara/passwordFile</code>) to the value of the new master password, so that Payara is started with the new password.</p>



<hr class="wp-block-separator has-css-opacity"/>



<p>Republished at: <a href="https://www.javacodegeeks.com/2017/11/configure-passwords-payara-server-glassfish.html" data-type="URL" data-id="https://www.javacodegeeks.com/2017/11/configure-passwords-payara-server-glassfish.html" target="_blank" rel="noreferrer noopener">JavaCodeGeeks.com</a></p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/configure-passwords-in-payara-server-and-glassfish/">Configure Payara Server passwords in Docker</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/configure-passwords-in-payara-server-and-glassfish/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">567</post-id>	</item>
		<item>
		<title>Using HotswapAgent to speed up development</title>
		<link>https://ondro.inginea.eu/index.php/using-hotswapagent-to-speed-up-development/</link>
					<comments>https://ondro.inginea.eu/index.php/using-hotswapagent-to-speed-up-development/#respond</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Fri, 20 Oct 2017 12:07:09 +0000</pubDate>
				<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Web development]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Payara]]></category>
		<category><![CDATA[JVM]]></category>
		<category><![CDATA[hotswap]]></category>
		<category><![CDATA[development]]></category>
		<guid isPermaLink="false">http://itblog.inginea.eu/?p=533</guid>

					<description><![CDATA[<p>As a Java EE developer, I sometimes envy how fast it&#8217;s possible to see the result of a code change in a running application with interpreted languages like PHP or JavaScript. With Java, it&#8217;s always necessary to rebuild the source code in a bytecode, which can be then safely updated only by restarting the whole [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/using-hotswapagent-to-speed-up-development/">Using HotswapAgent to speed up development</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>As a Java EE developer, I sometimes envy how fast it&#8217;s possible to see the result of a code change in a running application with interpreted languages like PHP or JavaScript. With Java, it&#8217;s always necessary to rebuild the source code in a bytecode, which can be then safely updated only by restarting the whole application. And all developers know that restoring the desired state of the application after a fresh restart takes time and is tedious. A while ago I&#8217;ve come across an opensource tool called <a href="http://hotswapagent.org/">HotswapAgent</a> that speeds up code reloading.<span id="more-533"></span></p>
<p>Many developers know that <a href="https://zeroturnaround.com/software/jrebel/">JRebel</a> can help a lot with updating the code on the fly. There&#8217;s been a lot of effort put into it to support all sorts of code and resource changes and refresh them with virtually any Java framework used by the application. But the downside is that it&#8217;s pretty expensive for a casual developer, doing just some hacking on his/her own or working on a non-commercial project. I have some experience with JRebel and I liked it a lot, but I was using it on a commercial project where I didn&#8217;t pay for the license. I tried HotswapAgent and it has worked very well as a free alternative of JRebel for me for my personal Java EE projects. I&#8217;m going to write up how I got it running in my IDE and my Java EE server of choice &#8211; <a href="https://www.payara.fish">Payara Server</a>.</p>
<h2>Getting started with HotswapAgent</h2>
<p>Hotswap Agent itself is just a java agent, which has to be attached to the application. It essentially scans the classpath to detect the presence of known frameworks and tries to refresh the frameworks after a code or resource change is detected. It&#8217;s also possible to write custom plugins for any project or even specifically for your application. However, getting the most of Hotswap Agent requires installing an alternative DCEVM engine into your JRE installation, which does much better job in reloading code changes than the standard VM engine in the HotSpot VM. The alternative VM engine is basically a patched version of the standard engine, which improves code hot swap via the debugging interface, without impacting other functions of the JVM.</p>
<p>So to summarize, we are going to do this to work with HotSwap from our IDE of choice:</p>
<ol>
<li>Install the <a href="https://github.com/dcevm/dcevm/releases">DCEVM</a> engine into a Java installation (JRE or JDK)</li>
<li>Configure the IDE to start the application with the <a href="https://github.com/HotswapProjects/HotswapAgent/releases">HotswapAgent JAR</a> as java agent and using the DCEVM engine instead of the standard JVM engine</li>
<li>Configure the IDE to refresh plain text resources like XML, property files, in the running application (this has to be done by the IDE because it&#8217;s not supported by Java debugger)</li>
<li>Start the application in debug mode and connect to it via the debugger interface from withing IDE</li>
<li>Continue coding and see the changes in your app immediately <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>
</ol>
<h2>Installing the DCEVM engine</h2>
<p>First, download the <a href="https://github.com/dcevm/dcevm/releases">DCEVM installer</a> for your Java installation. The project is pretty quick to release new versions for new Java updates. At the time of writing this blog post, there was a build for Java 8 update 144 available, released 12 days ago, just a month after the actual Java 8 update 144 had been released. There aren&#8217;t releases of DCEVM for every Java update, but I always just used the latest version with my Java installation and never had any issues.</p>
<p>The installer is a plain executable JAR file, which you can start with <span class="lang:java decode:true crayon-inline">java -jar DCEVM-installer.jar</span> . In Linux, I usually start this with admin privileges (using sudo), because it will add/modify files in the Java installation, which is usually read-only for standard users if installed system-wide:  <span class="lang:java decode:true crayon-inline">sudo java -jar DCEVM-installer.jar</span></p>
<p>The installer will open a window, which lists all the detected Java installations on the system.</p>
<p><div id="attachment_536" style="width: 940px" class="wp-caption alignnone"><a href="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2017/09/Screenshot-from-DCEVM.png?ssl=1"><img aria-describedby="caption-attachment-536" data-attachment-id="536" data-permalink="https://ondro.inginea.eu/index.php/using-hotswapagent-to-speed-up-development/screenshot-from-dcevm/" data-orig-file="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2017/09/Screenshot-from-DCEVM.png?fit=930%2C650&amp;ssl=1" data-orig-size="930,650" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Screenshot from DCEVM" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2017/09/Screenshot-from-DCEVM.png?fit=300%2C210&amp;ssl=1" data-large-file="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2017/09/Screenshot-from-DCEVM.png?fit=640%2C447&amp;ssl=1" decoding="async" loading="lazy" class="wp-image-536 size-full" src="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2017/09/Screenshot-from-DCEVM.png?resize=640%2C447&#038;ssl=1" alt="Screenshot from DCEVM" width="640" height="447" srcset="https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2017/09/Screenshot-from-DCEVM.png?w=930&amp;ssl=1 930w, https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2017/09/Screenshot-from-DCEVM.png?resize=300%2C210&amp;ssl=1 300w, https://i0.wp.com/ondro.inginea.eu/wp-content/uploads/2017/09/Screenshot-from-DCEVM.png?resize=700%2C489&amp;ssl=1 700w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a><p id="caption-attachment-536" class="wp-caption-text">The DCEVM installer windows showing all detected Java installations</p></div></p>
<p>set configs.config.server-config.java-config.java-home=&#8221;$DCEVM_JAVA_HOME&#8221;</p>
<p>It&#8217;s possible to install the DCEVM engine in 2 ways:</p>
<ul>
<li>replace the current VM engine with DCEVM</li>
<li>as an alternative engine into a Java installation, which won&#8217;t affect the standard bahavior of the JVM</li>
</ul>
<p>If you install DCEVM as an alternative engine, you can enable it by passing <span class="lang:java decode:true crayon-inline">-XXaltjvm=dcevm</span>  command line option to the <span class="lang:java decode:true crayon-inline ">java</span>  command along with the other options, like:</p>
<pre class="toolbar:2 nums:false nums-toggle:false lang:sh decode:true">java -XXaltjvm=dcevm -Xmx500m -jar application.jar</pre>
<p>I was usually successful with installing DCEVM as an alternative engine, which is less intrusive and very transparent. The DCEVM engine can then be enabled by a command line option only if you want it and you can have the same Java installation for both running third-party Java programs and development. The second option of replacing the current VM engine with DCVEM is convenient if you can&#8217;t pass additional command line arguments to the java program. In that case, I recommend using a separate Java installation to replace the default engine by DCEVM and use to it only during development.</p>
<p>The second option of replacing the current VM engine with DCVEM is convenient if you can&#8217;t pass additional command line arguments to the java program. In that case, I recommend using a separate Java installation to replace the default engine by DCEVM and use to it only during development.</p>
<h2>Configure the IDE to use HotswapAgent</h2>
<p>In order to enable the HotswapAgent, it has to be passed to the java program as an agent, via the <span class="lang:java decode:true crayon-inline">-javaagent</span> command line parameter. Then you have to pass additional parameters to enable the debug mode. Before configuring the IDE, I&#8217;ll explain how to start an application from command line, which is essentially what you need to configure in any IDE.</p>
<p>First, download the <a href="https://github.com/HotswapProjects/HotswapAgent/releases">HotswapAgent JAR</a> to some shared location. The JAR file will remain there and will be referenced by the  <span class="lang:java decode:true crayon-inline">-javaagent</span> command line parameter. Additionally, we&#8217;ll enable remote debugging on port 9009, with suspend=n so that the application doesn&#8217;t wait for the debugger to be attached. We can then attach a debugger at any time we want to update the application with code changes. This is an example of the command line to start an application with the HotswapAgent JAR located in <span class="lang:java decode:true crayon-inline ">/development/hotswap-agent.jar</span> :</p>
<pre class="toolbar:2 nums:false nums-toggle:false lang:sh decode:true">java -XXaltjvm=dcevm -javaagent:/development/hotswap-agent.jar \
  -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9009 \
  -jar application.jar</pre>
<p>If you haven&#8217;t installed DCEVM as an alternative JVM but replaced the default JVM engine, you should omit the <span class="lang:java decode:true crayon-inline">-XXaltjvm=dcevm</span> argument.</p>
<p>To configure HotswapAgent in your IDE, you have to do the following steps:</p>
<ol>
<li>Make sure that the IDE can apply your code changes via the debugger. In most IDEs this means that
<ul>
<li>automatic compile on saving is turned on</li>
<li>compiled classes are automatically replaced in the running application if it&#8217;s attached to the IDE via the debug interface</li>
</ul>
</li>
<li>Make sure that the IDE uses the Java installation with the DCEVM engine
<ol>
<li>if DCEVM was installed as an alternative engine, the IDE has to pass the <span class="lang:java decode:true crayon-inline">-XXaltjvm=dcevm</span> argument when starting the application in debug mode</li>
</ol>
</li>
<li>Turn off any restart/redeployment of the application on code change (this applies mostly when using application servers via an IDE server plugin)</li>
</ol>
<p>Detailed instructions how to do it in major Java IDEs can be found on the <a href="https://github.com/HotswapProjects/HotswapAgent/wiki#setup-in-ide">HotswapAgent Wiki</a>.</p>
<h2>Using HotswapAgent with Payara Server</h2>
<p>Some frameworks or application servers require additional configuration. This is mostly because the hotswap-agent.jar has to be added to the classpath and the agent isn&#8217;t able to modify the classloader to add the required classes automatically, or the framework or server spawns additional JVM process and has to be configured to use a JVM with DCEVM.</p>
<p>To use HotswapAgent with DCEVM while developing applications with Payara Server, it requires doing the following changes:</p>
<ol>
<li>copy the <span class="lang:java decode:true crayon-inline">hotswap-agent.jar</span>  into the <span class="lang:java decode:true crayon-inline">lib/ext</span> folder in the Payara Server&#8217;s domain directory. If you&#8217;re using the default <span class="lang:java decode:true crayon-inline ">domain1</span> domain, it would be <span class="lang:java decode:true crayon-inline">glassfish/domains/domain1/lib/ext/hotswap-agent.jar</span> (this is required to add HotswapAgent JAR to the server&#8217;s classpath, at least until HotswapAgent can do it automatically in Payara Server)</li>
<li>point Payara Server to the Java installation with the DCEVM engine, if it&#8217;s not the default system installation
<ul>
<li>set the Java Home property in JVM general settings to point to the root of your alternative Java installation (with asadmin command you would do this by calling <span class="lang:sh decode:true crayon-inline">asadmin set configs.config.server-config.java-config.java-home=&#8221;$ALTERNATIVE_JAVA_HOME&#8221;</span> )</li>
</ul>
</li>
<li>modify the JVM options:
<ul>
<li>remove any <span class="lang:java decode:true crayon-inline ">-client</span>  or <span class="lang:java decode:true crayon-inline">-server</span>  JVM options (they would prevent using DCEVM as an alternative engine even if the <span class="lang:java decode:true crayon-inline">-XXaltjvm</span>  option is present)</li>
<li>add the <span class="lang:java decode:true crayon-inline ">-XXaltjvm</span>  option</li>
<li>add the <span class="lang:java decode:true crayon-inline">-javaagent</span> option with the path to the hotswap-agent.jar, e.g.<span class="toolbar:2 nums:false nums-toggle:false lang:sh decode:true crayon-inline">-javaagent:/development/hotswap-agent.jar</span>. It can reference the same JAR file which is in the  <span class="lang:java decode:true crayon-inline">lib/ext</span>  folder, even using a relative reference to the domain folder, like this: <span class="lang:java decode:true crayon-inline">-javaagent:${com.sun.aas.instanceRoot}/lib/ext/hotswap-agent.jar</span></li>
</ul>
</li>
</ol>
<p>If starting Payara Server from IDE, you may have to apply the step 2. and 3. in the configuration of your IDE, because the Payara Server plugin in most IDEs bypasses the standard Payara Server configuration and starts Payara Server with the Java runtime and command line parameters specified in the IDE. Mind that in that case, you have to use the full path to the <span class="lang:java decode:true crayon-inline ">hotswap-agent.jar</span>  and avoid using the <span class="lang:java decode:true crayon-inline">${com.sun.aas.instanceRoot}</span>  variable.</p>
<p>In the IDE, you should also disable automatic redeployment of the application on code change. Most IDE plugins do that by default because under normal circumstances, it&#8217;s the only reliable way to change update the application to reflect code changes. Since with HotSwapAgent and DCEVM the usual class reloading is enough, automatic redeploy isn&#8217;t necessary and should be disabled.</p>
<h2>Using HotswapAgent with Payara Micro</h2>
<p>Payara Micro is an application runtime that, unlike application servers, is packaged as a single executable JAR file and can be started as such. It deploys applications passed as command line parameters, within the same JVM process. Therefore it&#8217;s very easy to start it with the HotswapAgent in the same way as any other executable JAR:</p>
<pre class="toolbar:2 nums:false nums-toggle:false lang:sh decode:true">java -XXaltjvm=dcevm -javaagent:/development/hotswap-agent.jar \
  -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9009 \
  -jar payara-micro.jar --deploy application-war</pre>
<p>After it&#8217;s started like this, it listens on port 9009 for debugger requests and any IDE can attach its debugger to it.</p>
<p>The web application is deployed from an exploded directory called <span class="lang:java decode:true crayon-inline ">application-war</span>  (not to be confused with a war file package) so that changes in resources like XML or JSF pages are also picked up automatically. Most IDEs support building a web application as an exploded directory. Maven also stages the application in a directory in the <span class="lang:java decode:true crayon-inline ">target</span>  folder before creating the WAR file and you can deploy your application from that directory using Payara Micro.</p>
<h2>Summary: Using HotswapAgent in Netbeans with Payara Server</h2>
<p>I&#8217;ll quickly summarize the steps required to get HotswapAgent running with Payara Server from the Netbeans IDE.</p>
<h3>Install DCEVM</h3>
<ul>
<li>Use the <a href="https://github.com/dcevm/dcevm/releases">DCEVM installer</a> to install DCEVM as an alternative VM into a Java installation (you may need to run the installer as administrator)</li>
</ul>
<h3>Configure Payara Server</h3>
<ul>
<li>Download the <a href="https://github.com/HotswapProjects/HotswapAgent/releases">HotswapAgent JAR</a> into the <span class="lang:java decode:true crayon-inline">lib/ext</span> folder in the Payara Server&#8217;s domain directory as <span class="lang:java decode:true crayon-inline">lib/ext/hotswap-agent.jar</span></li>
<li>modify the JVM options:
<ul>
<li>remove any <span class="lang:java decode:true crayon-inline">-client</span>  or <span class="lang:java decode:true crayon-inline">-server</span>  JVM options</li>
<li>add the <span class="lang:java decode:true crayon-inline">-XXaltjvm</span>  option</li>
<li>add the <span class="lang:java decode:true crayon-inline">-javaagent:${com.sun.aas.instanceRoot}/lib/ext/hotswap-agent.jar</span> option</li>
</ul>
</li>
</ul>
<h3>Configure Netbeans</h3>
<ul>
<li>In Netbeans, open the configuration of the Payara Server service
<ul>
<li>ensure that the Java installation with the DCEVM is selected as the Java Platform</li>
<li>there&#8217;s no way to configure JVM options &#8211; the plugin reads the standard Payara Server configuration which we modified earlier</li>
</ul>
</li>
<li>Open the project properties
<ul>
<li>in <strong>Build -&gt; Compile</strong>, ensure that the <strong>Compile On Save</strong> option is enabled</li>
<li>in <strong>Run</strong>, ensure that the <strong>Deploy on Save</strong> option is disabled</li>
</ul>
</li>
<li>In Netbeans Options (<strong>Tools -&gt; Options</strong>), in <strong>Java -&gt; Java Debugger</strong>, ensure that <strong>Apply code changes after save</strong> is enabled
<ul>
<li>you can also force applying code changes manually with the <strong>Apply Code Changes</strong> button in the debug toolbar while debugging</li>
</ul>
</li>
</ul>
<p>Now, you can debug the application in a standard way from within Netbeans. The IDE will automatically compile all classes, update them in the server. It will also copy all changed resources into an exploded directory which it used to deploy the application so that these resources are refreshed too, because Payara Server monitors them for changes.</p>
<h2>Summary: Using HotswapAgent in Netbeans with Payara Micro</h2>
<p>The following steps will get you to get HotswapAgent running with Payara Micro and the Netbeans IDE:</p>
<ul>
<li>install the <a href="https://github.com/dcevm/dcevm/releases">DCEVM</a> as an alternative VM (the same step as for Payara Server)</li>
<li>In Netbeans, open the project properties
<ul>
<li style="list-style-type: none;">
<ul>
<li>in <strong>Build -&gt; Compile</strong>, ensure that the <strong>Compile On Save</strong> option is enabled</li>
</ul>
</li>
</ul>
</li>
<li>In Netbeans Options (<strong>Tools -&gt; Options</strong>), in <strong>Java -&gt; Java Debugger</strong>, ensure that <strong>Apply code changes after save</strong> is enabled
<ul>
<li>you can also force applying code changes manually with the <strong>Apply Code Changes</strong> button in the debug toolbar while debugging</li>
</ul>
</li>
<li>Find out where Netbeans outputs the exploded directory of your application (before it packages it as a WAR file)
<ul>
<li>for maven projects, it&#8217;s in the <span class="lang:java decode:true crayon-inline">target</span>  folder and has the same name as the final WAR file, without the WAR extension</li>
</ul>
</li>
<li>Download the <a href="https://github.com/HotswapProjects/HotswapAgent/releases">HotswapAgent JAR</a> into the same folder that contains your exploded application</li>
<li>Run the application from the exploded directory, with the following command line (assuming that the exploded application directory is called <span class="lang:java decode:true crayon-inline ">application-war</span>  and that payara-micro.jar is in the same folder):
<ul>
<li>
<pre class="toolbar:2 nums:false nums-toggle:false lang:sh decode:true">java -XXaltjvm=dcevm -javaagent:hotswap-agent.jar \
  -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9009 \
  -jar payara-micro.jar --deploy application-war</pre>
</li>
</ul>
</li>
<li>Attach Netbeans debugger to the application &#8211; menu Debug -&gt; Attach Debugger, use the port 9009 as the debug port</li>
</ul>
<blockquote><p>Republished at:</p>
<ul>
<li><a href="https://dzone.com/articles/using-hotswapagent-to-speed-up-development">DZone.com</a></li>
</ul>
</blockquote>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/using-hotswapagent-to-speed-up-development/">Using HotswapAgent to speed up development</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/using-hotswapagent-to-speed-up-development/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">533</post-id>	</item>
		<item>
		<title>Oracle announced to open JavaEE &#8211; what to expect in the future?</title>
		<link>https://ondro.inginea.eu/index.php/oracle-to-open-javaee-what-to-expect/</link>
					<comments>https://ondro.inginea.eu/index.php/oracle-to-open-javaee-what-to-expect/#respond</comments>
		
		<dc:creator><![CDATA[Ondro Mihályi]]></dc:creator>
		<pubDate>Sat, 26 Aug 2017 10:41:03 +0000</pubDate>
				<category><![CDATA[Opinions]]></category>
		<category><![CDATA[javaee]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[JCP]]></category>
		<category><![CDATA[microprofile]]></category>
		<category><![CDATA[EclipseFoundation]]></category>
		<guid isPermaLink="false">http://itblog.inginea.eu/?p=513</guid>

					<description><![CDATA[<p>Last week, Oracle announced their intentions to open Java EE and transfer it to an open source foundation to continue its development in a more open way. I&#8217;ve been involved in some email discussions (here and here) and in a conference call organized by Oracle and I want to summarize what I know and expect in [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/oracle-to-open-javaee-what-to-expect/">Oracle announced to open JavaEE &#8211; what to expect in the future?</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Last week, Oracle announced their <a href="https://blogs.oracle.com/theaquarium/opening-up-java-ee">intentions to open Java EE</a> and transfer it to an open source foundation to continue its development in a more open way. I&#8217;ve been involved in some email discussions (<a href="https://groups.google.com/d/msg/javaee-guardians/xnsSHeIUlj0/rZ6ArAnDDAAJ">here</a> and <a href="https://groups.google.com/d/msg/javaee-guardians/dM1B5CxDbHE/jPEBw-FrDQAJ">here</a>) and in a conference call organized by Oracle and I want to summarize what I know and expect in the future. I&#8217;m also a MicroProfile project member, so I&#8217;ll comment on its relation and future benefits to Java EE.<span id="more-513"></span></p>
<p>Opening the process of Java EE development and moving it under an open source foundation is certainly a good news. I&#8217;m hopeful that this will finally address many concerns that the community and vendors have had with the current process in the past years, frequently having called for improvements. I appreciate that the process within the JCP has been very open compared to the development of other similar standards or frameworks and that the JCP is evolving in a good and promising direction. But the process is still driven mostly by Oracle and involves many administrative and legal obstacles to community contributions. The collaboration within the Java EE community and most vendors is maturing much faster, in a more and more open and agile way, and the JCP processes and Oracle&#8217;s leadership of Java EE is still too far behind, only catching up with this trend. I credit Oracle my respect that they&#8217;ve realized and admitted this and they decided to transfer the platform into an open foundation, which would be more ready to support the way the Java EE community wants to progress.</p>
<p>It&#8217;s also very promising that Oracle is very open to discussion about the future direction of the Java EE platform, inviting respected partners and members of the community to join a call to discuss Oracle&#8217;s intentions and answer questions. On this call, some concerns were raised, especially about the continuity of the platform after it&#8217;s transferred to an independent foundation. It&#8217;s still uncertain whether the platform can retain its current name Java EE due to trademark licenses and whether the API can evolve continually without breaking changes, again due to license issues. But Oracle seems to be very open and cooperative to resolve these concerns and my hope is that the Java EE platform will be transferred without significant harm. Another thing to keep in mind is that Oracle admitted that their leadership in Java EE development will decrease a lot, becoming just a regular contributor like many others. I can certainly understand that because Oracle&#8217;s been investing heavily in leading most of the Java EE specifications and the current process hasn&#8217;t allowed delegating most of that work because of legal issues. Moving to a foundation will distribute the responsibility for the platform equally among all that benefit from it. This means that with freedom will also come responsibility and the community and vendors will need to invest a lot more into Java EE development than they&#8217;ve used to. But I wouldn&#8217;t be afraid, because the community is already doing this at different levels, most notably within the Eclipse MicroProfile project. For some open source projects like <a href="https://www.payara.fish/">Payara</a>, which shares a lot of code with the <a href="https://javaee.github.io/glassfish/">GlassFish</a> reference implementation, or <a href="https://deltaspike.apache.org/">DeltaSpike</a>, which provides lots of useful extensions to Java EE, it would be even a lot easier to contribute than now.</p>
<p>I can say that the community and vendors are looking forward to more open collaboration with fewer restrictions. The Eclipse Microprofile project, supported by many Java EE community members and Java EE vendors, already proves that the community is prepared to embrace the platform within an open foundation. The MicroProfile project started as an open initiative to move enterprise Java forward, with focus on delivering the functionality in a very open way and leaving any legal matters as an afterthought, which was welcomed by the community. The Eclipse Foundation then did their best to provide a solid legal and collaboration foundation. This is again a proof that a development platform like Java EE can be safely transferred and continue to thrive under an opensource foundation. MicroProfile is based on Java EE foundations and initiated from discussions within the Java EE community, so both have a lot in common. In my view, MicroProfile can be used as an example of how an API platform can be adopted by an open source foundation, namely the Eclipse Foundation. Java EE can benefit from MicroProfile even more, with MicroProfile providing more agile platform for experimenting with ideas that can be adopted by Java EE when matured. In fact, this is not only a promise but it&#8217;s already happening, as the Eclipse Foundation <a href="https://twitter.com/EclipseFdn/status/898526288331264000">submitted a MicroProfile JSR</a> to the JCP with the aim to become a part of a <a href="https://adtmag.com/articles/2017/08/23/eclipse-microprofile.aspx">future Java EE version</a>.</p>
<p>Compared to some rather unpopular things that Oracle did in the past, like <a href="http://itblog.inginea.eu/index.php/so-oracle-killed-java-net/">shutting down the java.net community portal</a>, it seems that they are doing the right thing now. I believe that the community will hugely benefit from Oracle&#8217;s recent plans and that Java EE will thrive under an open source foundation in harmony with the existing Eclipse MicroProfile project.</p>
<p>UPDATE:</p>
<p>Oracle&#8217;s announced that they have chosen <a href="https://blogs.oracle.com/theaquarium/opening-up-ee-update">the Eclipse Foundation to transfer Java EE</a> to. This is a very natural choice for Java EE and is very welcome by the Java EE and MicroProfile communities.</p>
<blockquote><p>Republished at:</p>
<ul>
<li><a href="https://dzone.com/articles/open-java-ee-what-to-expect">DZone.com</a></li>
</ul>
</blockquote>
<p>The post <a rel="nofollow" href="https://ondro.inginea.eu/index.php/oracle-to-open-javaee-what-to-expect/">Oracle announced to open JavaEE &#8211; what to expect in the future?</a> appeared first on <a rel="nofollow" href="https://ondro.inginea.eu">.Lost in Coding</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ondro.inginea.eu/index.php/oracle-to-open-javaee-what-to-expect/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">513</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/

Page Caching using disk: enhanced (Requested URI is rejected) 

Served from: ondro.inginea.eu @ 2024-11-10 10:50:30 by W3 Total Cache
-->