<?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:media="http://search.yahoo.com/mrss/" >

<channel>
	<title>IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog</title>
	<atom:link href="https://blog.jetbrains.com/idea/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.jetbrains.com</link>
	<description>Developer Tools for Professionals and Teams</description>
	<lastBuildDate>Tue, 05 May 2026 12:33:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://blog.jetbrains.com/wp-content/uploads/2024/01/cropped-mstile-310x310-1-32x32.png</url>
	<title>IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog</title>
	<link>https://blog.jetbrains.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Java Annotated Monthly – May 2026</title>
		<link>https://blog.jetbrains.com/idea/2026/05/java-annotated-monthly-may-2026/</link>
		
		<dc:creator><![CDATA[Irina Mariasova]]></dc:creator>
		<pubDate>Tue, 05 May 2026 12:33:33 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/05/IJ-social-BlogFeatured-1280x720-1.png</featuredImage>		<category><![CDATA[ai]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[kotlin]]></category>
		<category><![CDATA[news]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=705190</guid>

					<description><![CDATA[April flew by. The pace of tech development didn’t slow, and the flow of news and knowledge didn’t either. This month, Emily Bache joins us to share some sharp finds about AI agents and test-driven development. Java stays busy with fresh updates and practical tips, and Kotlin keeps pushing forward right next to it. The [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>April flew by. The pace of tech development didn’t slow, and the flow of news and knowledge didn’t either.</p>



<p>This month, <a href="http://bacheconsulting.com/" target="_blank" rel="noopener">Emily Bache</a> joins us to share some sharp finds about AI agents and test-driven development. Java stays busy with fresh updates and practical tips, and Kotlin keeps pushing forward right next to it. The AI section is, as usual, packed with things worth your attention.</p>



<p>You’ll also find upcoming events to plan for and a few ideas to challenge your thinking.</p>



<h2 class="wp-block-heading">Featured Content </h2>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/05/image-2.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Emily Bache</h4>
                                                <p><span style="font-weight: 400;">Emily Bache is an independent consultant, YouTuber, author, and Technical Coach, with over 25 years of experience working with Java and other programming languages and tools. She works with developers, training and coaching effective agile practices like refactoring and test-driven development. Emily has written two books about software development and contributed to several others. Emily founded the Samman Technical Coaching Society in order to promote technical excellence and support coaches everywhere.</span></p>
                    </div>
                            </div>
        </div>
    </div>



<p>It&#8217;s my pleasure to bring to your attention some interesting content that appeared in April. The huge change that is sweeping through our industry right now is the adoption of AI coding agents, which many people are using instead of hand-coding changes to software. One of the most important new skills to master is designing a &#8220;harness&#8221; for your AI tool, and this month Birgitta Böckeler has published the <a href="https://martinfowler.com/articles/harness-engineering.html" target="_blank" rel="noopener">best reference</a> I&#8217;ve seen so far about what that is and a mental model for how to think about it. Chris Parsons has also published an extensive guide titled <a href="https://www.chrismdp.com/coding-with-ai/" target="_blank" rel="noopener"><em>How I use AI to Code</em></a>, which is a really great resource for experienced developers looking to create their own harness and mentor others to do the same.</p>



<p>Perhaps as a contrast, I&#8217;d also like to highlight Michael Taggart&#8217;s <a href="https://taggart-tech.com/reckoning/" target="_blank" rel="noopener">introspective experience report</a> on his use of AI. He wrestles with his conscience over using these tools at all. An interesting metaphor for AI-assisted coding came up in an article by Drew Breunig – we run the risk of building a <a href="https://www.dbreunig.com/2026/03/26/winchester-mystery-house.html" target="_blank" rel="noopener">Winchester Mystery House</a>. After you read that, listen to Kevlin Henney’s talk <a href="https://youtu.be/vpYJMr1pJRY?si=EE528ERYChpGhHHw" target="_blank" rel="noopener"><em>Being the Human in the Loop</em></a>, where he takes a look at the engineering skills we still need – ones that could perhaps prevent the kind of thing Drew writes about from happening.&nbsp;</p>



<p>I have a particular interest in test-driven development, which, as a technical coach, is a big part of what I teach to others. I wrote an initial assessment of <a href="https://coding-is-like-cooking.info/2026/03/test-driven-development-with-agentic-ai/" target="_blank" rel="noopener">what TDD looks like these days</a>, based on interviews with several practitioners I trust who are all using agentic AI. For those of you who’d like to see me in action writing code,&nbsp; I have a demo of a <a href="https://www.youtube.com/watch?v=pqz_efj61q8" target="_blank" rel="noopener">narrow integration test for an outbound port in a hexagonal architecture</a>, in Kotlin.</p>



<h2 class="wp-block-heading">Java News</h2>



<p>Catch what shipped and track what’s next:</p>



<ul>
<li>Java News Roundup <a href="https://www.infoq.com/news/2026/04/java-news-roundup-apr06-2026/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">1</a>, <a href="https://www.infoq.com/news/2026/04/java-news-roundup-apr13-2026/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">2</a>, <a href="https://www.infoq.com/news/2026/04/java-news-roundup-apr20-2026/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">3</a>, <a href="https://www.infoq.com/news/2026/05/java-news-roundup-apr27-2026/" target="_blank" rel="noopener">4</a></li>



<li><a href="https://inside.java/2026/04/12/newsletter/" target="_blank" rel="noopener">Newsletter: Java 26 Is Now Available | JDK 27 Heads-Ups</a></li>



<li><a href="https://inside.java/2026/04/21/quality-heads-up/" target="_blank" rel="noopener">Quality Outreach Heads-up – JDK 27: Obsolete Translation Resources Removed</a></li>



<li><a href="https://www.youtube.com/watch?v=Hy-Hf-G0Fp8" target="_blank" rel="noopener">Update Your JDK, Read More Code, and Talk to Your Users: Interviews From VoxxedDays Amsterdam (#93)</a></li>
</ul>



<h2 class="wp-block-heading">Java Tutorials and Tips</h2>



<p>Steal these tricks:</p>



<ul>
<li><a href="https://nipafx.dev/inside-java-newscast-109" target="_blank" rel="noopener">Analysing Crashed JVMs – Inside Java Newscast #109</a></li>



<li><a href="https://foojay.io/today/the-javafx-revival/" target="_blank" rel="noopener">Oracle’s Java Verified Portfolio and JavaFX: What It Actually Means</a></li>



<li><a href="https://www.youtube.com/watch?v=9h0FEgNYyr8" target="_blank" rel="noopener">10 Things I Hate About Java by Adele Carpenter</a></li>



<li><a href="https://www.youtube.com/watch?v=Jts62hWkRO8" target="_blank" rel="noopener">Is AI Ruining Java Open Source? – Andres Almiray | The Marco Show</a></li>



<li><a href="https://medium.com/@achrafhasbi/java-26-updates-you-must-know-7dbbdd489a28" target="_blank" rel="noopener">Java 26: Updates You Must Know</a></li>



<li><a href="https://www.youtube.com/live/RDNrCz4EiFI" target="_blank" rel="noopener">Java and Gen AI: JVM Agents With Embabel by Rod Johnson (Spring Creator)</a></li>



<li><a href="https://spring.io/blog/2026/04/02/a-bootiful-podcast-ana-maria-mihalceanu" target="_blank" rel="noopener">A Bootiful Podcast: Java Developer Advocate Ana-Maria Mihalceanu</a></li>



<li><a href="https://foojay.io/today/does-java-really-use-too-much-memory-lets-look-at-the-facts-jeps/" target="_blank" rel="noopener">Does Java Really Use Too Much Memory? Let’s Look at the Facts (JEPs)</a></li>



<li><a href="https://foojay.io/today/java-native-memory-access-modes/" target="_blank" rel="noopener">Thread-Safe Native Memory in Java: VarHandle Access Modes Explained</a></li>



<li><a href="https://inside.java/2026/04/09/podcast-054/" target="_blank" rel="noopener">Episode 54 “How JDK 26 Improves G1’s Throughput” [AtA]</a></li>



<li><a href="https://nipafx.dev/inside-java-newscast-110" target="_blank" rel="noopener">You Must Avoid Final Field Mutation – Inside Java Newscast #110</a></li>



<li><a href="https://inside.java/2026/04/19/generics-optimization/" target="_blank" rel="noopener">How the JVM Optimizes Generic Code</a></li>



<li><a href="https://4comprehension.com/enum-map-serialization/" target="_blank" rel="noopener">The Curious Case of Enum and Map Serialization</a></li>



<li><a href="https://inside.java/2026/04/27/avoiding-final-field-mutation/" target="_blank" rel="noopener">Avoiding Final Field Mutation</a></li>
</ul>



<h2 class="wp-block-heading">Kotlin Corner</h2>



<ul>
<li><a href="https://javapro.io/2026/04/16/kotlin-kontra-java-part-1-ecosystem/" target="_blank" rel="noopener">Kotlin kontra Java – Part 1 – Ecosystem</a></li>



<li><a href="https://blog.jetbrains.com/kotlin/2026/04/kotlin-professional-certificate-by-jetbrains-now-on-linkedin-learning/">Kotlin Professional Certificate by JetBrains – Now on LinkedIn Learning</a></li>



<li><a href="https://blog.jetbrains.com/ai/2026/04/introducing-koog-integration-for-spring-ai-smarter-orchestration-for-your-agents/">Introducing Koog Integration for Spring AI: Smarter Orchestration for Your Agents</a></li>



<li><a href="https://www.youtube.com/watch?v=Tg3BN36v-wQ" target="_blank" rel="noopener">Reliable AI Agents Using Domain Modeling With Koog in Java</a></li>
</ul>



<h2 class="wp-block-heading">AI&nbsp;</h2>



<p>Cut the hype, test the tools, and boost your flow:&nbsp;</p>



<ul>
<li><a href="https://foojay.io/today/how-we-built-a-java-ai-agent-by-connecting-the-dots-the-ecosystem-already-had/" target="_blank" rel="noopener">How We Built a Java AI Agent by Connecting the Dots the Ecosystem Already Had</a></li>



<li><a href="https://www.infoq.com/articles/ai-agent-transport-layer/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Stateful Continuation for AI Agents: Why Transport Layers Now Matter</a></li>



<li><a href="https://spring.io/blog/2026/04/09/a-bootiful-podcast-ana-mark-kropf" target="_blank" rel="noopener">A Bootiful Podcast: Mark Kropf on AI Orchestration</a></li>



<li><a href="https://www.youtube.com/watch?v=2mGr7kdstJs" target="_blank" rel="noopener">Embabel Tools &amp; MCP Servers: Supercharge Your Java AI Agents</a></li>



<li><a href="https://blog.jetbrains.com/qodana/2026/04/adversarial-ai-threats/">Adversarial AI: Understanding the Threats to Modern AI Systems</a></li>



<li><a href="https://foojay.io/today/why-java-developers-over-trust-ai-dependency-suggestions/" target="_blank" rel="noopener">Why Java Developers Over-Trust AI Dependency Suggestions</a></li>



<li><a href="https://blog.frankel.ch/agentic-github-workflows/" target="_blank" rel="noopener">A GitHub Agentic Workflow</a>&nbsp;</li>



<li><a href="https://blog.pollack.ai/p/8a0a3a73-144a-4615-a992-560da556f13c/" target="_blank" rel="noopener">ACP Java SDK: Building IDE Agents in Java</a>&nbsp;</li>



<li><a href="https://spring.io/blog/2026/04/15/spring-ai-session-management" target="_blank" rel="noopener">Spring AI Agentic Patterns (Part 7): Session API – Event-Sourced Short-Term Memory with Context Compaction</a></li>



<li><a href="https://www.infoq.com/articles/beyond-rag-context-aware/" target="_blank" rel="noopener">Beyond RAG: Architecting Context-Aware AI Systems With Spring Boot</a>&nbsp;</li>



<li><a href="https://spring.io/blog/2026/04/07/spring-ai-agentic-patterns-6-memory-tools" target="_blank" rel="noopener">Spring AI Agentic Patterns (Part 6): AutoMemoryTools – Persistent Agent Memory Across Sessions</a>&nbsp;</li>



<li><a href="https://foojay.io/today/best-practices-for-working-with-ai-agents-subagents-skills-and-mcp/" target="_blank" rel="noopener">5 Best Practices for Working with AI Agents, Subagents, Skills, and MCP</a>&nbsp;</li>



<li><a href="https://www.infoq.com/presentations/deepfakes-ai/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Deepfakes, Disinformation, and AI Content Are Taking Over the Internet</a></li>



<li><a href="https://www.infoq.com/articles/mcp-java-architectural-strategy-llm-integrations/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">MCP in the Java World: Bringing Architectural Strategy to LLM Integrations</a></li>
</ul>



<h2 class="wp-block-heading">Languages, Frameworks, Libraries, and Technologies</h2>



<p>Explore new tools and technologies, and revisit the old ones:</p>



<ul>
<li>This Week in Spring <a href="https://spring.io/blog/2026/04/07/this-week-in-spring-april-07-2026" target="_blank" rel="noopener">1</a>, <a href="https://spring.io/blog/2026/04/14/this-week-in-spring-april-14-2026" target="_blank" rel="noopener">2</a>, <a href="https://spring.io/blog/2026/04/21/this-week-in-spring-april-21-2026" target="_blank" rel="noopener">3</a>, <a href="https://spring.io/blog/2026/04/28/this-week-in-spring-april-28-2026" target="_blank" rel="noopener">4</a></li>



<li><a href="https://www.infoq.com/articles/beyond-rag-context-aware/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Article: Beyond RAG: Architecting Context-Aware AI Systems With Spring Boot</a></li>



<li><a href="http://hollycummins.com/quarkus-ridiculous-things-devoxx-poland/" target="_blank" rel="noopener">Six and a Half Ridiculous Things to Do With Quarkus</a></li>



<li><a href="https://www.infoq.com/articles/spring-team-spring-7-boot-4/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">The Spring Team on Spring Framework 7 and Spring Boot 4</a></li>



<li><a href="https://spring.io/blog/2026/04/16/a-bootiful-podcast-craig-walls" target="_blank" rel="noopener">A Bootiful Podcast: The Legendary Craig Walls</a></li>



<li><a href="https://quarkus.io/blog/reflection-free-jsckson-serializers/" target="_blank" rel="noopener">Enabling Reflection-Free Jackson Serializers by Default</a>&nbsp;</li>



<li><a href="https://dandreamsofcoding.com/2026/03/31/understanding-performance/" target="_blank" rel="noopener">Understanding Performance</a>&nbsp;</li>



<li><a href="https://spring.io/blog/2026/04/23/a-bootiful-podcast-venkat-james" target="_blank" rel="noopener">A Bootiful Podcast: A Bootiful Podcast: Dr. Venkat Subramaniam and James Ward on Intelligent Kotlin and So Much More</a></li>



<li><a href="https://foojay.io/today/the-road-to-docker-official-images-for-java-the-azul-zulu-story/" target="_blank" rel="noopener">The Road to Docker Official Images for Java: The Azul Zulu Story</a></li>



<li><a href="https://www.youtube.com/watch?v=cUofXEeCCXo" target="_blank" rel="noopener">Spring Debugger New Power: Where Should I Click to Demystify Spring Boot Magic?</a></li>
</ul>



<h2 class="wp-block-heading">Conferences and Events</h2>



<p>Join the crowd online or offline:</p>



<ul>
<li><a href="https://jax.de/mainz-en" target="_blank" rel="noopener">JAX</a> – Mainz, Germany or Online, May 4–8</li>



<li><a href="https://www.devoxx.co.uk" target="_blank" rel="noopener">Devoxx UK</a> – London, United Kingdom, May 6–7; JetBrains will have a booth at the event. Also, come and listen to our JetBrains speakers: <a href="https://maritvandijk.com/" target="_blank" rel="noopener">Marit van Dijk</a>, <a href="https://cheuk.dev/" target="_blank" rel="noopener">Cheuk Ting Ho</a>, and <a href="https://www.linkedin.com/in/vergauwensimon/" target="_blank" rel="noopener">Simon Vergauwen</a>. The Spring documentary will premiere there, followed by a panel with <a href="https://joshlong.com/" target="_blank" rel="noopener">Josh Long</a>, <a href="https://www.linkedin.com/in/noregressions/" target="_blank" rel="noopener">Steve Poole</a>, and <a href="https://maritvandijk.com/" target="_blank" rel="noopener">Marit van Dijk</a>.</li>
</ul>



<ul>
<li><a href="https://2026.geecon.org" target="_blank" rel="noopener">GeeCon</a> – Kraków, Poland, May 14–15; <a href="https://maritvandijk.com/" target="_blank" rel="noopener">Marit van Dijk</a> is speaking and moderating a panel on Java to discuss what excites each of them most about Java in 2026.&nbsp;</li>



<li><a href="http://jalba.scot" target="_blank" rel="noopener">JAlba</a> – Edinburgh, Scotland, May 14–16</li>



<li><a href="https://jnation.pt" target="_blank" rel="noopener">JNation Conference</a> – Coimbra, Portugal, May 26–27; <a href="https://www.linkedin.com/in/antonarhipov/" target="_blank" rel="noopener">Anton Arhipov</a> and <a href="https://maritvandijk.com/" target="_blank" rel="noopener">Marit van Dijk</a> from JetBrains are the speakers.&nbsp;</li>



<li><a href="https://makeit.si" target="_blank" rel="noopener">JCON Slovenia</a> – Portorož, Slovenia, May 27–29</li>
</ul>



<figure class="wp-block-image size-full"><a href="https://kotlinconf.com/" target="_blank" rel="noopener"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" fetchpriority="high" src="https://blog.jetbrains.com/wp-content/uploads/2026/05/image-1.png" alt="" class="wp-image-705191"/></a></figure>



<h2 class="wp-block-heading">Culture and Community</h2>



<p>Where do you stand on these topics?</p>



<ul>
<li><a href="https://www.infoq.com/presentations/panel-positive-culture/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Panel: Building a Culture That Works</a></li>



<li><a href="https://sive.rs/balance" target="_blank" rel="noopener">How to Do What You Love and Make Good Money</a>&nbsp;</li>



<li><a href="https://www.paulgraham.com/ds.html" target="_blank" rel="noopener">Do Things That Don’t Scale</a>&nbsp;</li>



<li><a href="https://martinfowler.com/articles/reduce-friction-ai/encoding-team-standards.html" target="_blank" rel="noopener">Encoding Team Standards</a>&nbsp;</li>



<li><a href="https://blog.scottlogic.com/2026/04/01/beyond-the-hype-is-ai-taking-fun-out-of-software-development.html" target="_blank" rel="noopener">Beyond the Hype: Is AI Taking the Fun out of Software Development?</a>&nbsp;</li>
</ul>



<h2 class="wp-block-heading">And Finally…</h2>



<p>One last thing before you close the article. Don’t skip it!</p>



<ul>
<li><a href="https://blog.jetbrains.com/idea/2026/03/using-spring-data-jpa-with-kotlin/">Using Spring Data JPA With Kotlin</a></li>



<li><a href="https://blog.jetbrains.com/idea/2026/04/using-spring-data-jdbc-with-kotlin/">Using Spring Data JDBC With Kotlin</a></li>



<li><a href="https://blog.jetbrains.com/platform/2026/04/speeding-up-interactive-rebase-in-jetbrains-ides/">Speeding up Interactive Rebase in JetBrains IDEs</a></li>



<li><a href="https://blog.jetbrains.com/platform/2026/04/from-java-to-wayland-a-pixel-s-journey/">From Java to Wayland: A Pixel’s Journey</a></li>
</ul>



<p>That’s it for today! We’re always collecting ideas for the next Java Annotated Monthly – send us your suggestions via <a href="https://mail.google.com/mail/u/0/?fs=1&amp;tf=cm&amp;source=mailto&amp;to=JAM@jetbrains.com" target="_blank" rel="noopener">email</a> or <a href="https://x.com/intellijidea?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor" target="_blank">X</a> by May 20. And don’t forget to check out our archive of <a href="https://www.jetbrains.com/lp/jam/" target="_blank" rel="noopener">past JAM issues</a> for any articles you might have missed!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Teaching an AI Agent to Debug Flaky Tests</title>
		<link>https://blog.jetbrains.com/idea/2026/05/teaching-an-ai-agent-to-debug-flaky-tests/</link>
		
		<dc:creator><![CDATA[Igor Kulakov]]></dc:creator>
		<pubDate>Mon, 04 May 2026 09:14:46 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/04/IJ-social-BlogFeatured-1280x720-1-3.png</featuredImage>		<category><![CDATA[ai]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[tutorials]]></category>
		<category><![CDATA[ai-agent]]></category>
		<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[ai-skills]]></category>
		<category><![CDATA[intellij-idea]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=704196</guid>

					<description><![CDATA[If you&#8217;ve been connected to the internet for a while, you&#8217;ve surely heard of AI Agent Skills. They teach your agent to do this and that. You might have even used or written a couple of them yourself. If you aren&#8217;t yet familiar with them, the idea is simple: Instead of prompting instructions for a [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>If you&#8217;ve been connected to the internet for a while, you&#8217;ve surely heard of <a href="https://blog.jetbrains.com/idea/2026/03/ai-assisted-java-application-development-with-agent-skills/">AI Agent Skills</a>. They teach your agent to do this and that. You might have even used or written a couple of them yourself.</p>



<p>If you aren&#8217;t yet familiar with them, the idea is simple: Instead of prompting instructions for a specific task each time, you define them once and reuse them later. A Skill is an AI equivalent of a knowledge base article: a plain text document that lives in a discoverable location and describes steps, a set of conventions, or domain-specific knowledge.</p>



<p>Most Skills you see in the wild are for simple things like enforcing code style or commit message conventions. But they can be much more powerful than that. In this article, we&#8217;ll combine AI Skills, good old developer tools, and a bit of creative thinking to address a notoriously challenging task: making AI <em>deterministically</em> find the root cause of flaky tests.</p>



<h2 class="wp-block-heading"><strong>The problem</strong></h2>



<p>Quoting the <a href="https://www.jetbrains.com/teamcity/ci-cd-guide/concepts/flaky-tests/" target="_blank" rel="noopener">TeamCity CI/CD guide</a>:</p>



<blockquote class="wp-block-quote">
<p></p>
<cite>Flaky tests are defined as tests that return both passes and failures despite no changes to the code or the test itself.</cite></blockquote>



<p><em>Flakiness</em> undermines the whole point of tests: When a test fails, you can&#8217;t tell whether something is actually broken. You can&#8217;t fully rely on the test results, and at the same time, you can&#8217;t ignore them. This wastes both human and infrastructure resources.</p>



<p>And as if the underlying bugs weren&#8217;t difficult enough on their own, flaky tests often have this property of failing once in several thousand runs, making them extremely hard to reproduce and debug.</p>



<h2 class="wp-block-heading"><strong>Example project</strong></h2>



<p>For the example project, let&#8217;s take the <a href="https://github.com/flounder4130/webshop-demo" target="_blank" rel="noopener">webshop demo</a> from this article: <a href="https://flounder.dev/posts/your-programs-are-not-single-threaded/" target="_blank" rel="noopener">Your Programs Are Not Single-Threaded</a>. It is a Spring Boot project, in which one of the services has a <a href="https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use" target="_blank" rel="noopener">TOCTOU (time-of-check to time-of-use)</a> problem: It checks a condition and then acts on it, but another thread can change the state in between. In this particular case, it may sometimes cause duplicate invoice numbers and also makes the corresponding test flaky.</p>



<p>Here&#8217;s the problematic test:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@SpringBootTest
class InvoiceServiceTest {

    @Autowired
    private OrderService orderService;

    @Test
    void firstTwoOrdersGetInvoiceNumbersOneAndTwo() {
        CompletableFuture&lt;Invoice> alice = CompletableFuture.supplyAsync(
                () -> orderService.checkout("Alice", BigDecimal.TEN));
        CompletableFuture&lt;Invoice> bob = CompletableFuture.supplyAsync(
                () -> orderService.checkout("Bob", BigDecimal.TEN));

        String num1 = alice.join().getInvoiceNumber();
        String num2 = bob.join().getInvoiceNumber();

        assertEquals(Set.of("INV-00001", "INV-00002"), Set.of(num1, num2));
    }
}
</pre>



<p>The test creates two orders concurrently and checks that the resulting invoices get numbers <code>INV-00001</code> and <code>INV-00002</code>. Because of a bug in <code>InvoiceService</code>, it can either pass or fail randomly.</p>


                    <div class="alert ">
            <p><strong>Note:</strong> If you&#8217;re using IntelliJ IDEA, you can test whether a test is actually flaky by using the Run until failure option in the test runner. Leave the suspect spinning for some time and see if it eventually fails.<br />
</p>
        </div>
    






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



<p>If we knew nothing about the underlying bug, and only had the test, is there a tool that could help us find the root cause? Or can we make one ourselves? Furthermore, could we delegate both building and using the tool to AI?</p>



<h2 class="wp-block-heading"><strong>The intuition</strong></h2>



<p>Let&#8217;s come up with some intuition for this class of problem.</p>



<p>To produce two kinds of results, the execution must follow different code paths. The difference might be minimal, possibly just one extra method call or one <code>if</code> branch taken instead of another. But it has to be there; otherwise, the result would be consistent. So, if we could record the code path for a passing run and a failing run and then compare them, the diff should at least point us in the right direction. And ideally, by following the call tree, we could find the place where execution splits. This line must be exactly where the flakiness originates.</p>



<p>Does this reasoning make sense? Let&#8217;s put it to the test.</p>



<h2 class="wp-block-heading"><strong>Build the tools</strong></h2>



<p>What tool can we use for recording code paths? While not designed specifically for tracing, a test coverage tool can give us the information we&#8217;re after.</p>



<p>There are a couple of Java coverage tools to choose from, such as <a href="https://www.jacoco.org/jacoco/" target="_blank" rel="noopener">JaCoCo</a> and <a href="https://www.jetbrains.com/help/idea/code-coverage.html" target="_blank" rel="noopener">IntelliJ IDEA&#8217;s coverage tool</a>. We&#8217;ll go with IntelliJ IDEA&#8217;s, because it includes a hit counting feature that is very useful. We may need this extra granularity because the flakiness might stem not only from <em>what</em> is executed, but also <em>how many times</em>.</p>



<h3 class="wp-block-heading"><strong>Run coverage from the command line</strong></h3>



<p>IntelliJ IDEA&#8217;s coverage tool has a familiar UI, but we need a way to launch it programmatically. Fortunately, coverage can also be collected from the command line by attaching the coverage agent to the JVM via <a href="https://maven.apache.org/surefire/maven-surefire-plugin/" target="_blank" rel="noopener">Maven Surefire</a>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">mvn surefire:test \
  -Dtest=com.example.webshop.service.InvoiceServiceTest \
  "-DargLine=-Didea.coverage.calculate.hits=true \
    -javaagent:\$AGENT_JAR=\$IC_FILE,true,false,false,true,com.example.webshop.*"
</pre>



<p>The <code>-Didea.coverage.calculate.hits=true</code> flag tells the agent to record invocation counts per line rather than just a boolean hit/not-hit mask. After the test finishes, the results are written to a binary <code>.ic</code> file.</p>



<p>So far so good, but we need the report in a human (and AI)-readable format.</p>



<h3 class="wp-block-heading"><strong>Add text output</strong></h3>



<p>Luckily, the <a href="https://github.com/JetBrains/intellij-coverage" target="_blank" rel="noopener">IntelliJ coverage agent</a> is open-source. Let&#8217;s clone the project and ask AI to add a text reporter that converts binary reports to plain text.</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/image6-1.png" alt="" class="wp-image-704276"/></figure>



<p>The agent creates a new class called <code>TextCoverageStatistics</code>. After we build the project and run the reporter against our <code>.ic</code> file, we get something like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">=== Coverage Summary ===

  Instructions: 236/618  38,2%
  Branches    : 0/20   0,0%
  Lines       : 56/150  37,3%
  ...

=== Per-Class Coverage ===

Class                                                           Lines    Line%  Methods    Meth%
--------------------------------------------------------------------------------------------
...
com.example.webshop.service.InvoiceNumberGenerator              4/4    100,0%    2/2    100,0%
com.example.webshop.service.InvoiceService                     10/10   100,0%    3/3    100,0%
com.example.webshop.service.OrderService                        6/6    100,0%    2/2    100,0%
...
</pre>



<p>The first part of the report gives a high-level overview: How many lines, branches, and methods were covered across the entire project. Below that, there&#8217;s a per-class breakdown showing the same metrics for each class individually.</p>



<p>Then it is followed by per-line hit counts for each class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">--- com.example.webshop.service.InvoiceService ---
  Line       Hits  Branch
  19            2
  20            1
  22            2
  23            2
  24            2
  ...</pre>



<p>For every line that the coverage agent instrumented, we see how many times it was executed and whether any branches were taken. The actual report is longer, but you get the idea. Now we have a text representation of which lines were executed, and exactly how many times.</p>



<p>This is the raw material we need for the diff. So far, so good!</p>



<h3 class="wp-block-heading"><strong>Diff the reports</strong></h3>



<p>Supposedly, the obtained reports contain the necessary information, and a very determined developer could peruse them and find the bug. But we&#8217;re not here for mundane tasks like that, right?</p>



<p>Let&#8217;s upgrade the tool so that it gets multiple report variations and presents the diff. The most controllable way would be to do one &#8220;brick&#8221; at a time, but I think we&#8217;re safe to delegate the entire thing to AI here, including the automation:</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/image1-2.png" alt="" class="wp-image-704287"/></figure>



<p>The resulting script runs the test in a loop until <em>both</em> of the following happen:</p>



<ul>
<li>We get at least one passing and one failing run.</li>



<li>The specified number of runs have passed.</li>
</ul>



<p>Both conditions are important because test failures can be very rare, and the specified number of runs might not be enough. At the same time, there can be finer grained variations within pass and fail runs, so we might want to catch those too.</p>



<p>After the reports are collected, the script summarizes the lines that have variations between the runs. Here&#8217;s what it looks like:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Collected 20 runs: 12 pass, 8 fail

Lines that vary across runs:

  Invoice:29                           Hits(1,2)
  Invoice:31                           Hits(1,2)
  Invoice:32                           Hits(1,2)
  InvoiceNumberGenerator:15            Hits(1,2)
  InvoiceService:19                    Hits(1,2)  Branch(1/2)
  InvoiceService:20                    Hits(1,2)
  InvoiceService:22                    Hits(1,2)
  InvoiceService:24                    Hits(1,2)</pre>



<p>All variations have the same pattern: the difference is not which lines were executed, but <em>how many times</em>. As we expected, the hit counting feature of IntelliJ IDEA&#8217;s coverage agent proved useful!</p>



<p>The varying lines point at a lazy initialization block in <code>InvoiceService</code> and its downstream effects in <code>InvoiceNumberGenerator</code> and <code>Invoice</code>. The variation in hit counts means that the initialization sometimes runs more than once, which shouldn&#8217;t happen. That&#8217;s exactly where the flakiness comes from.</p>



<p>If you missed the article that describes the problem, here&#8217;s why double initialization causes this bug. The <code>createGenerator()</code> method queries the database for the last used invoice number and creates a counter starting from that value. When two threads both enter the <code>if (generator == null)</code> block before either finishes, each reads the same number from the database and creates its own generator starting from the same value. The result is duplicate invoice numbers.</p>



<p>The coverage diff has pointed us at the very same <a href="http://localhost:8085/posts/your-programs-are-not-single-threaded/" target="_blank" rel="noopener">TOCTOU race</a> discussed in more detail in the previous article. But, what is novel in our current approach is that it doesn’t solely rely on human expertise and is easily accessible for AI.</p>



<h2 class="wp-block-heading"><strong>Turning it into a Skill</strong></h2>



<p>Now, I&#8217;d say that AI-assisted modifications to open-source tools that help you solve the task at hand, all within minutes, are amazing on their own. But let&#8217;s keep our eyes on the bigger picture.</p>



<p>Here&#8217;s what we&#8217;ve done so far: We started with an intuition: Flaky tests take different code paths, and coverage analysis can reveal where they diverge. Then we turned that intuition into a concrete, repeatable procedure. Does this warrant a knowledge base article, or an AI Agent Skill, perhaps? Yes!</p>



<p>In the same agent session, let&#8217;s ask the agent to:</p>



<ol>
<li>Make sure all the scripts are self-contained and runnable.</li>



<li>Document the entire procedure in a <code>SKILL.md</code> file, step by step, so that another agent can follow it without any prior context.</li>
</ol>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/image5-1.png" alt="" class="wp-image-704298"/></figure>



<p>The agent packages everything and writes a guide that describes when to apply the Skill, what tools are needed, and what steps to follow.



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/image-38.png" alt="" class="wp-image-704198"/></figure>



The only follow-up during review was to align the Skill with the <a href="https://agentskills.io/specification" target="_blank" rel="noopener">specification</a>. The original Skill written by the agent lacks meta in frontmatter. Agents are good at sorting out Skills that omit minor details, but meta is important for discoverability. Without it, a Skill might not be picked up by an agent in the first place.</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/image-39.png" alt="" class="wp-image-704235"/></figure>



<h2 class="wp-block-heading"><strong>Testing the Skill</strong></h2>



<p>To verify that the Skill actually works, let&#8217;s start a fresh agent session. No warm-up, no hints. Instead, let&#8217;s deliberately phrase it in a very general way, something like &#8220;find and fix the cause of flakiness in <code>InvoiceServiceTest</code>&#8220;.</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/05/skill-used.png" alt="An agent uses the skill" class="wp-image-704309"/></figure>



<p>The agent matches the Skill description from <code>SKILL.md</code> with the problem description, discovers the instructions, and executes them: It runs the coverage script, reads the diff, and identifies the race condition. Instead of guesswork, it follows the established steps and arrives at the same conclusion every time. That’s about as deterministic as generative AI can get!</p>



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



<p>The changes that we’ve made to the coverage agent are already published with the new version <a href="https://mvnrepository.com/artifact/org.jetbrains.intellij.deps/intellij-coverage-agent/1.0.774" target="_blank" rel="noopener">1.0.774</a>. And the Skill is available <a href="https://github.com/flounder4130/webshop-demo/blob/main/.claude/skills/analyze-flaky-coverage/SKILL.md" target="_blank" rel="noopener">here</a>. </p>



<p>In this article, we started with an intuition about flaky tests, built custom tooling around an open-source coverage agent, used it to find a race condition, and packaged the entire procedure into a reusable AI Skill. You can use this Skill for finding flaky tests in your own projects, but I hope this post conveys the bigger idea.</p>



<p>AI Skills allow you to teach agents to solve virtually anything, as long as you can stack text interfaces together. Many hard programming problems can be broken down into simpler ones and solved using familiar tools. And with AI orchestrating all this, we can even make the process enjoyable. As was the case long before AI, curiosity is the only real prerequisite. </p>



<p>Have you been inspired to solve a tough problem in your own work? Would you like to share the Skills you wrote or find most useful? Let us know in the comments!</p>



<p>Happy debugging!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>IntelliJ IDEA 2026.1.1 Is Out!</title>
		<link>https://blog.jetbrains.com/idea/2026/04/intellij-idea-2026-1-1/</link>
		
		<dc:creator><![CDATA[Maria Kosukhina]]></dc:creator>
		<pubDate>Thu, 23 Apr 2026 13:04:22 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/04/IntelliJ-IDEA-2026.1.1.png</featuredImage>		<category><![CDATA[releases]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=702902</guid>

					<description><![CDATA[IntelliJ IDEA 2026.1.1 has arrived with several valuable fixes. You can update to this version from inside the IDE, using the&#160;Toolbox App, or using snaps if you are a Ubuntu user. You can also download it from our&#160;website. Here are the most notable updates included in this version: To find out more details about the [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>IntelliJ IDEA 2026.1.1 has arrived with several valuable fixes.</p>



<p>You can update to this version from inside the IDE, using the&nbsp;<a href="https://www.jetbrains.com/toolbox-app/" target="_blank" rel="noreferrer noopener">Toolbox App</a>, or using snaps if you are a Ubuntu user. You can also download it from our&nbsp;<a href="https://www.jetbrains.com/idea/download/" target="_blank" rel="noreferrer noopener">website</a>.</p>



<p>Here are the most notable updates included in this version:</p>



<ul>
<li>It’s once again possible to set up a WSL Python SDK. [<a href="https://youtrack.jetbrains.com/issue/IJPL-240728/Unable-to-add-WSL-Python-SDK" target="_blank" rel="noopener">IJPL-240728</a>]</li>



<li>Emmet in remote development now works as expected. [<a href="https://youtrack.jetbrains.com/issue/IJPL-168255" target="_blank" rel="noopener">IJPL-168255</a>]&nbsp;</li>



<li>Gradle sync no longer fails due to a class cast error involving <code>InternalIdeaModule</code> and <code>org.gradle.tooling.model.ProjectModel</code>. [<a href="https://youtrack.jetbrains.com/issue/IDEA-386409/Gradle-sync-fails-with-InternalIdeaModule-cannot-be-cast-to-class-org.gradle.tooling.model.ProjectModel" target="_blank" rel="noopener">IDEA-386409</a>]</li>



<li>The IDE now correctly connects to the WildFly admin process after server startup, restoring deployment and the <em>Open browser after launch</em> option. [<a href="https://youtrack.jetbrains.com/issue/IDEA-387483" target="_blank" rel="noopener">IDEA-387483</a>]&nbsp;</li>



<li>The IDE no longer fails to locate the WSL 2 JDK. [<a href="https://youtrack.jetbrains.com/issue/IJPL-222935" target="_blank" rel="noopener">IJPL-222935</a>]&nbsp;</li>



<li>Double-clicking an Ant target in the <em>Ant</em> tool window now runs the target and shows the build output in the <em>Messages </em>tool window. [<a href="https://youtrack.jetbrains.com/issue/IDEA-387507" target="_blank" rel="noopener">IDEA-387507</a>]&nbsp;</li>



<li>Search for context actions and code completion in large Spring projects are now more responsive and faster. [<a href="https://youtrack.jetbrains.com/issue/IDEA-378966" target="_blank" rel="noopener">IDEA-378966</a>]&nbsp;&nbsp;</li>



<li>The IDE now correctly supports creating a run configuration for a local WebLogic server.<a href="https://youtrack.jetbrains.com/issue/IDEA-387617" target="_blank" rel="noopener"> [IDEA-387617</a>]</li>



<li>The <em>Find and Replace</em> action now works as expected when pressing <em>Enter</em>. [<a href="https://youtrack.jetbrains.com/issue/IJPL-240373" target="_blank" rel="noopener">IJPL-240373</a>]</li>
</ul>



<p></p>



<p>To find out more details about the issues resolved, please refer to the <a href="https://youtrack.jetbrains.com/articles/IDEA-A-2100662664" data-type="link" data-id="https://youtrack.jetbrains.com/articles/IDEA-A-2100662664" target="_blank" rel="noopener">release notes</a>.</p>



<p>If you encounter any bugs, please report them to our&nbsp;<a href="https://youtrack.jetbrains.com/issues/IDEA" target="_blank" rel="noreferrer noopener">issue tracker</a>.</p>



<p>Happy developing!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using Spring Data JDBC With Kotlin</title>
		<link>https://blog.jetbrains.com/idea/2026/04/using-spring-data-jdbc-with-kotlin/</link>
		
		<dc:creator><![CDATA[Teodor Irkhin]]></dc:creator>
		<pubDate>Thu, 09 Apr 2026 11:46:14 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/04/IJ-social-BlogFeatured-1280x720-1-1.png</featuredImage>		<category><![CDATA[features]]></category>
		<category><![CDATA[kotlin]]></category>
		<category><![CDATA[tutorials]]></category>
		<category><![CDATA[jdbc]]></category>
		<category><![CDATA[spring]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=699658</guid>

					<description><![CDATA[This post was written together with&#160;Thorben Janssen, who has more than 20 years of experience with JPA and Hibernate and is the author of “Hibernate Tips: More than 70 Solutions to Common Hibernate Problems” and the JPA newsletter. Spring Data JDBC provides a simple and predictable persistence model. It focuses on aggregate roots, constructor-based mapping, [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><em>This post was written together with&nbsp;<a href="https://thorben-janssen.com/" target="_blank" rel="noreferrer noopener">Thorben Janssen</a>, who has more than 20 years of experience with JPA and Hibernate and is the author of “Hibernate Tips: More than 70 Solutions to Common Hibernate Problems” and the JPA newsletter.</em></p>



<p>Spring Data JDBC provides a simple and predictable persistence model. It focuses on aggregate roots, constructor-based mapping, and clear rules for reading and writing data. If you enjoy working with explicit data flows and want full control over your SQL, Spring Data JDBC might be the perfect framework for your project.</p>



<p>And with Kotlin, everything becomes so much easier. Its focus on immutability, null safety, and concise data structures aligns nicely with Spring Data JDBC&#8217;s design. In this article, you will see how to model aggregates, store and retrieve data, use <code>value</code> objects, handle child entities, and define custom queries using Kotlin.</p>



<h1 class="wp-block-heading">Kotlin&#8217;s strengths for JDBC-based persistence</h1>



<p>Before looking at concrete examples, it helps to understand why Kotlin fits so well into this programming model.</p>



<p><code>Data</code> classes keep your aggregates concise. They define constructor parameters, implement the <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code> methods, and encourage immutable states. Spring Data JDBC provides strong support for constructor-based mapping and handles immutable aggregates with ease, significantly reducing boilerplate code.</p>



<p>Kotlin’s type system also reduces many common mistakes. Nullability is explicit, so you can see immediately which fields may not contain a value. Constructor-based mapping becomes more reliable because there is no silent conversion of null values into empty strings or default primitives.</p>



<p>Lightweight <code>value</code> classes allow you to express domain concepts without adding noise. An email address, a customer number, or a price becomes a first-class concept in your model. And Spring Data JDBC can, of course, map them without requiring any additional boilerplate code or mapping annotations.</p>



<p>Kotlin also simplifies custom query projections, because <code>data</code> classes work very well with constructor mapping. Default parameters, named arguments, and collection operations make aggregate updates straightforward.</p>



<p>All these features create a natural fit for Spring Data JDBC and Kotlin.</p>



<h2 class="wp-block-heading">Defining an aggregate root with Kotlin</h2>



<p>An aggregate is a pattern introduced by <a href="https://martinfowler.com/bliki/DDD_Aggregate.html" target="_blank" rel="noopener">domain-driven design (DDD)</a> concepts. It consists of one or more entities that are handled as a unit when reading or writing them to the database. The aggregate root is the primary object of the aggregate. You address it when referencing the aggregate or when fetching it from the database.&nbsp;</p>



<p>Let&#8217;s start with a simple aggregate that only consists of the aggregate root. Each instance is stored as a record in your database whenever you decide to persist or update it. There is no hidden state and no proxying.</p>



<p>The following <code>data</code> class represents a person. The <code>@Table</code> annotation is optional, but it clearly marks the class as an entity. This helps IntelliJ IDEA to provide you with the most suitable tooling when building your persistence layer.</p>



<p>The <code>@Id</code> annotation marks the field as the object’s identifier. The <code>@Sequence</code> annotation is optional and tells Spring Data to retrieve a value from the database sequence when persisting a new object. And because this happens after you created a new Person object in your code, the ID field has to be nullable.</p>



<p>If you want, you can define all other fields as non-nullable.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Table
data class Person(
    @Id
    @Sequence(sequence = "person_seq")
    val id: Long? = null,
    val firstName: String,
    val lastName: String
)</pre>



<p>As you can see in the code snippet, you don’t need to provide any additional mapping annotations. By default, Spring Data JDBC maps the class to a database table with the same name and each field to a column with the same name. You can change this mapping by annotating your class with <code>@Table</code> and a field with <code>@Column</code>. But most teams try to avoid that to keep their entities easy to read and understand.</p>



<p>By default, Spring Data JDBC uses the primary constructor to create and hydrate entity instances. You can also annotate a constructor with <code>@PersistenceCreator</code> if you want Spring Data JDBC to use it instead. This is an excellent match for Kotlin’s <code>data</code> classes, because all non-primary-key fields can be immutable, mandatory, and have default values. This helps you avoid uninitialized properties and the need for no-argument constructors that you might be familiar with in Spring Data JPA and other persistence frameworks.</p>



<p>After you define the aggregate, you have to create a repository to manage it.</p>



<h2 class="wp-block-heading">Creating repositories and defining queries</h2>



<p>Spring Data JDBC uses repository interfaces to define data access operations. The simplest way to define a repository is to extend Spring Data JDBC’s <code>CrudRepository</code>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface PersonRepository : CrudRepository&lt;Person, Long> {}</pre>



<p>This provides you with basic methods, including <code>save()</code>, <code>findById()</code>, and <code>deleteById()</code>.</p>



<p>You can also add your own queries using Spring Data JDBC’s derived query methods. These are methods whose names describe the query that Spring Data JDBC should execute. The framework parses the method name, creates the appropriate SQL statement, and maps the query result.</p>



<p>And if you need more control over the executed query statement, you can define a method, annotate it with <code>@Query</code>, and provide your own SQL statement. Spring Data JDBC handles the rest!</p>



<p>Here are a few examples.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface PersonRepository : CrudRepository&lt;Person, Long> {
    fun findByLastName(lastName: String): List&lt;Person>

    @Query("select * from Person p where p.last_name = :lastName")
    fun getByLastName(lastName: String): List&lt;Person>
}</pre>



<p>You can also return Kotlin <code>data</code> class projections. This works well when you want to read specific columns but not the entire aggregate, or when you want to transform your data into a different structure.</p>



<p>The following PersonName <code>data</code> class and <code>findPersonNameById</code> repository method show a typical example.&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class PersonName(
    val id: Long,
    val name: String
)

interface PersonRepository : CrudRepository&lt;Person, Long> {
    @Query("select p.id, p.first_name || ' ' || p.last_name as name FROM Person p where p.id = :id")
    fun findPersonNameById(id: Long): PersonName
}</pre>



<p>Spring Data JDBC executes the defined query and maps the query result to the constructor parameters of the <code>PersonName</code> class. This keeps the projection code clean and allows you to avoid manual mapping.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">2025-12-09T21:59:12.572+01:00 DEBUG 7484 --- [SDJWithKotlin] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [select p.id, p.first_name || ' ' || p.last_name as name FROM Person p where p.id = ?]
2025-12-09T21:59:12.595+01:00  INFO 7484 --- [SDJWithKotlin] [           main] c.t.j.k.s.SpringDataJdbcKotlinTests      : PersonName(id=401, name=Jane Smith)</pre>



<h2 class="wp-block-heading">Persisting and loading aggregates</h2>



<p>Working with repositories is straightforward. Each call interacts directly with the database. There is no state tracking or implicit updates. This makes the behavior easy to understand and gives you full control over the executed statements.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Service
@Transactional
class PersonService(private val personRepository: PersonRepository) {
    fun createNewPerson(firstName: String, lastName: String): Person {
        // add additional validations and/or logic ...
        return personRepository.save(
            Person(
                firstName = firstName,
                lastName = lastName
            )
        )
    }

    fun updateLastName(id: Long, lastName: String): Person {
        val person = personRepository.findById(id).orElseThrow()
        val updated = person.copy(lastName = lastName)
        return personRepository.save(updated)
    }
}</pre>



<p>The only logic Spring Data JDBC provides when you call the <code>save()</code> method is a check to see if the identifier is <code>null</code>. If it is, the record is inserted. Otherwise, an update is executed. Since all fields are immutable, you’re always working with complete and consistent objects.</p>



<h2 class="wp-block-heading">Using Kotlin value objects in your aggregate</h2>



<p>Real-world aggregates often contain values that deserve their own type. Using Kotlin, you can model them using <code>value</code> classes, and Spring Data JDBC supports them out of the box.</p>



<p>If your <code>value</code> class only wraps one value, you should annotate it with <a href="https://kotlinlang.org/docs/inline-classes.html" target="_blank" rel="noopener">@JvmInline</a>. This activates a Kotlin-specific optimization removing the performance overhead of a wrapper class by replacing it with its inlined value at runtime.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@JvmInline
value class Email(val value: String)

data class Person(
    @Id
    @Sequence(sequence = "person_seq")
    val id: Long? = null,
    val firstName: String,
    val lastName: String,
    val email: Email
)</pre>



<p>As you can see, Kotlin’s <code>value</code> and <code>data</code> classes make the code very easy to read and quick to write.&nbsp;</p>



<p>Doing the same in Java requires much more code, an additional mapping annotation and Spring Data JDBC’s embedded entity concept.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Table
public class Person {

    @Id
    @Sequence(sequence = "person_seq")
    private Long id;

    private String firstName;

    private String lastName;

    @Embedded.Nullable
    private Email email;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Email getEmail() {
        return email;
    }

    public void setEmail(Email email) {
        this.email = email;
    }
}

public class Email {

    private String email;

    public Email(String email) {
        this.email = email;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}</pre>



<p>Java doesn’t know <code>value</code> classes. Spring Data JDBC tries to compensate for this by introducing the concept of an <a href="https://docs.spring.io/spring-data/relational/reference/jdbc/mapping.html#entity-persistence.embedded-entities" target="_blank" rel="noopener">embedded entity</a>.&nbsp;</p>



<p>You define an embedded entity by creating a Java class with a set of properties. In this example, that’s the <code>Email</code> class with its email property. To use the Email class as a property type, you have to annotate it with <code>@Embedded</code>. Spring Data JDBC then applies the same mapping we covered in the example demonstrating Kotlin’s <code>value</code> class. It maps the <code>email</code> field to a database column with the same name, enabling you to use it in all your queries.</p>



<p>So, it looks like you have to write more code and use an embedded entity in Java to get the same result as you got with a simple <code>value</code> class in Kotlin. But it&#8217;s actually worse than that. In Kotlin, you can annotate your simple <code>value</code> classes with <code>@JvmInline</code> and get the previously described optimizations. These don&#8217;t exist in Java. As a result, your embedded class mapping not only requires more code &#8211; it also carries a much greater performance overhead.</p>



<p>Now, let’s get back to our Kotlin-based examples.</p>



<p>Spring Data JDBC maps the value object based on its wrapped value and doesn’t require any additional mapping annotations.</p>



<p>You can even use the <code>value</code> class as a parameter type in your derived or custom queries.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface PersonRepository : CrudRepository&lt;Person, Long> {
    fun findByEmail(email: Email): Person?
}</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">2025-12-09T22:03:49.340+01:00 DEBUG 14665 --- [SDJWithKotlin] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT "person"."id" AS "id", "person"."email" AS "email", "person"."last_name" AS "last_name", "person"."first_name" AS "first_name" FROM "person" WHERE "person"."email" = ?]
2025-12-09T22:03:49.363+01:00  INFO 14665 --- [SDJWithKotlin] [           main] c.t.j.k.s.SpringDataJdbcKotlinTests      : Person(id=401, firstName=Jane, lastName=Smith, email=Email(value=a@b.com))</pre>



<h2 class="wp-block-heading">Modeling one-to-many relationships</h2>



<p>Aggregates can contain collections of child entities. Spring Data JDBC stores each of these entity types in separate tables.&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class Company(
    @Id
    var id: Long,
    val name: String,
    val employees: List&lt;Employee>
)

data class Employee(
    @Id
    var id: Long,
    var name: String
)</pre>



<p>When you read the aggregate, Spring Data JDBC always fetches the entire aggregate with all child entities. And it handles all write operations the same way. When persisting or updating an aggregate, it writes the entire aggregate with all its entities to the database. This fits well with Kotlin’s immutable list types, but requires some attention when defining your aggregates to avoid performance issues.</p>



<h2 class="wp-block-heading">Transactions and practical considerations</h2>



<p>Spring Data JDBC integrates with Spring&#8217;s transaction management. A transactional boundary ensures that all write operations within the aggregate are applied consistently.</p>



<p>Kotlin reduces many typical pitfalls. Properties must be initialized, nullability is clear, and immutable data helps avoid accidental side effects. When updating an aggregate, you create a new instance with the correct state as opposed to modifying an existing one. This results in a predictable and maintainable persistence layer.</p>



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



<p>Spring Data JDBC offers a clear and simple approach to relational persistence. You work with aggregates that are written and read as complete units, and you always know which statements are executed. Kotlin supports this style through immutable data structures, <code>value</code> classes, nullability rules, and concise syntax.</p>



<p>If you design your aggregates carefully and treat each instance as a complete snapshot of its state, you can build applications that remain easy to understand and maintain. The combination of Spring Data JDBC and Kotlin gives you a persistence stack that stays simple even as your application grows.</p>



<p>To learn more about persistence with Kotlin, check out our two previous articles in this series:&nbsp;&nbsp;&nbsp;</p>



<ul>
<li><a href="https://blog.jetbrains.com/idea/2026/01/how-to-avoid-common-pitfalls-with-jpa-and-kotlin/">How to Avoid Common Pitfalls with JPA and Kotlin</a></li>



<li><a href="https://blog.jetbrains.com/idea/2026/03/using-spring-data-jpa-with-kotlin/">Using Spring Data JPA with Kotlin</a></li>
</ul>



<h2 class="wp-block-heading">About the author</h2>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2025/12/Thorben-Janssen-400x400-1.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Thorben Janssen</h4>
                                                <div class="p-client_container">
<div class="p-ia4_client_container">
<div class="p-ia4_client p-ia4_client--sidebar-wide p-ia4_client--with-split-view-feature">
<div class="p-client_workspace_wrapper" role="tabpanel" aria-label="JetBrains">
<div class="p-client_workspace">
<div class="p-client_workspace__layout">
<div class="p-client_workspace__tabpanel" role="tabpanel" aria-label="DMs">
<div class="enabled-managed-focus-container" role="none">
<div>
<div class="p-view_contents p-view_contents--primary" tabindex="-1" role="dialog" aria-label="Conversation with Teodor Irkhin">
<div class="tabbed_channel__Abx5r">
<div class="tabbed_channel__Abx5r">
<div class="channel_tab_panel__zJ5Bt c-tabs__tab_panel c-tabs__tab_panel--active c-tabs__tab_panel--full_height" role="none" data-qa="tabs_content_container">
<div class="p-file_drag_drop__container">
<div class="p-workspace__primary_view_body">
<div class="p-message_pane p-message_pane--classic-nav p-message_pane--scrollbar-float-adjustment p-message_pane--with-bookmarks-bar" data-qa="message_pane">
<div>
<div id="message-list" role="presentation">
<div id="message-list" class="c-virtual_list c-virtual_list--scrollbar c-message_list c-scrollbar c-scrollbar--fade" role="presentation">
<div class="c-scrollbar__hider" role="presentation" data-qa="slack_kit_scrollbar">
<div class="c-scrollbar__child" role="presentation">
<div class="c-virtual_list__scroll_container" role="presentation" data-qa="slack_kit_list">
<div id="message-list_1766072525.327379" class="c-virtual_list__item" tabindex="0" role="listitem" aria-setsize="-1" data-qa="virtual-list-item" data-item-key="1766072525.327379">
<div class="c-message_kit__background c-message_kit__background--hovered p-message_pane_message__message c-message_kit__message" role="presentation" data-qa="message_container" data-qa-unprocessed="false" data-qa-placeholder="false" data-msg-ts="1766072525.327379" data-msg-channel-id="D072Y30UX54">
<div class="c-message_kit__hover c-message_kit__hover--hovered" role="document" aria-roledescription="message" data-qa-hover="true">
<div class="c-message_kit__actions c-message_kit__actions--above">
<div class="c-message_kit__gutter">
<div class="c-message_kit__gutter__right" role="presentation" data-qa="message_content">
<div class="c-message_kit__blocks c-message_kit__blocks--rich_text">
<div class="c-message__message_blocks c-message__message_blocks--rich_text" data-qa="message-text">
<div class="p-block_kit_renderer" data-qa="block-kit-renderer">
<div class="p-block_kit_renderer__block_wrapper p-block_kit_renderer__block_wrapper--first">
<div class="p-rich_text_block" dir="auto">
<p>Thorben Janssen is a consultant and trainer who helps teams build better persistence layers with JPA and Hibernate. An international speaker with more than 20 years of experience in JPA and Hibernate, Thorben is the author of the best-selling book <i data-stringify-type="italic">Hibernate Tips: More than 70 solutions to common Hibernate problems</i>.</p>
<p>He also writes on thorben-janssen.com about various persistence topics, and to help developers improve their skills, he founded the Persistence Hub.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
                    </div>
                            </div>
        </div>
    </div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Java Annotated Monthly – April 2026</title>
		<link>https://blog.jetbrains.com/idea/2026/04/java-annotated-monthly-april-2026/</link>
		
		<dc:creator><![CDATA[Irina Mariasova]]></dc:creator>
		<pubDate>Mon, 06 Apr 2026 11:10:42 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/04/IJ-social-BlogFeatured-1280x720-1.png</featuredImage>		<category><![CDATA[news]]></category>
		<category><![CDATA[ai]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[java-annotated]]></category>
		<category><![CDATA[java-annotated-monthly]]></category>
		<category><![CDATA[kotlin]]></category>
		<category><![CDATA[spring]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=697934</guid>

					<description><![CDATA[It&#8217;s safe to say March was defined by one thing: Java 26. In this issue of Java Annotated Monthly, we&#8217;ve curated a rich selection of articles to help you get the full picture of the release. Marit van Dijk joins us as the featured guest author, bringing her expertise to help you navigate the changes [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>It&#8217;s safe to say March was defined by one thing: Java 26. In this issue of Java Annotated Monthly, we&#8217;ve curated a rich selection of articles to help you get the full picture of the release. <a href="https://maritvandijk.com/" target="_blank" rel="noopener">Marit van Dijk</a> joins us as the featured guest author, bringing her expertise to help you navigate the changes with confidence. Alongside our Java 26 coverage, you&#8217;ll find our regular roundup of AI developments, Spring updates, Kotlin news, industry trends, and community reads that caught our eye.</p>



<h2 class="wp-block-heading">Featured Content</h2>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/1763313006438-1.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Marit van Dijk</h4>
                                                <p>Marit van Dijk is a Java Champion and Developer Advocate at JetBrains with over 20 years of software development experience. She’s passionate about building great software with great people, and making developers’ lives easier.</p>
                    </div>
                            </div>
        </div>
    </div>



<p>Marit regularly presents at international conferences and shares her expertise through webinars, podcasts, blog posts, videos, and tutorials. She’s also a contributor to the book <a href="https://www.oreilly.com/library/view/97-things-every/9781491952689/" target="_blank" rel="noopener"><em>97 Things Every Java Programmer Should Know</em></a> (O’Reilly Media).</p>



<p>March held a lot of interesting things for Java. First of all, there was the Java 26 release on March 17. You can read all about <a href="https://blog.jetbrains.com/idea/2026/03/java-26-in-intellij-idea/">Java 26 in IntelliJ IDEA </a>on the blog, and find more links on Java 26 in the Java sections below.</p>



<p>Also in March, JavaOne took place in Redwood Shores, USA. During the community keynote, our colleague Anton Arhipov talked about <a href="https://www.youtube.com/live/skc-nIFS-hs?t=5171s" target="_blank" rel="noopener">25 years of IntelliJ IDEA</a>. In case you missed it, we also did a <a href="https://dukescorner.libsyn.com/site/marit-van-dijk-and-anton-arhipov-25-years-of-intellij-idea" target="_blank" rel="noopener">Duke’s Corner podcast</a> and a <a href="https://www.youtube.com/watch?v=Bi3wLP5ZCWw" target="_blank" rel="noopener">Foojay podcast </a>on the same topic. And of course, the <a href="https://www.youtube.com/watch?v=Kourq_Lz03U" target="_blank" rel="noopener">IntelliJ IDEA documentary</a> was released this month. Also at JavaOne, we announced that <a href="https://blog.jetbrains.com/ai/2026/03/koog-comes-to-java/">Koog is coming to Java</a>, if you want to try JetBrains’ <a href="https://www.jetbrains.com/koog/" target="_blank" rel="noopener">Koog</a> AI agent with Java instead of Kotlin.</p>



<p>IntelliJ IDEA 2026.1 was just released. Of course we have Java 26 support from day one, as well as improvements to the debugger for virtual threads, support for new Kotlin features, Spring Data and Spring Debugger features, new AI features, and more. You can read all about it on the <a href="https://blog.jetbrains.com/idea/2026/03/intellij-idea-2026-1/">blog</a> or watch our <a href="https://www.youtube.com/watch?v=FVsMsCFtlOs" target="_blank" rel="noopener">release video</a>.</p>



<p>The release of Java 26 also means that Piotr Przybył and I updated our talk, <a href="https://maritvandijk.com/presentations/modern-java-playful/" target="_blank" rel="noopener"><em>Learning modern Java the playful way</em></a>, for Java 26. You can watch the <a href="https://www.youtube.com/watch?v=6jHZpbLH4WU" target="_blank" rel="noopener">recording from Voxxed Days Amsterdam</a>, or catch us at multiple <a href="https://maritvandijk.com/events/" target="_blank" rel="noopener">events</a> around Europe.&nbsp;</p>



<h2 class="wp-block-heading">Java News</h2>



<p>Check out all the Java news highlights in March:&nbsp;</p>



<ul>
<li>Java News Roundup <a href="https://www.infoq.com/news/2026/03/java-news-roundup-mar02-2026/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">1</a>, <a href="https://www.infoq.com/news/2026/03/java-news-roundup-mar09-2026/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">2</a>, <a href="https://www.infoq.com/news/2026/03/java-news-roundup-mar16-2026/" target="_blank" rel="noopener">3</a>, <a href="https://www.infoq.com/news/2026/03/java-news-roundup-mar23-2026/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">4</a>, <a href="https://www.infoq.com/news/2026/04/java-news-roundup-mar30-2026/" target="_blank" rel="noopener">5</a></li>



<li><a href="https://foojay.io/today/java-26-whats-new/" target="_blank" rel="noopener">Java 26: What’s New?</a></li>



<li><a href="https://inside.java/2026/03/04/jdk-26-http-client/" target="_blank" rel="noopener">HTTP Client Updates in Java 26</a></li>



<li><a href="https://inside.java/2026/03/08/jfokus-java-performance-update/" target="_blank" rel="noopener">Java Performance Update: From JDK 21 to JDK 25</a></li>



<li><a href="https://inside.java/2026/03/10/quality-heads-up/" target="_blank" rel="noopener">Quality Outreach Heads-up &#8211; JDK 27: Removal of ‘java.locale.useOldISOCodes’ System Property</a></li>



<li><a href="https://inside.java/2026/03/12/podcast-051/" target="_blank" rel="noopener">Episode 51 “Unboxing Java 26 for Developers”&nbsp;</a></li>



<li><a href="https://nipafx.dev/talk-java-x" target="_blank" rel="noopener">Java 27 &#8211; Better Language, Better APIs, Better Runtime</a></li>



<li><a href="https://foojay.io/today/foojay-podcast-92/" target="_blank" rel="noopener">Foojay Podcast #92: Java 26 Is Here: What’s New, What’s Gone, and Why It Matters in 2026</a></li>



<li><a href="https://inside.java/2026/03/18/jdk-26-in-2-mins/" target="_blank" rel="noopener">Java 26 in definitely UNDER 3 minutes</a></li>



<li><a href="https://inside.java/2026/03/19/jdk26-security-enhancements/" target="_blank" rel="noopener">JDK 26 Security Enhancements</a></li>
</ul>



<h2 class="wp-block-heading">Java Tutorials and Tips</h2>



<p>You can never have too many tips for getting more out of Java:</p>



<ul>
<li><a href="https://inside.java/2026/03/02/jdk-26-rn-ops/" target="_blank" rel="noopener">Java 26 for DevOps</a></li>



<li><a href="https://hanno.codes/2026/03/17/java-26-is-here/" target="_blank" rel="noopener">Java 26 Is Here, And With It a Solid Foundation for the Future</a></li>



<li><a href="https://pvs-studio.com/en/blog/posts/java/1357/" target="_blank" rel="noopener">Closed-world assumption in Java</a></li>



<li><a href="https://foojay.io/today/java-for-scripting/" target="_blank" rel="noopener">JavaScript (No, Not That One): Modern Automation with Java</a></li>



<li><a href="https://mostlynerdless.de/blog/2026/02/13/redacting-sensitive-data-from-java-flight-recorder-files/" target="_blank" rel="noopener">Redacting Sensitive Data from Java Flight Recorder Files</a></li>



<li><a href="https://foojay.io/today/foojay-podcast-91/" target="_blank" rel="noopener">Foojay Podcast #91: 25 Years of IntelliJ IDEA: The IDE That Grew Up With Java</a></li>



<li><a href="https://maritvandijk.com/vulnerable-api-usage/" target="_blank" rel="noopener">Vulnerable API usage: Is your Java code vulnerable?</a></li>



<li><a href="https://mostlynerdless.de/blog/2026/03/17/java-26-is-boring-and-thats-a-good-thing/" target="_blank" rel="noopener">Java 26 is boring, and that’s a good thing</a></li>



<li><a href="https://inside.java/2026/03/06/podcast-049/" target="_blank" rel="noopener">Episode 49 “LazyConstants in JDK 26”&nbsp;</a></li>



<li><a href="https://donraab.medium.com/empty-should-be-empty-c09e21edc205" target="_blank" rel="noopener">Empty Should be Empty</a></li>



<li><a href="https://www.elastic.co/search-labs/blog/elasticsearch-integration-tests" target="_blank" rel="noopener">Testing Elasticsearch. It just got simpler</a></li>



<li><a href="https://spring.io/blog/2026/03/19/a-bootiful-podcast-cay-horstmann" target="_blank" rel="noopener">A Bootiful Podcast: Cay Horstmann, legendary Java professor, author, lecturer</a>&nbsp;</li>



<li><a href="https://inside.java/2026/03/09/podcast-050/" target="_blank" rel="noopener">Episode 50 “Towards Better Checked Exceptions”&nbsp;</a></li>



<li>How is Leyden improving Java Performance? <a href="https://foojay.io/today/122962/" target="_blank" rel="noopener">1,</a> <a href="https://foojay.io/today/how-is-leyden-improving-java-performance-part-2-of-3/" target="_blank" rel="noopener">2</a>, <a href="https://foojay.io/today/how-is-leyden-improving-java-performance-part-3-of-3/" target="_blank" rel="noopener">3</a></li>



<li><a href="https://jvogel.me/posts/2026/java-is-fast-your-code-might-not-be" target="_blank" rel="noopener">Java Is Fast. Your Code Might Not Be.</a></li>



<li><a href="https://openjdk.org/projects/amber/design-notes/beyond-records" target="_blank" rel="noopener">Data Oriented Programming, Beyond Records&nbsp;</a></li>



<li><a href="https://www.selikoff.net/2026/03/18/javaone-2026-evolving-the-java-language-an-inside-perspective/" target="_blank" rel="noopener">Evolving the Java Language: An Inside Perspective</a></li>



<li><a href="https://www.elastic.co/search-labs/blog/langchain4j-elasticsearch-hybrid-search" target="_blank" rel="noopener">Hybrid search with Java: LangChain4j Elasticsearch integration</a></li>



<li><a href="https://www.selikoff.net/2026/03/19/javaone-2026-secure-coding-guidelines-for-java/" target="_blank" rel="noopener">Secure Coding Guidelines for Java</a></li>



<li><a href="https://www.balarawool.me/Vector-API-Pi-Estimator/" target="_blank" rel="noopener">Estimating value of pi (π) using Monte Carlo Simulation and Vector API</a></li>



<li><a href="https://kpavlov.me/blog/javable/" target="_blank" rel="noopener">Javable: generate Java-friendly wrappers for Kotlin with KSP</a></li>
</ul>



<h2 class="wp-block-heading">Kotlin Corner</h2>



<p>Stay sharp with the latest Kotlin news and practical tips:</p>



<ul>
<li><a href="https://blog.jetbrains.com/kotlin/2026/03/kotlin-2-3-20-released/">Kotlin 2.3.20 Released&nbsp;</a></li>



<li><a href="https://blog.jetbrains.com/amper/2026/03/amper-0-10/">Amper 0.10 – JDK Provisioning, a Maven Converter, Custom Compiler Plugins, and More&nbsp;</a></li>



<li>The <a href="http://klibs.io" target="_blank" rel="noopener">klibs.io</a> source repository was <a href="https://github.com/JetBrains/klibs-io" target="_blank" rel="noopener">made public</a>.</li>



<li><a href="https://proandroiddev.com/building-a-deep-research-agent-with-koog-teaching-your-agent-to-think-in-phases-d5681ea7d237" target="_blank" rel="noopener">Building a Deep Research Agent with Koog — Teaching Your Agent to Think in Phases&nbsp;</a></li>



<li><a href="https://blog.jetbrains.com/ai/2026/03/koog-comes-to-java/">Koog Comes to Java: The Enterprise AI Agent Framework From JetBrains</a></li>



<li><a href="https://blog.jetbrains.com/kotlin/2026/03/introducing-tracy-the-ai-observability-library-for-kotlin/">Introducing Tracy: The AI Observability Library for Kotlin&nbsp;</a></li>



<li><a href="https://blog.jetbrains.com/kotlin/2026/03/kotlinconf-26-speakers-in-conversation-with-josh-long/">KotlinConf’26 Speakers: In Conversation with Josh Long</a>&nbsp;</li>
</ul>



<h2 class="wp-block-heading">AI&nbsp;</h2>



<p>Plenty of AI reads this month. Pick what catches your eye:</p>



<ul>
<li><a href="https://inside.java/2026/03/01/jfr-ai-monitor/" target="_blank" rel="noopener">Intelligent JVM Monitoring: Combining JDK Flight Recorder with AI</a></li>



<li><a href="https://jvmskills.com/" target="_blank" rel="noopener">AI coding skills from the engineers who build the JVM ecosystem</a></li>



<li><a href="https://loiane.com/2026/03/vibe-coding-with-specs-driven-feedback-loops/" target="_blank" rel="noopener">Vibe Coding, But Production-Ready: A Specs-Driven Feedback Loop for AI-Assisted Development</a></li>



<li><a href="https://www.infoq.com/presentations/ai-systems-privacy-security/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Busting AI Myths and Embracing Realities in Privacy &amp; Security</a></li>



<li><a href="https://foojay.io/today/shaping-jakarta-agentic-ai-together-watch-the-open-conversation/" target="_blank" rel="noopener">Shaping Jakarta Agentic AI Together – Watch the Open Conversation</a></li>



<li><a href="https://www.selikoff.net/2026/03/05/devnexus-2026-how-i-automated-my-life-with-mcp-servers/" target="_blank" rel="noopener">how i automated my life with mcp servers</a></li>



<li><a href="https://www.selikoff.net/2026/03/05/devnexus-2026-10-things-i-hate-about-ai/" target="_blank" rel="noopener">10 things i hate about ai</a></li>



<li><a href="https://blog.frankel.ch/writing-agent-skill/" target="_blank" rel="noopener">Writing an agent skill</a>&nbsp;</li>



<li><a href="https://www.selikoff.net/2026/03/06/devnexus-2026-hacking-ai-how-to-survive-the-ai-uprising/" target="_blank" rel="noopener">Hacking AI – How to Survive the AI Uprising</a></li>



<li><a href="https://www.selikoff.net/2026/03/06/devnexus-2026-stop-fighting-your-ai-engineering-prompts-that-actually-work/" target="_blank" rel="noopener">Stop Fighting Your AI: Engineering Prompts That Actually Work</a></li>



<li><a href="https://www.infoq.com/presentations/patterns-ai-native-development/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Four Patterns of AI Native Development</a></li>



<li><a href="https://event-driven.io/en/interactive_rubber_ducking_with_gen_ai/" target="_blank" rel="noopener">Interactive Rubber Ducking with GenAI</a>&nbsp;</li>



<li><a href="https://www.infoq.com/articles/oil-water-moment-ai-architecture/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">The Oil and Water Moment in AI Architecture</a></li>



<li><a href="https://www.selikoff.net/2026/03/19/javaone-2026-look-inside-a-large-language-model-to-become-a-better-java-developer/" target="_blank" rel="noopener">Look Inside a Large Language Model to Become a Better Java Developer</a></li>



<li><a href="http://joshondesign.com/2026/03/01/vibecoding_experience" target="_blank" rel="noopener">A Senior Engineer Tries Vibe Coding</a></li>



<li><a href="https://foojay.io/today/how-we-built-a-java-ai-agent-by-connecting-the-dots-the-ecosystem-already-had/" target="_blank" rel="noopener">How We Built a Java AI Agent by Connecting the Dots the Ecosystem Already Had</a>&nbsp;</li>
</ul>



<h2 class="wp-block-heading">Languages, Frameworks, Libraries, and Technologies</h2>



<p>Spring updates and more tech news, all in one place:</p>



<ul>
<li>This Week in Spring <a href="https://spring.io/blog/2026/03/03/this-week-in-spring-march-3rd-2026" target="_blank" rel="noopener">1</a>, <a href="https://spring.io/blog/2026/03/10/this-week-in-spring-march-10th-2026" target="_blank" rel="noopener">2</a>, <a href="https://spring.io/blog/2026/03/17/this-week-in-spring-march-17th-2026" target="_blank" rel="noopener">3</a>, <a href="https://spring.io/blog/2026/03/24/this-week-in-spring-march-24th-2026" target="_blank" rel="noopener">4</a></li>



<li><a href="https://foojay.io/today/data-enrichment-in-mongodb/" target="_blank" rel="noopener">Data Enrichment in MongoDB</a></li>



<li><a href="https://www.youtube.com/watch?v=UqaSWiE076w" target="_blank" rel="noopener">Supercharge your JVM performance with Project Leyden and Spring Boot by Moritz Halbritter</a></li>



<li><a href="https://www.youtube.com/watch?v=D-yp3sB8cu0" target="_blank" rel="noopener">A Typo Led to the Creation of Spring Cloud Contract • Marcin Grzejszczak &amp; Jakub Pilimon • GOTO 2026</a></li>



<li><a href="https://spring.io/blog/2026/03/05/a-bootiful-podcast-jennifer-reif" target="_blank" rel="noopener">A Bootiful Podcast: Neo4j legend Jennifer Reif</a></li>



<li><a href="https://spring.io/blog/2026/03/12/a-bootiful-podcast-soby-chacko" target="_blank" rel="noopener">A Bootiful Podcast: Spring Messaging Legend Soby Chacko</a></li>



<li><a href="https://spring.io/blog/2026/03/18/mcp-apps" target="_blank" rel="noopener">Blending Chat with Rich UIs with Spring AI and MCP Apps</a></li>



<li><a href="https://dzone.com/articles/java-microservicesscs-vs-spring-modulith" target="_blank" rel="noopener">Java Microservices(SCS) vs. Spring Modulith</a></li>



<li><a href="https://spring.io/blog/2026/02/27/moving-beyond-strings-in-spring-data" target="_blank" rel="noopener">Moving beyond Strings in Spring Data</a></li>



<li><a href="https://quarkus.io/blog/new-benchmarks/" target="_blank" rel="noopener">Quarkus has great performance – and we have new evidence</a></li>



<li><a href="https://foojay.io/today/modeling-one-to-many-relationships-in-java-with-mongodb/" target="_blank" rel="noopener">Modeling One-to-Many Relationships in Java with MongoDB</a></li>



<li><a href="https://foojay.io/today/clean-architecture-with-spring-boot-and-mongodb/" target="_blank" rel="noopener">Clean Architecture with Spring Boot and MongoDB</a></li>
</ul>



<h2 class="wp-block-heading">Conferences and Events</h2>



<p>Pick your next events to attend:</p>



<ul>
<li><a href="https://2026.springio.net" target="_blank" rel="noopener">Spring I/O</a> – Barcelona, Spain, April 13–15; Come say hi at the JetBrains booth and join the <a href="https://2026.springio.net/side-events/#community-run" target="_blank" rel="noopener">community run</a>!&nbsp;</li>
</ul>



<figure class="wp-block-image size-full"><a href="https://2026.springio.net/side-events/#community-run" target="_blank" rel="noopener"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/04/image-2.jpeg" alt="" class="wp-image-697935"/></a></figure>



<ul>
<li><a href="https://www.javaday.istanbul" target="_blank" rel="noopener">Java Day Istanbul</a> – Istanbul, Türkiye, April 17–18; <a href="https://www.linkedin.com/in/antonarhipov/" target="_blank" rel="noopener">Anton Arhipov</a> is a speaker.&nbsp;&nbsp;</li>



<li><a href="https://2026.europe.jcon.one" target="_blank" rel="noopener">JCON EUROPE</a> – Cologne, Germany, April 20–23; <a href="https://www.linkedin.com/in/maritvandijk/" target="_blank" rel="noopener">Marit van Dijk</a> will talk about learning modern Java the playful way.</li>



<li><a href="https://developersummit.com" target="_blank" rel="noopener">Great International Developer Summit</a> – Bengaluru, India, April 21–24; Join Siva Katamreddy’s talk on Spring AI + MCP.&nbsp;</li>



<li><a href="https://www.devoxx.fr" target="_blank" rel="noopener">Devoxx France</a> – Paris, France, April 22–24; Check out the talks by <a href="https://www.linkedin.com/in/antonarhipov/" target="_blank" rel="noopener">Anton Arhipov</a> and <a href="https://www.linkedin.com/in/maritvandijk/" target="_blank" rel="noopener">Marit van Dijk</a>.&nbsp;&nbsp;</li>



<li><a href="https://devoxx.gr" target="_blank" rel="noopener">Devoxx Greece</a> – Athens, Greece, April 23–25; <a href="https://www.linkedin.com/in/maritvandijk/" target="_blank" rel="noopener">Marit van Dijk</a> is a speaker.&nbsp;</li>



<li><a href="https://romania.voxxeddays.com/voxxed-days-bucharest-2026/" target="_blank" rel="noopener">Voxxed Days Bucharest</a> – Bucharest, Romania, April 28–29; And if you haven’t caught <a href="https://www.linkedin.com/in/maritvandijk/" target="_blank" rel="noopener">Marit van Dijk</a> during this busy month of hers, here’s the last chance to hear her speak in April.</li>
</ul>



<h2 class="wp-block-heading">Culture and Community</h2>



<p>Your go-to section to slow down and think about the industry, self-growth, and more:</p>



<ul>
<li><a href="https://www.infoq.com/podcasts/mindful-leadership/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Mindful Leadership in the Age of AI</a></li>



<li><a href="http://joshondesign.com/2026/03/19/software-joy" target="_blank" rel="noopener">Can we still make software that sparks joy?</a></li>



<li><a href="https://www.infoq.com/podcasts/hidden-driver-engineering-culture/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Information Flow: The Hidden Driver of Engineering Culture</a></li>



<li><a href="https://www.infoq.com/presentations/cultural-alignment/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Beyond the Code: Hiring for Cultural Alignment</a></li>



<li><a href="https://foojay.io/today/language-learning-flashcard-system-part-1/" target="_blank" rel="noopener">Build a Spaced Repetition Flashcard API with Spring Boot &amp; MongoDB (Part 1)</a></li>



<li><a href="https://www.infoq.com/news/2026/03/mf-aiassisted-dev/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Where Do Humans Fit in AI-Assisted Software Development?</a></li>



<li><a href="https://www.infoq.com/news/2026/03/green-IT-AI-impact/?utm_campaign=infoq_content&amp;utm_source=infoq&amp;utm_medium=feed&amp;utm_term=global" target="_blank" rel="noopener">Green IT: How to Reduce the Impact of AI on the Environment</a></li>



<li><a href="https://foojay.io/today/does-language-still-matter-in-the-age-of-ai-yes-but-the-tradeoff-has-changed/" target="_blank" rel="noopener">Does Language Still Matter in the Age of AI? Yes — But the Tradeoff Has Changed</a></li>



<li><a href="https://www.youtube.com/watch?v=Kourq_Lz03U" target="_blank" rel="noopener">IntelliJ IDEA: The Documentary | An origin story</a>&nbsp;</li>



<li><a href="https://blog.frankel.ch/software-architect-elevator/" target="_blank" rel="noopener">The Software Architect Elevator</a>&nbsp;</li>
</ul>



<h2 class="wp-block-heading">And Finally…</h2>



<p>Top picks from the IntelliJ IDEA blog:</p>



<ul>
<li><a href="https://blog.jetbrains.com/idea/2026/03/whats-fixed-intellij-idea-2026-1/">What’s fixed in IntelliJ IDEA 2026.1</a></li>



<li><a href="https://blog.jetbrains.com/idea/2026/03/java-26-in-intellij-idea/">Java 26 in IntelliJ IDEA</a></li>



<li><a href="https://blog.jetbrains.com/idea/2026/03/intellij-idea-s-new-kotlin-coroutine-inspections-explained/">IntelliJ IDEA’s New Kotlin Coroutine Inspections, Explained</a></li>



<li><a href="https://blog.jetbrains.com/ai/2026/03/cursor-joined-the-acp-registry-and-is-now-live-in-your-jetbrains-ide/">Cursor Joined the ACP Registry and Is Now Live in Your JetBrains IDE</a></li>



<li><a href="https://blog.jetbrains.com/platform/2026/03/sunsetting-code-with-me/">Sunsetting Code With Me</a></li>



<li><a href="https://blog.jetbrains.com/ai/2026/03/koog-comes-to-java/">Koog Comes to Java: The Enterprise AI Agent Framework From JetBrains</a></li>



<li><a href="https://blog.jetbrains.com/idea/2026/03/ai-assisted-java-application-development-with-agent-skills/">AI-Assisted Java Application Development with Agent Skills</a></li>



<li><a href="https://blog.jetbrains.com/idea/2026/03/js-ts-free-support/">Core JavaScript and TypeScript Features Become Free in IntelliJ IDEA</a></li>
</ul>



<p>That’s it for today! We’re always collecting ideas for the next Java Annotated Monthly – send us your suggestions via <a href="https://mail.google.com/mail/u/0/?fs=1&amp;tf=cm&amp;source=mailto&amp;to=JAM@jetbrains.com" target="_blank" rel="noopener">email</a> or <a href="https://x.com/intellijidea?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor" target="_blank">X</a> by April 20. Don’t forget to check out our archive of <a href="https://www.jetbrains.com/lp/jam/" target="_blank" rel="noopener">past JAM issues</a> for any articles you might have missed!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using Spring Data JPA with Kotlin</title>
		<link>https://blog.jetbrains.com/idea/2026/03/using-spring-data-jpa-with-kotlin/</link>
		
		<dc:creator><![CDATA[Teodor Irkhin]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 11:30:47 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/IJ-social-BlogFeatured-1280x720-1-4.png</featuredImage>		<category><![CDATA[kotlin]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=693601</guid>

					<description><![CDATA[This post was written together with&#160;Thorben Janssen, who has more than 20 years of experience with JPA and Hibernate and is the author of “Hibernate Tips: More than 70 Solutions to Common Hibernate Problems” and the JPA newsletter. Spring Data JPA is based on the Jakarta Persistence specification and was originally designed for Java. That [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><em>This post was written together with&nbsp;<a href="https://thorben-janssen.com/" target="_blank" rel="noreferrer noopener">Thorben Janssen</a>, who has more than 20 years of experience with JPA and Hibernate and is the author of “Hibernate Tips: More than 70 Solutions to Common Hibernate Problems” and the JPA newsletter.</em></p>



<p>Spring Data JPA is based on the Jakarta Persistence specification and was originally designed for Java. That often raises the question of whether it is a good fit for Kotlin projects.&nbsp;</p>



<p>The short answer is yes!&nbsp;</p>



<p>You can use Spring Data JPA with Kotlin without any issues and enjoy Kotlin’s compact syntax and language features, like null safety and extension functions, when writing your business code.</p>



<p>And doing all of that is so quick and easy could explained in this short blog post. Let’s use Spring Data JPA with Kotlin to define and use a simple persistence layer.</p>



<h2 class="wp-block-heading"><strong>Required dependencies</strong></h2>



<p>The easiest way to get started is to use the “New Project” wizard in IntelliJ. Once you select Kotlin and Spring Data JPA, the basic setup is done for you. That includes configuring the Kotlin <a href="https://kotlinlang.org/docs/no-arg-plugin.html" target="_blank" rel="noopener">no-arg</a> and <a href="https://kotlinlang.org/docs/all-open-plugin.html#0" target="_blank" rel="noopener">all-open</a> plugins. They ensure that your Kotlin classes fulfill Jakarta Persistence’s requirements for non-final classes and parameterless constructors. You also get the kotlin-reflect dependency, which is required by Spring.</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image2-5.png" alt="" class="wp-image-693635"/></figure>



<p>On the next page, you can select the Spring Boot Starter modules and other dependencies you want to use. In this example, that’s Spring Data JPA and the PostgreSQL database driver.</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image1-7.png" alt="" class="wp-image-693646"/></figure>



<h3 class="wp-block-heading">Adding Kotlin to an existing project</h3>



<p>If you already have a Java-based Spring Boot project with the required dependencies, you can simply add a Kotlin class to it. Starting with version 2026.1 Intellij IDEA automatically adds the plugins plugin.spring and plugin.jpa to your build configuration and configure the all-open plugin.</p>



<p>In case you’re using an older IDEA version, you have to add the following configuration yourself.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">plugins {
   kotlin("plugin.spring") version "2.2.20"
   kotlin("plugin.jpa") version "2.2.20"
}

allOpen {
   annotation("jakarta.persistence.Entity")
   annotation("jakarta.persistence.MappedSuperclass")
   annotation("jakarta.persistence.Embeddable")
}</pre>



<h3 class="wp-block-heading">Database and logging configuration</h3>



<p>After defining your project’s dependencies, you need to set up the database connection in your application.properties file, and you can provide your preferred logging configuration.&nbsp;</p>



<p>The following settings connect to a local PostgreSQL database and activate detailed Hibernate logging. The logging configuration instructs Hibernate to log the executed SQL statements and all bind parameter values. This information is extremely helpful during development and debugging, but it generates a lot of output. So, please make sure to use a different logging configuration in production.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">spring.datasource.url=jdbc:postgresql://localhost:5432/postgres

spring.datasource.username=postgres
spring.datasource.password=postgres

logging.level.root=INFO
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.orm.jdbc.bind=TRACE</pre>



<h2 class="wp-block-heading">Modelling entities</h2>



<p>You can then start modeling your entities in Kotlin. The Jakarta Persistence specification defines a few requirements for entity classes. As we explained in a <a href="https://blog.jetbrains.com/idea/2026/01/how-to-avoid-common-pitfalls-with-jpa-and-kotlin/">recent article on common best practices</a>, some of these requirements don’t align well with Kotlin’s data classes. But you will not run into any issues and enjoy Kotlin’s concise syntax if you define your entity classes as regular Kotlin classes and annotate the fields you want to persist.</p>



<p>It’s a general best practice to avoid exposing your entity classes and their technical dependencies in your API. Most teams introduce a second non-entity representation of their data for that. Using Kotlin, you can easily model those classes as a data class. Doing that requires additional mapping code to convert your data between the different formats. You could, of course, do that in your business code. But it’s much more comfortable to add a set of converter functions to your entity class or select the data class directly from the database. You will see an example of the second approach later in this article. Let’s concentrate on the entity class for now.</p>



<p>Here is a simple Person entity. It maps the person’s first and last name, along with a many-to-one relationship to the company they work for.&nbsp;</p>



<p>The PersonData class represents the same information. You can use it in your API without exposing any technical details of your persistence layer. To make using this class as comfortable as possible, the Person entity class provides 2 functions with the required mapping code.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Entity
class Person(
    @Id
    @GeneratedValue
    var id: Long? = null,

    var firstName: String? = null,

    var lastName: String? = null,

    @ManyToOne(fetch = FetchType.LAZY)
    var company: Company? = null,

    @Version
    var version: Integer? = null
) {
    fun createPersonData(): PersonData {
        return PersonData(
            id = id!!,
            firstName = firstName ?: "",
            lastName = lastName ?: "",
            version = version
        )
    }

    companion object {
        fun createPersonFromData(data: PersonData): Person {
            return Person(
                id = data.id,
                firstName = data.firstName,
                lastName = data.lastName,
                version = data.version
            )
        }
    }
}

data class PersonData(
    val id: Long,
    val firstName: String,
    val lastName: String,
    val version: Int
)</pre>



<p>The functions&nbsp;</p>



<p>The Company entity follows the same approach:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Entity
class Company(
    @Id
    @GeneratedValue
    var id: Long? = null,

    var name: String = "default",

    @Version
    var version: Integer? = null
)</pre>



<p>After you modeled your entity classes, you can start defining your repositories.</p>



<h2 class="wp-block-heading">Designing and using a repository</h2>



<p>Spring Data JPA’s repository abstraction works the same way in Kotlin as it does in Java. You extend one of the provided repository interfaces, such as JpaRepository or CrudRepository, and Spring Data provides you with an implementation.&nbsp;</p>



<p>These repositories define a set of standard methods for fetching entities by primary key, persisting new entities, and removing existing ones. They also integrate with Spring’s transaction handling, so that you can use the <a href="https://www.marcobehler.com/guides/spring-transaction-management-transactional-in-depth" target="_blank" rel="noopener">@Transactional annotation</a> on your business or API layer to define the transaction handling.</p>



<p>Here is an example of a simple PersonRepository definition. It inherits all standard methods defined by the JpaRepository. Let’s see how to add your own query methods in one of the following examples.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface PersonRepository : JpaRepository&lt;Person, Long> {}</pre>



<p>To make it even easier, IntelliJ IDEA can create the repository for you automatically. Just start typing repository name in the service and IDEA will suggest creating it:</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-47.png" alt="" class="wp-image-693607"/></figure>



<p>With this repository in place, you can focus on your business logic. That’s especially convenient in Kotlin because constructor injection and concise function definitions keep your classes short and focused.&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Component
@Transactional
class PersonController (
   private val personRepository: PersonRepository) {
   fun createNewPerson(person : Person): Person {
       // add additional validations and/or logic ...
       return personRepository.save(person)
   }
}</pre>



<p>In this example, Spring injects a PersonRepository instance and joins an active transaction or starts a new one before entering the createNewPerson method. If it started a new transaction, it also commits it after completing this method call. And the PersonRepository, together with the Jakarta Persistence implementation, provides the required code to create and execute a SQL INSERT statement that stores the provided Person object in the database.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">2025-11-16T16:02:53.988+01:00 DEBUG 10104 --- [SDJWithKotlin] [           main] org.hibernate.SQL                        : select next value for person_seq
2025-11-16T16:02:54.012+01:00 DEBUG 10104 --- [SDJWithKotlin] [           main] org.hibernate.SQL                        : insert into person (company_id,first_name,last_name,version,id) values (?,?,?,?,?)
2025-11-16T16:02:54.014+01:00 TRACE 10104 --- [SDJWithKotlin] [           main] org.hibernate.orm.jdbc.bind              : binding parameter (1:BIGINT) &lt;- [null]
2025-11-16T16:02:54.014+01:00 TRACE 10104 --- [SDJWithKotlin] [           main] org.hibernate.orm.jdbc.bind              : binding parameter (2:VARCHAR) &lt;- [John]
2025-11-16T16:02:54.014+01:00 TRACE 10104 --- [SDJWithKotlin] [           main] org.hibernate.orm.jdbc.bind              : binding parameter (3:VARCHAR) &lt;- [Doe]
2025-11-16T16:02:54.014+01:00 TRACE 10104 --- [SDJWithKotlin] [           main] org.hibernate.orm.jdbc.bind              : binding parameter (4:INTEGER) &lt;- [0]
2025-11-16T16:02:54.015+01:00 TRACE 10104 --- [SDJWithKotlin] [           main] org.hibernate.orm.jdbc.bind              : binding parameter (5:BIGINT) &lt;- [2]
</pre>



<p>You might know all of this from using Spring Data JPA with Java. Kotlin does not change any of this behavior, and you also get all the benefits from using Kotlin when implementing your business logic.</p>



<p>Let’s take a look at another example.</p>



<p>Fetching and updating an existing entity follows the same pattern. The updateLastName function loads the entity by its primary key and changes the lastName. That’s all you have to do. The Jakarta Persistence implementation finds that modification during its next <a href="https://www.baeldung.com/java-hibernate-entity-dirty-check" target="_blank" rel="noopener">dirty check</a> and updates the database automatically.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Component
@Transactional
class PersonController (
   private val personRepository: PersonRepository) {
   fun updateLastName(id : Long, lastName : String): Person {
       var person = personRepository.findById(id).orElseThrow()
       person.lastName = lastName
       return person
   }
}</pre>



<p>As you can see, Kotlin’s concise syntax helps keep the business logic easy to read, and Spring handles all the boilerplate code for you. That makes implementing your application very comfortable.</p>



<h2 class="wp-block-heading">Adding your own queries</h2>



<p>In addition to the standard methods provided by Spring Data JPA’s repositories, you need to define queries that fetch the data used in your business code. You can do that in 2 ways, both of which work fine with Kotlin.&nbsp;</p>



<p>The first and most convenient option is to use <a href="https://docs.spring.io/spring-data/jpa/reference/jpa/query-methods.html" target="_blank" rel="noopener">derived query methods</a>. Spring analyzes the method name, derives the corresponding JPQL query, and binds the method parameter values. This is a good choice when your query is simple and only requires one or two bind parameters.</p>



<p>You can add a derived query method directly to your repository. Or In IDEA, you can start typing a desired method name and use autocompletion to have it automatically added to your repository.</p>



<p>You can see a typical example in the following code snippet. The findByLastName method fetches all Person entities with a lastName equal to the provided one.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface PersonRepository : JpaRepository&lt;Person, Long> {
   fun findByLastName(lastName: String): List&lt;Person>
}</pre>



<p>If your query becomes more complex, you should instead annotate your repository method with a <a href="https://thorben-janssen.com/spring-data-jpa-query-annotation/" target="_blank" rel="noopener">@Query annotation</a>. That allows you to write your own <a href="https://thorben-janssen.com/jpql/" target="_blank" rel="noopener">JPQL query</a> and gives you full control over the executed statement. You can use joins, grouping, or any other JPQL feature you need.</p>



<p>Here you can see the same query statement as in the previous example. But this time, using a <code>@Query</code> annotation instead of Spring Data’s derived query feature.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface PersonRepository : JpaRepository&lt;Person, Long> {
   @Query("select p from Person p where p.lastName = :lastName")
   fun getByLastName(lastName: String): List&lt;Person>
}</pre>



<p>When you call one of these methods, Spring Data JPA uses Jakarta Persistence’s EntityManager to instantiate a Query, set the provided bind parameters, execute the query, and map the result to a managed Person entity object.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">2025-11-16T16:47:20.949+01:00 DEBUG 16193 --- [SDJWithKotlin] [           main] 
org.hibernate.SQL                        : select 
p1_0.id,p1_0.company_id,p1_0.first_name,p1_0.last_name,p1_0.version from person p1_0 
where p1_0.last_name=?
2025-11-16T16:47:20.952+01:00 TRACE 16193 --- [SDJWithKotlin] [           main]
org.hibernate.orm.jdbc.bind              : binding parameter (1:VARCHAR) &lt;- [Doe]
</pre>



<p>But entities are not the only projection you can use. For many use cases, a read-only DTO projection that only fetches the required information is more efficient. And Kotlin’s <a href="https://kotlinlang.org/docs/data-classes.html" target="_blank" rel="noopener">data classes</a> are a great way to model such a DTO.</p>



<p>If you only want to show the first and last names of multiple people along with the company they work for, you could use the following <code>PersonWithCompany</code> data class.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class PersonWithCompany(
    val firstName: String,
    val lastName: String,
    val company: String
)</pre>



<p>In the next step, you can define a repository method that returns a <code>List</code> of those objects. If you annotate that method with a <code>@Query</code> annotation and provide a JPQL query that returns 3 fields with matching names, Spring Data JPA automatically maps each record to a <code>PersonWithCompany</code> object.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface PersonRepository : JpaRepository&lt;Person, Long> {
   @Query("select p.firstName, p.lastName, c.name as company from Person p join p.company c")
   fun findPersonsWithCompany(): List&lt;PersonWithCompany>
}</pre>



<p>As you can see in the log output, using a data class as your query projection combines the convenience of Kotlin data classes in your business code with the performance benefits of fetching only the required information from the database.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">2025-11-16T16:59:42.260+01:00 DEBUG 22541 --- [SDJWithKotlin] [           main]
org.hibernate.SQL                        : select p1_0.first_name,p1_0.last_name,c1_0.name from 
person p1_0 join company c1_0 on c1_0.id=p1_0.company_id
2025-11-16T16:59:42.278+01:00  INFO 22541 --- [SDJWithKotlin] [           main] c.t.j.k.s.SDJWithKotlinApplicationTests  : PersonWithCompany(firstName=Jane,
lastName=Doe, company=Mighty Business Corp)</pre>



<h2 class="wp-block-heading"><strong>Provide your own repository method implementations</strong></h2>



<p>If you need more flexibility than Spring Data JPA’s <code>@Query</code> annotation provides, you can also add your own method implementations to a repository. You do that by creating an interface that defines only the methods you want to implement, letting your repository extend that interface, and providing an implementation of that interface. This is called a fragment repository.</p>



<p>In this example, the <code>PersonFragmentRepository</code> defines the searchPerson method that expects a <code>PersonSearchInput</code> parameter.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface PersonFragmentRepository {
   fun searchPerson(searchBy : PersonSearchInput): List&lt;Person?>?
}

data class PersonSearchInput(
   val firstName : String?,
   val lastName : String?,
   val worksForCompany : String?
) {}</pre>



<p>In the next step, you have to implement the <code>PersonFragmentRepository</code>. The name of your class should be the interface name with the postfix <code>Impl</code>. Spring Data then automatically detects this class, wires it into your repository, and delegates all calls to the searchPerson method to your class.</p>



<p>The goal of the following searchPerson implementation is to check which fields of the PersonSearchInput object are set and consider only those fields in the query’s WHERE clause. This is a typical implementation for complex search dialogs, where users can choose which information to search for.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">override fun searchPerson(searchBy: PersonSearchInput): List&lt;Person?>? {
    val cBuilder = em.criteriaBuilder
    val cQuery = cBuilder.createQuery(Person::class.java)
    val person = cQuery.from(Person::class.java)
    val wherePredicates = mutableListOf&lt;Predicate>()

    searchBy.firstName?.let {
        wherePredicates.add(cBuilder.equal(person.get&lt;String>("firstName"), searchBy.firstName))
    }
    searchBy.lastName?.let {
        wherePredicates.add(cBuilder.equal(person.get&lt;String>("lastName"), searchBy.lastName))
    }
    searchBy.worksForCompany?.let {
        val company = person.join&lt;Person, Company>("company")
        wherePredicates.add(cBuilder.equal(company.get&lt;String>("name"), searchBy.worksForCompany))
    }

    cQuery.where(*wherePredicates.toTypedArray())
    return em.createQuery(cQuery).resultList
}</pre>



<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></p>



<p>As you can see in the code snippet, the searchPerson method uses Jakarta Persistence’s Criteria API to define a query based on the fields set on the provided PersonSearchInput object.</p>



<p>It first gets a <code>CriteriaBuilder</code> and uses it to create a <code>CriteriaQuery</code> that returns <code>Person</code> objects. It then defines the <code>FROM</code> clause and creates a <code>List of Predicates</code>. For each field of the <code>PersonSearchInput</code> object that’s not null, an equal predicate gets added to the <code>wherePredicates List</code>.</p>



<p>Thanks to Kotlin’s concise syntax and null handling, defining those <code>Predicates</code> is straightforward. Only the handling of the company name requires a little attention. If that field is set, you have to add a join to the <code>Company</code> entity before you can define the equal predicate.</p>



<p>You can then use the <code>wherePredicates</code> <code>List</code> to define the <code>WHERE</code> clause, execute the query, and return the result.</p>



<p>After you define the <code>PersonFragmentRepository</code> and implement it, you can use it in your repository definition. Let’s add it to the <code>PersonRepository</code>, which you already know from previous examples. It now extends Spring Data JPA’s JpaRepository and the <code>PersonFragmentRepository</code>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface PersonRepository : JpaRepository&lt;Person, Long>, PersonFragmentRepository {
    fun findByLastName(lastName: String): List&lt;Person>

    @Query("select p from Person p where p.lastName = :lastName")
    fun getByLastName(lastName: String): List&lt;Person>

    @Query("select p.firstName, p.lastName, c.name as company from Person p join p.company c")
    fun findPersonsWithCompany(): List&lt;PersonWithCompany>
}</pre>



<p>When you use this <code>PersonRepository</code> in your business code, Spring Data JPA provides the implementations of all methods defined by the <code>JpaRepository</code>. It also generates the implementations of the 3 query methods. Only the calls to the <code>searchPerson</code> method get delegated to your <code>PersonFragmentRepositoryImpl</code> class.</p>



<h2 class="wp-block-heading"><strong>Summary&nbsp;</strong></h2>



<p>As you’ve seen in this article, Kotlin works well with Spring Data JPA. You can model your entities and define repositories in the same way you would in a Java application. Kotlin’s concise syntax often makes these parts of your code easier to read and maintain without changing any persistence behavior. If you follow the established <a href="https://blog.jetbrains.com/idea/2026/01/how-to-avoid-common-pitfalls-with-jpa-and-kotlin/">Jakarta Persistence best practices for Kotlin</a>, you get a smooth development experience and an efficient persistence layer.</p>



<p>To learn more about persistence with Kotlin, check out two other articles in this series:  </p>



<ul>
<li><a href="https://blog.jetbrains.com/idea/2026/01/how-to-avoid-common-pitfalls-with-jpa-and-kotlin/">How to Avoid Common Pitfalls with JPA and Kotlin</a></li>



<li><a href="https://blog.jetbrains.com/idea/2026/04/using-spring-data-jdbc-with-kotlin/" data-type="link" data-id="https://blog.jetbrains.com/idea/2026/04/using-spring-data-jdbc-with-kotlin/">Using Spring Data JDBC With Kotlin</a></li>
</ul>



<h2 class="wp-block-heading">About the author</h2>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2025/12/Thorben-Janssen-400x400-1.jpg" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Thorben Janssen</h4>
                                                <div class="p-client_container">
<div class="p-ia4_client_container">
<div class="p-ia4_client p-ia4_client--sidebar-wide p-ia4_client--with-split-view-feature">
<div class="p-client_workspace_wrapper" role="tabpanel" aria-label="JetBrains">
<div class="p-client_workspace">
<div class="p-client_workspace__layout">
<div class="p-client_workspace__tabpanel" role="tabpanel" aria-label="DMs">
<div class="enabled-managed-focus-container" role="none">
<div>
<div class="p-view_contents p-view_contents--primary" tabindex="-1" role="dialog" aria-label="Conversation with Teodor Irkhin">
<div class="tabbed_channel__Abx5r">
<div class="tabbed_channel__Abx5r">
<div class="channel_tab_panel__zJ5Bt c-tabs__tab_panel c-tabs__tab_panel--active c-tabs__tab_panel--full_height" role="none" data-qa="tabs_content_container">
<div class="p-file_drag_drop__container">
<div class="p-workspace__primary_view_body">
<div class="p-message_pane p-message_pane--classic-nav p-message_pane--scrollbar-float-adjustment p-message_pane--with-bookmarks-bar" data-qa="message_pane">
<div>
<div id="message-list" role="presentation">
<div id="message-list" class="c-virtual_list c-virtual_list--scrollbar c-message_list c-scrollbar c-scrollbar--fade" role="presentation">
<div class="c-scrollbar__hider" role="presentation" data-qa="slack_kit_scrollbar">
<div class="c-scrollbar__child" role="presentation">
<div class="c-virtual_list__scroll_container" role="presentation" data-qa="slack_kit_list">
<div id="message-list_1766072525.327379" class="c-virtual_list__item" tabindex="0" role="listitem" aria-setsize="-1" data-qa="virtual-list-item" data-item-key="1766072525.327379">
<div class="c-message_kit__background c-message_kit__background--hovered p-message_pane_message__message c-message_kit__message" role="presentation" data-qa="message_container" data-qa-unprocessed="false" data-qa-placeholder="false" data-msg-ts="1766072525.327379" data-msg-channel-id="D072Y30UX54">
<div class="c-message_kit__hover c-message_kit__hover--hovered" role="document" aria-roledescription="message" data-qa-hover="true">
<div class="c-message_kit__actions c-message_kit__actions--above">
<div class="c-message_kit__gutter">
<div class="c-message_kit__gutter__right" role="presentation" data-qa="message_content">
<div class="c-message_kit__blocks c-message_kit__blocks--rich_text">
<div class="c-message__message_blocks c-message__message_blocks--rich_text" data-qa="message-text">
<div class="p-block_kit_renderer" data-qa="block-kit-renderer">
<div class="p-block_kit_renderer__block_wrapper p-block_kit_renderer__block_wrapper--first">
<div class="p-rich_text_block" dir="auto">
<p>Thorben Janssen is a consultant and trainer who helps teams build better persistence layers with JPA and Hibernate. An international speaker with more than 20 years of experience in JPA and Hibernate, Thorben is the author of the best-selling book <i data-stringify-type="italic">Hibernate Tips: More than 70 solutions to common Hibernate problems</i>.</p>
<p>He also writes on thorben-janssen.com about various persistence topics, and to help developers improve their skills, he founded the Persistence Hub.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
                    </div>
                            </div>
        </div>
    </div>
]]></content:encoded>
					
		
		
		                    <language>
                        <code><![CDATA[zh-hans]]></code>
                        <url>https://blog.jetbrains.com/zh-hans/idea/2026/03/using-spring-data-jpa-with-kotlin/</url>
                    </language>
                	</item>
		<item>
		<title>AI-Assisted Java Application Development with Agent Skills</title>
		<link>https://blog.jetbrains.com/idea/2026/03/ai-assisted-java-application-development-with-agent-skills/</link>
		
		<dc:creator><![CDATA[Siva Katamreddy]]></dc:creator>
		<pubDate>Thu, 26 Mar 2026 13:21:10 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/IJ-social-BlogFeatured-1280x720-1-3.png</featuredImage>		<category><![CDATA[ai]]></category>
		<category><![CDATA[idea]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jetbrains-ai]]></category>
		<category><![CDATA[ai-agents]]></category>
		<category><![CDATA[claude-agent]]></category>
		<category><![CDATA[junie]]></category>
		<category><![CDATA[spring-boot]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=692555</guid>

					<description><![CDATA[Agent-assisted development is quickly becoming a common mode of software development. New techniques are emerging to help LLMs generate code that matches your preferences and standards. One common approach is to create an AGENTS.md, CLAUDE.md, or GEMINI.md file with project details, build instructions, and coding guidelines. The AI agent loads this file into context on [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Agent-assisted development is quickly becoming a common mode of software development. New techniques are emerging to help LLMs generate code that matches your preferences and standards.</p>



<p>One common approach is to create an <strong>AGENTS.md</strong>, <strong>CLAUDE.md</strong>, or <strong>GEMINI.md</strong> file with project details, build instructions, and coding guidelines. The AI agent loads this file into context on every request.</p>



<p>This has two drawbacks:</p>



<ul>
<li>It consumes tokens on every request, increasing cost.</li>



<li>Loading too much context into an LLM degrades its effectiveness.</li>
</ul>



<p><br><a href="https://agentskills.io/" target="_blank" rel="noopener">Agent Skills</a> is a new initiative that solves both problems by managing context progressively and extending AI agent capabilities on demand.</p>



<h2 class="wp-block-heading">What are Agent Skills?</h2>



<p>Agent Skills is an open standard introduced by Anthropic, to extend AI agent capabilities with specialized knowledge and workflows.</p>



<p>Consider a use case where you want an AI to generate presentations using your company&#8217;s slide template and design guidelines. You can package those assets (the PPT template, font files, and design rules) into a <em>skill</em>. The agent then uses that skill to generate slides that match your standards automatically.</p>



<p>A skill is a folder containing a <strong>SKILL.md</strong> file. This file includes metadata (<code>name</code> and <code>description</code> at minimum) and instructions that tell an agent how to perform a specific task. Skills can also bundle scripts, templates, and reference materials.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">skill-name/
├── SKILL.md          # Required: instructions + metadata
├── scripts/          # Optional: executable code
├── references/       # Optional: documentation
└── assets/           # Optional: templates, resources</pre>



<p>The format of a <strong>SKILL.md</strong> file is:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">---
name: name-of-the-skill
description: Skill description.
license: Apache-2.0
metadata:
  author: author/org
  version: "1.0"
compatibility: Requires git, docker, jq, and access to the internet
---

Skill Content</pre>



<p>In a <code>SKILL.md</code> file, <code>name</code> and <code>description</code> are required fields, and you can add optional fields like <code>licence</code>, <code>metadata</code>, <code>compatibility</code>, etc. You can explore more about the Skill Specification <a href="https://agentskills.io/specification" target="_blank" rel="noopener">here</a>.</p>



<h2 class="wp-block-heading">How do Agent Skills manage context?</h2>



<p>At startup, agents load only the metadata (name and description) of installed skills. When you ask the agent to perform a task, it finds the relevant skill and loads only that <strong>SKILL.md</strong> into context.</p>



<p>This progressive loading keeps context minimal and pulls in additional information only when needed, unlike a monolithic <strong>CLAUDE.md</strong> that loads everything upfront.</p>



<h2 class="wp-block-heading">What can be a skill?</h2>



<p>Skills extend AI capabilities across a wide range: from coding guidelines for a specific library, to step-by-step workflows with reference documents and helper scripts.</p>



<p>For example, you can create a skill that:</p>



<ul>
<li>Specifies which library APIs to use and which anti-patterns to avoid.</li>



<li>Bundles reference documentation in a <code>references/</code> directory.</li>



<li>Includes helper scripts in a <code>scripts/</code> directory.</li>
</ul>



<h2 class="wp-block-heading">Case Study: Implementing Spring Data JPA Pagination</h2>



<p>Suppose you ask an AI agent to implement a Spring Boot REST API endpoint that returns a paginated list of <code>Post</code> entities along with their <code>Comment</code> collections.</p>



<p>Without guidance, the agent is likely to produce one of these common mistakes:</p>



<ul>
<li><strong>N+1 SELECT problem</strong> — lazy-loading comments trigger a separate query per post.</li>



<li><strong>In-memory pagination</strong> — using <code>JOIN FETCH</code> with pagination loads all rows into memory, then paginates in the application layer.</li>
</ul>



<p><br>You can check out the sample code from the GitHub repository <a href="https://github.com/sivaprasadreddy/agent-skills-demo" target="_blank" rel="noopener">https://github.com/sivaprasadreddy/agent-skills-demo</a>&nbsp;</p>



<p>Let us see how an AI Agent might generate code when asked to implement a REST API endpoint to return paginated posts along with comments.</p>



<figure class="wp-block-video"><video controls src="https://blog.jetbrains.com/wp-content/uploads/2026/03/AIA-Junie-without-Skills.webm"></video></figure>



<p>Without any specific guidelines or skills, the AI Agent generated the following implementation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@RestController
@RequestMapping("/api/posts")
class PostController {
   private final PostService postService;

   PostController(PostService postService) {
       this.postService = postService;
   }

   @GetMapping
   PagedResult&lt;PostDto> getPosts(
           @RequestParam(name = "page", defaultValue = "1") int pageNo,
           @RequestParam(name = "size", defaultValue = "10") int pageSize) {
       return postService.getPosts(pageNo, pageSize);
   }

}


@Service
@Transactional(readOnly = true)
public class PostService {
   private final PostRepository postRepository;

   public PostService(PostRepository postRepository) {
       this.postRepository = postRepository;
   }

   public PagedResult&lt;PostDto> getPosts(int pageNo, int pageSize) {
       Sort sort = Sort.by(Sort.Direction.ASC, "id");
       Pageable pageable = PageRequest.of(pageNo &lt;= 0 ? 0 : pageNo - 1, pageSize, sort);
       Page&lt;PostDto> postPage = postRepository.findAllWithComments(pageable).map(PostDto::from);
       return PagedResult.from(postPage);
   }

}</pre>



<p>If you run the application and invoke the <code>GET /api/posts</code> endpoint, you will get the results, but in the logs you will find the below <strong>WARNING</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">HHH000104: firstResult/maxResults specified with collection fetch; applying in memory</pre>



<p>This essentially means, Hibernate will load all the entities into memory and then apply pagination. This will result in poor performance and even OutOfMemory exceptions if there are a large number of rows in the <code>posts</code> table.</p>



<p>A Spring Data JPA skill prevents both issues by giving the agent explicit guidelines and a working code example.</p>



<h2 class="wp-block-heading">Spring Data JPA Agent Skill</h2>



<p>Create a <code>spring-data-jpa/SKILL.md</code> file with the following content:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">---
name: spring-data-jpa-skill
description: Implement the persistence layer using Spring Data JPA in Spring Boot applications.
---

Follow the below principles when using Spring Data JPA:

1. Disable the Open Session in View (OSIV) filter: 
spring.jpa.open-in-view=false
2. Disable in-memory pagination: 
spring.jpa.properties.hibernate.query.fail_on_pagination_over_collection_fetch=true

3. Avoid the N+1 SELECT problem: use JOIN FETCH to load associated child collections in a single query.
4. Avoid in-memory pagination: when loading a paginated list of parent entities with child collections:
	* First, load only the parent IDs using pagination
	* Then, load the full entities with their child collections using JOIN FETCH for those IDs
	* Assemble the final Page from the paginated IDs and the loaded entities


## Pagination with child collections example:

PostRepository.java

public interface PostRepository extends JpaRepository&lt;Post, Long> {

   @Query("select p.id from Post p order by p.id")
   Page&lt;Long> findPostIds(Pageable pageable);

   @Query("select distinct p from Post p left join fetch p.comments where p.id in :ids")
   List&lt;Post> findAllByIdInWithComments(@Param("ids") Collection&lt;Long> ids);
}


PostService.java

@Service
public class PostService {
   private final PostRepository postRepository;

   public PostService(PostRepository postRepository) {
       this.postRepository = postRepository;
   }

   @Transactional(readOnly = true)
   public Page&lt;Post> findPosts(Pageable pageable) {
       Page&lt;Long> idsPage = postRepository.findPostIds(pageable);
       if (idsPage.isEmpty()) {
           return Page.empty(pageable);
       }
       List&lt;Post> posts = postRepository.findAllByIdInWithComments(idsPage.getContent());
       return new PageImpl&lt;>(posts, pageable, idsPage.getTotalElements());
   }
}</pre>



<h2 class="wp-block-heading">How to use Agent Skills?</h2>



<p>Agent Skills work with Claude Code, Codex, Gemini CLI, JetBrains Junie, and other agents. Install a skill at the project level or user level depending on your preference.</p>



<figure class="wp-block-table"><table><tbody><tr><td>Agent</td><td>Project-Level</td><td>User-Level</td></tr><tr><td>Junie</td><td><code>.junie/skills/</code></td><td><code>~/.junie/skills/</code></td></tr><tr><td>Claude Code</td><td><code>.claude/skills/</code></td><td><code>~/.claude/skills/</code></td></tr><tr><td>Codex</td><td><code>.agents/skills/</code></td><td><code>~/.agents/skills/</code></td></tr><tr><td>Gemini CLI</td><td><code>.gemini/skills/</code>(or)<code>.agents/skills/</code></td><td><code>~/.gemini/skills/</code>(or)<code>~/.agents/skills/</code></td></tr></tbody></table><figcaption class="wp-element-caption"><br></figcaption></figure>



<p>To use the Spring Data JPA skill with Claude Code:</p>



<ol>
<li>Copy the <code>spring-data-jpa/</code> directory into <code>{project-root}/.claude/skills/</code>.</li>



<li>Ask Claude Code to implement a paginated REST API endpoint.</li>



<li>Claude Code discovers the skill automatically and follows the guidelines.</li>
</ol>



<figure class="wp-block-video"><video controls src="https://blog.jetbrains.com/wp-content/uploads/2026/03/Agent-Skills-with-Claude-demo.webm"></video></figure>



<p>As you can see, Claude Code automatically discovered the Spring Data JPA skill and generated the following implementation following the guidelines given in the skill.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Service
public class PostService {
   private final PostRepository postRepository;

   public PostService(PostRepository postRepository) {
       this.postRepository = postRepository;
   }

   @Transactional(readOnly = true)
   public Page&lt;Post> findPosts(Pageable pageable) {
       Page&lt;Long> idPage = postRepository.findPostIds(pageable);
       if (idPage.isEmpty()) {
           return Page.empty(pageable);
       }
       List&lt;Post> posts = postRepository.findAllByIdInWithComments(idPage.getContent());
       return new PageImpl&lt;>(posts, pageable, idPage.getTotalElements());
   }
}</pre>



<p>With this implementation, only the Post IDs of the desired page will be loaded first, and then a list of posts along with their comments will be fetched in a separate query. This will fix the pagination in-memory issue.</p>



<h2 class="wp-block-heading">Using Agent Skills with Junie</h2>



<p>You can use the <a href="https://junie.jetbrains.com/" data-type="link" data-id="https://junie.jetbrains.com/" target="_blank" rel="noopener">JetBrains Junie</a> Agent to generate code which automatically loads the necessary skills from <code>.junie/skills</code>&nbsp; and directory.</p>



<figure class="wp-block-video"><video controls src="https://blog.jetbrains.com/wp-content/uploads/2026/03/AIA-Junie-Skills.webm"></video></figure>



<p>The Junie agent loaded <code>spring-data-jpa</code> skill based on the given task and applied the guidelines. You can also observe that Junie automatically runs the relevant tests to verify the generated code is working or not and iterate until the tests are passed.</p>



<p>In the sample repository <a href="https://github.com/sivaprasadreddy/agent-skills-demo" target="_blank" rel="noopener">https://github.com/sivaprasadreddy/agent-skills-demo</a>, you can find the following branches to try out the spring-data-jpa Agent Skill:</p>



<ul>
<li><code>main</code>: Starting point to try implementing the mentioned usecase without any skills.</li>



<li><code>in-memory-pagination-issue</code>: Usecase implementation generated by AI that results in in-memory pagination issue.</li>



<li><code>skills</code>: With <code>spring-data-jpa</code> skill to try implementing the mentioned usecase.</li>
</ul>



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



<p>If the AI agent is generating code with any anti-patterns or not following team coding standards and conventions, instead of fixing issues one-by-one with follow-up prompts, consider creating a skill to provide those as guidelines.</p>



<p>To explore more on Agent Skills, please refer to the following resources:</p>



<ul>
<li><a href="https://agentskills.io/" target="_blank" rel="noopener">https://agentskills.io/</a></li>



<li><a href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview" target="_blank" rel="noopener">https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview</a></li>



<li><a href="https://developers.openai.com/codex/skills/" target="_blank" rel="noopener">https://developers.openai.com/codex/skills/</a></li>



<li><a href="https://geminicli.com/docs/cli/skills/" target="_blank" rel="noopener">https://geminicli.com/docs/cli/skills/</a></li>



<li><a href="https://junie.jetbrains.com/docs/agent-skills.html" target="_blank" rel="noopener">https://junie.jetbrains.com/docs/agent-skills.html</a>&nbsp;</li>
</ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>IntelliJ IDEA 2026.1 Is Out!</title>
		<link>https://blog.jetbrains.com/idea/2026/03/intellij-idea-2026-1/</link>
		
		<dc:creator><![CDATA[Maria Kosukhina]]></dc:creator>
		<pubDate>Wed, 25 Mar 2026 14:28:29 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/IJ-IDEA-2026.1-BlogFeatured.png</featuredImage>		<category><![CDATA[releases]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=692136</guid>

					<description><![CDATA[IntelliJ IDEA 2026.1 is here, and it comes packed with an array of new features and enhancements to elevate your coding experience!&#160; You can download this latest release from our&#160;website&#160;or update to it directly from inside the IDE, via the free&#160;Toolbox App, or using snap packages for Ubuntu. As always, all new features are brought [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>IntelliJ IDEA 2026.1 is here, and it comes packed with an array of new features and enhancements to elevate your coding experience!&nbsp;</p>



<p>You can download this latest release from our&nbsp;<a href="https://www.jetbrains.com/idea/download/" target="_blank" rel="noreferrer noopener">website</a>&nbsp;or update to it directly from inside the IDE, via the free&nbsp;<a href="https://www.jetbrains.com/toolbox-app/" target="_blank" rel="noreferrer noopener">Toolbox App</a>, or using snap packages for Ubuntu.</p>



<p>As always, all new features are brought together on the <a href="https://www.jetbrains.com/idea/whatsnew/" data-type="link" data-id="https://www.jetbrains.com/idea/whatsnew/" target="_blank" rel="noopener">What’s New page</a>, with detailed explanations and demos.</p>



<p align="center"><a class="jb-download-button" href="https://www.jetbrains.com/idea/whatsnew/" target="_blank" rel="noopener">Explore the What&#8217;s New page</a></p>



<p>In addition to the What’s New page, our developer advocates got together to discuss and demonstrate the key updates. If you prefer watching to reading, check it out.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="What&#039;s New In IntelliJ IDEA 2026.1" src="https://www.youtube.com/embed/FVsMsCFtlOs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>IntelliJ IDEA 2026.1 brings built-in support for more AI agents, including Codex, Cursor, and any ACP-compatible agent, and delivers targeted, first-class improvements for Java, Kotlin, and Spring. The release also advances IntelliJ IDEA’s mission to provide support for the latest languages and tools from day one.</p>



<p><em>Please note that some AI features may work differently or be unavailable in your region. <a href="https://www.jetbrains.com.cn/ai-china/" target="_blank" rel="noreferrer noopener">Learn more</a>.</em></p>



<p><strong>Any agent, built-in:</strong></p>



<ul>
<li>ACP Registry: Browse and install AI agents in one click.</li>



<li>Git worktrees: Work in parallel branches and hand one off to an agent while you keep moving in another.</li>



<li>Database access for AI agents: Let Codex or Claude Agent query and modify your data sources natively.</li>
</ul>



<p></p>



<p><strong>Intelligence in the platform:</strong></p>



<ul>
<li>Quota-free next edit suggestions: Propagate changes throughout a given file with IDE-driven assistance.</li>



<li>Spring runtime insight: Inspect injected beans, endpoint security, and property values without pausing execution.</li>



<li>Kotlin-aware JPA: Detect and fix Kotlin-specific pitfalls in Jakarta Persistence entities.</li>
</ul>



<p></p>



<p><strong>First-class language support:</strong></p>



<ul>
<li>Java 26: Enjoy day-one support, including preview features.</li>



<li>Kotlin 2.3.20: Enjoy day-one support, including experimental features.</li>



<li>C/C++ in IntelliJ IDEA: Access first-class C/C++ coding assistance for multi-language projects.</li>



<li>Support for JavaScript without an Ultimate subscription.</li>
</ul>



<p></p>



<p><strong>Productivity and environment:</strong></p>



<ul>
<li>Expanded command completion, now with AI actions, postfix templates, and config file support.</li>



<li>Better performance for large-scale TypeScript projects.</li>



<li>Native Dev Container workflow: Open containerized projects as if they were local.</li>
</ul>



<p></p>



<p>Along with new features, 2026.1 delivers numerous stability, performance, and usability improvements across the platform. These are described in a separate <a href="https://blog.jetbrains.com/idea/2026/03/whats-fixed-intellij-idea-2026-1/">What’s Fixed blog post</a>.</p>



<p>As always, your feedback plays an important role in shaping IntelliJ IDEA. Tell us what you think about the new features and help guide future improvements.</p>



<p>Join the discussion on <a href="https://x.com/intellijidea" target="_blank">X</a>, <a href="https://www.linkedin.com/showcase/intellijidea/" target="_blank" rel="noopener">LinkedIn</a>, or <a href="https://bsky.app/profile/intellijidea.com" target="_blank" rel="noopener">Bluesky</a>, and if you encounter any issues, please report them via <a href="https://youtrack.jetbrains.com/issues/IDEA" target="_blank" rel="noopener">YouTrack</a>.</p>



<p>For full details of the improvements introduced in version 2026.1, refer to the <a href="https://youtrack.jetbrains.com/articles/IDEA-A-2100662652/IntelliJ-IDEA-2026.1-261.22158.277-build-Release-Notes" data-type="link" data-id="https://youtrack.jetbrains.com/articles/IDEA-A-2100662652/IntelliJ-IDEA-2026.1-261.22158.277-build-Release-Notes" target="_blank" rel="noopener">release notes</a>.</p>



<p>Thank you for using IntelliJ IDEA. Happy developing!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What’s fixed in IntelliJ IDEA 2026.1</title>
		<link>https://blog.jetbrains.com/idea/2026/03/whats-fixed-intellij-idea-2026-1/</link>
		
		<dc:creator><![CDATA[Dmitriy Smirnov]]></dc:creator>
		<pubDate>Wed, 25 Mar 2026 10:48:22 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/IJ-IDEA-2026.1-whats-fixed.png</featuredImage>		<category><![CDATA[releases]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=691936</guid>

					<description><![CDATA[Welcome to the overview of fixes and improvements in IntelliJ IDEA 2026.1. In this release, we have resolved over 1,000 bugs and usability issues, including 334 reported by users. Below are the most impactful changes that will help you work with greater confidence every day. Performance We continue to prioritize reliability, working to improve application [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Welcome to the overview of fixes and improvements in IntelliJ IDEA 2026.1.</p>
<p>In this release, we have resolved <a href="https://youtrack.jetbrains.com/issues?q=Project:%20IDEA,%20IJPL,%20WEB%20Available%20in:%202026.1*%20%23resolved%20sort%20by:%20votes%20visible%20to:%20%7Bissue%20readers%7D%20Type:%20Bug,%20%7BUsability%20Problem%7D" target="_blank" rel="noopener">over 1,000 bugs and usability issues</a>, including <a href="https://youtrack.jetbrains.com/issues?q=Project:%20IDEA,%20IJPL,%20WEB%20Available%20in:%202026.1*%20%23resolved%20sort%20by:%20votes%20visible%20to:%20%7Bissue%20readers%7D%20Type:%20Bug,%20%7BUsability%20Problem%7D%20reporter:%20-jetbrains-team" target="_blank" rel="noopener">334<br />
reported by users</a>. Below are the most impactful changes that will help you work with greater confidence every day.</p>
<h2 id="performance">Performance</h2>
<p>We continue to prioritize reliability, working to improve application performance, fix freezes, optimize operations, and cover the most common use cases with metrics. Using our internal tools, we identified and resolved 40 specific scenarios that caused UI freezes.</p>
<p>However, internal tooling alone cannot uncover every issue. To identify additional cases, we enabled automatic error and freeze reporting in EAP builds. By collecting this data, we gain a real, unfiltered picture of what’s going wrong, how often it happens, and how many users are affected. This allows us to prioritize fixes based on real impact rather than guesswork.</p>
<p>As always, we prioritize your privacy and security. When using EAP builds, you maintain full control and can disable automatic error and freeze reporting in <em>Settings</em> | <em>Appearance &amp; Behavior</em> | <em>System Settings</em> | <em>Data Sharing</em>. Thank you for helping us build better tools!</p>
<h2 id="terminal">Terminal</h2>
<p>Version 2026.1 enhances your productivity by streamlining the experience offered by the terminal, a crucial workspace for developer workflows involving CLI-based AI agents.</p>
<p>First, we fixed the <a href="https://youtrack.jetbrains.com/issue/IJPL-184110" target="_blank" rel="noopener"><em>Esc</em> behavior</a> – it is now handled by the shell instead of switching focus to the editor, so it does not break the AI-agent workflow. Additionally, <a href="https://youtrack.jetbrains.com/issue/IJPL-221848" target="_blank" rel="noopener"><em>Shift</em>+<em>Enter</em> now inserts a new line</a>, making it easier to write multi-line prompts and commands directly. This behavior can be disabled in <em>Settings</em> | <em>Advanced Settings</em> | <em>Terminal</em>.</p>
<p>We also improved the detection of <a href="https://youtrack.jetbrains.com/issue/IJPL-206783" target="_blank" rel="noopener">absolute</a> and <a href="https://youtrack.jetbrains.com/issue/IJPL-232564" target="_blank" rel="noopener">relative</a> file paths in terminal output, allowing you to open files and folders with a single click in any context. When you encounter compilation or build errors, or submit a task to an AI coding agent, you can jump directly to the referenced file and review or fix issues faster.</p>
<p>Link navigation is activated by <a href="https://youtrack.jetbrains.com/issue/IJPL-221853" target="_blank" rel="noopener">holding <em>Ctrl</em></a> (or <em>Cmd</em> on macOS) and clicking – just like in external terminals.</p>
<h2 id="jvm-language-support">JVM language support</h2>
<h3 id="better-kotlin-bean-registration-support">Better Kotlin bean registration support</h3>
<p>Kotlin’s strong DSL capabilities are a perfect fit for Spring Framework 7’s BeanRegistrar API. In 2026.1, we’ve made working with programmatic registration as productive as annotation-based configuration.</p>
<p>The IDE ensures complete visibility into your application structure thanks to the <em>Structure</em> tool window, providing better endpoint visibility, intuitive navigation with gutter icons, integrated HTTP request generation, and path variable support.</p>
<h3 id="new-kotlin-coroutine-inspections">New Kotlin coroutine inspections</h3>
<p>To help maintain code quality, we’ve introduced a set of new inspections for the Kotlin coroutines library, covering common pitfalls.</p>
<p>Read more about coroutine inspections in <a href="https://blog.jetbrains.com/idea/2026/03/intellij-idea-s-new-kotlin-coroutine-inspections-explained/">this article</a>.</p>
<h3 id="scala">Scala</h3>
<p>Working with sbt projects inside WSL and Docker containers is now as smooth as working with local projects. We’ve also improved code highlighting performance and sped up sbt project synchronization.</p>
<p>To reduce cognitive load and provide a more ergonomic UI, we’ve redesigned the Scala code highlighting settings. A new <em>Settings</em> page consolidates previously scattered options, making them cleaner, more intuitive, and easier to access.</p>
<p>You can now disable built-in inspections when compiler highlighting is sufficient, or configure compilation delay for compiler-based highlighting. Settings for Scala 2 and Scala 3 projects are now independent, and the type-aware highlighting option has been integrated with the rest of the settings.</p>
<p>You can read more about these updates <a href="https://blog.jetbrains.com/scala/2026/03/23/intellij-scala-plugin-2026-1-is-out">this article</a>.</p>
<h2 id="spring">Spring</h2>
<p>Spring support remains a core focus for IntelliJ IDEA. We are committed to maximizing reliability and reducing friction in your daily development.</p>
<p>In this release, we made a dedicated effort to address <a href="https://youtrack.jetbrains.com/issue/IDEA-370094/Spring-Boot-Run-Problems-2026.1" target="_blank" rel="noopener">issues related to running Spring Boot application</a> from the IDE. There are now even fewer reasons to run your application in the terminal &#8211; just run it in the IDE and use the debugger when you need deeper insights.</p>
<h3 id="API-versioning">Spring Boot 4 API versioning support</h3>
<p>This is a new Spring Boot feature, and we keep improving its support based on your feedback. In this version, we added .yml files support for version configuration, fixed false positives and added a couple of useful inspections, so you get an instant feedback about issues without running the app.</p>
<h3 id="API-versioning">Flyway DB Migrations</h3>
<p>To ensure a reliable and distraction-free experience, the IDE now verifies migration scripts only when a data source is active, eliminating false-positive errors when the data source is disconnected.</p>
<p>At the same time, Flyway scripts got correct navigation to the table definitions, and SQL autocompletion for any files and tables defined in them.</p>
<h2 id="user-interface">User interface</h2>
<p>With IntelliJ IDEA 2026.1, we’ve continued to prioritize ultimate comfort and an ergonomic UI, ensuring your workspace is as accessible and customizable as your code.</p>
<p>The long-awaited ability to <a href="https://youtrack.jetbrains.com/issue/IJPL-54591" target="_blank" rel="noopener">sync the IDE theme with the OS</a> is now available to Linux users, bringing parity with macOS and Windows. Enable it in <em>Settings</em> |<em>Appearance &amp; Behavior</em> | <em>Appearance</em>.</p>
<p>The code editor now supports <a href="https://youtrack.jetbrains.com/issue/IJPL-26382" target="_blank" rel="noopener">OpenType stylistic sets</a>. Enjoy more expressive typography with your favorite fonts while coding. Configure them via <em>Editor</em> |<em>Font</em>, and preview glyph changes instantly with a helpful tooltip before applying a set.</p>
<p>Windows users who rely on the keyboard can now bring the IDE’s main menu into focus by <a href="https://youtrack.jetbrains.com/issue/IJPL-58454" target="_blank" rel="noopener">pressing the <em>Alt</em> key</a>. This change improves accessibility for screen reader users.</p>
<h2 id="version-control">Version control</h2>
<p>We continue to make small but impactful improvements that reduce friction and support your everyday workflow.</p>
<p>You can now [coming in 2026.1.1 update] <a href="https://youtrack.jetbrains.com/issue/IJPL-219835" target="_blank" rel="noopener">amend any recent commit</a> directly from the <em>Commit</em> tool window – no more ceremonies involving interactive rebase. Simply select the target commit and the necessary changes, then confirm them – the IDE will take care of the rest.</p>
<p>In addition to Git worktrees, we’ve improved branch workflows by introducing the <a href="https://youtrack.jetbrains.com/issue/IJPL-73967" target="_blank" rel="noopener"><em>Checkout &amp; Update</em></a> action, which pulls all remote changes.</p>
<p>Furthermore, fetching changes can now be automated – no need for a separate plugin. Enable <em>Fetch remote changes automatically</em> in <em>Settings</em> | <em>Git</em>.</p>
<p>In-IDE reviews for GitLab merge requests now offer near feature parity with the web interface. <a href="https://youtrack.jetbrains.com/issue/IJPL-82603" target="_blank" rel="noopener">Multi-line comments</a>, <a href="https://youtrack.jetbrains.com/issue/IJPL-84177" target="_blank" rel="noopener">comment navigation</a>, <a href="https://youtrack.jetbrains.com/issue/IJPL-82619" target="_blank" rel="noopener">image uploads</a>, and <a href="https://youtrack.jetbrains.com/issue/IJPL-82596" target="_blank" rel="noopener">assignee selection</a> when creating a merge request are all available directly in the IDE, so you can stay focused without switching to the browser.</p>
<p>The Subversion, Mercurial, and Perforce plugins are no longer bundled with the IDE distribution, but you can still install them from <a href="https://plugins.jetbrains.com/" target="_blank" rel="noopener">JetBrains Marketplace</a>.</p>
<h2 id="databases">Databases</h2>
<p>We’ve enhanced the <em>Explain Plan</em> workflow with UI optimizations for the <em>Query Plan</em> tab, an additional separate pane for details about the execution plan row, inner tabs that hold flame graphs, and an action to copy the query plan in the database’s native format.</p>
<h2 id="jetbrains-daemon">JetBrains daemon</h2>
<p>IntelliJ IDEA 2026.1 includes a lightweight background service – <a href="https://www.jetbrains.com/help/toolbox-app/daemon.html" target="_blank" rel="noopener">jetbrainsd</a> – that handles jetbrains:// protocol links from documentation, learning resources, and external tools, opening them directly in your IDE without requiring you to have the Toolbox App running.</p>
<h2 id="sunsetting-of-code-with-me">Sunsetting of Code With Me</h2>
<p>As of version 2026.1, Code With Me will be unbundled from all JetBrains IDEs and will instead be available as a separate plugin on JetBrains Marketplace. Version 2026.1 will be the last IDE release to officially support Code With Me as we gradually sunset the service.</p>
<p>Read the full announcement and timeline in <a href="https://blog.jetbrains.com/platform/2026/03/sunsetting-code-with-me/">our blog post</a>.</p>
<h2 id="enhanced-ai-management-and-analytics-for-organizations">Enhanced AI management and analytics for organizations</h2>
<p>We are working hard to provide development teams with centralized control over AI and built-in analytics to understand adoption, usage, and cost. As part of the effort, we’ve <a href="https://blog.jetbrains.com/ai/2026/02/enhanced-ai-management-and-analytics-for-organizations/">introduced the JetBrains Console</a>. It adds visibility into how your teams use AI in practice, including information about active users, credit consumption, and acceptance rates for AI-generated code.</p>
<p>The JetBrains Console is available to all organizations with a JetBrains AI subscription, providing the trust and visibility required to manage professional-grade development at any scale.</p>
<p>That’s it for this overview.</p>
<p>Let us know what you think about the fixes and priorities in this release. Your feedback helps us steer the product so it works best for you!</p>
<p>We’d also love to hear your thoughts on this overview and the format in general.</p>
<p>Update to IntelliJ IDEA 2026.1 now and see how it has improved. Don’t forget to join us on <a href="https://x.com/IntelliJIDEA" target="_blank">X</a> , <a href="https://bsky.app/profile/intellijidea.com/" target="_blank" rel="noopener">Bluesky</a>, or <a href="https://www.linkedin.com/showcase/intellijidea" target="_blank" rel="noopener">LinkedIn</a> and share your favorite updates.</p>
<p>Thank you for using IntelliJ IDEA!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Core JavaScript and TypeScript Features Become Free in IntelliJ IDEA</title>
		<link>https://blog.jetbrains.com/idea/2026/03/js-ts-free-support/</link>
		
		<dc:creator><![CDATA[Julia Shashkova]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 11:43:34 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/IJ-social-BlogFeatured-js-ts-1.png</featuredImage>		<category><![CDATA[news]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=684420</guid>

					<description><![CDATA[Modern Java development often involves web technologies. To make this workflow more accessible and smoother, we’re making some core JavaScript, TypeScript, HTML, and CSS features – previously included with the Ultimate subscription only – available for free in IntelliJ IDEA v2026.1. JavaScript, TypeScript, HTML, CSS, and React Support Enjoy a comprehensive set of features for [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Modern Java development often involves web technologies. To make this workflow more accessible and smoother, we’re making some core JavaScript, TypeScript, HTML, and CSS features – previously included with the Ultimate subscription only – available for free in IntelliJ IDEA v2026.1.</p>



<h2 class="wp-block-heading">JavaScript, TypeScript, HTML, CSS, and React Support</h2>



<p>Enjoy a comprehensive set of features for building modern web applications:</p>



<ul>
<li><strong>Basic React support</strong>, including code completion, component and attribute navigation, and React component and prop rename refactorings.</li>
</ul>



<ul>
<li><strong>Full syntax highlighting</strong> for JavaScript, TypeScript, HTML, and CSS, ensuring better readability and usability of frontend code inside the IDE.<br><img decoding="async" loading="lazy" class="wp-image-685026" style="width: 1500px;; width:100% !important; height:auto !important; max-width:100% !important;" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/js-ts-syntax-2026-1.jpg" alt="Full syntax highlighting for JavaScript, TypeScript, HTML, and CSS"></li>



<li><strong>Reliable code completion</strong> to write code faster and with fewer errors across both backend and frontend parts of your web application.<img decoding="async" loading="lazy" class="wp-image-685065" style="width: 1500px;; width:100% !important; height:auto !important; max-width:100% !important;" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/js-ts-completion-2026-1.png" alt="code completion for JS and TS"></li>
</ul>



<ul>
<li><strong>Advanced import management</strong> automatically handles JavaScript and TypeScript imports as you code, adds missing references when pasting code, and cleans up unused ones with <em>Optimize Imports</em> – helping you save time, reduce errors, and keep your codebase clean.</li>



<li><strong>Smooth code navigation </strong>via dedicated gutter icons for <em>Jump to&#8230;</em> actions, recursive calls, TypeScript source mapping, and more.<img decoding="async" loading="lazy" class="wp-image-685037" style="width: 1500px;; width:100% !important; height:auto !important; max-width:100% !important;" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/js-ts-navigation-2026-1.png" alt="code navigation for JS and TS"></li>
</ul>



<h2 class="wp-block-heading">Code Intelligence and Code Quality</h2>



<p>Improve and maintain your web code with built-in intelligence and quality tools:</p>



<ul>
<li><strong>Core web refactorings:</strong> Make changes to your code with reliable <em>Rename</em> refactorings and actions (<em>Introduce Variable</em>, <em>Introduce Constant</em>, <em>Change Signature</em>, <em>Move Members</em>, and more).</li>



<li><strong>Quality control</strong>: Identify potential issues early with built-in inspections, intentions, and quick fixes, and get improvement suggestions as you code.</li>



<li><strong>Code cleanup</strong>: Keep your codebase clean with JavaScript and TypeScript duplicate detection, making it easier to spot and eliminate redundant code.</li>
</ul>



<h2 class="wp-block-heading">Integrated workflows</h2>



<p>Now it’s easier to manage, maintain, and secure your web projects from within a single environment.</p>



<ul>
<li><strong>Create</strong> <strong>new web projects </strong>quickly by using the built-in Vite generator.</li>



<li><strong>Keep your codebase consistent and clean</strong> with integrated support for Prettier, ESLint, TSLint, and StyleLint.</li>



<li><strong>Execute NPM scripts </strong>directly from <code>package.json</code>.<br><img decoding="async" loading="lazy" class="wp-image-685048" style="width: 1500px;; width:100% !important; height:auto !important; max-width:100% !important;" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/js-ts-npm-script-2026-1.png" alt="Execute NPM scripts directly from package.json"></li>



<li><strong>Monitor your project dependencies</strong> and identify known security vulnerabilities early.</li>
</ul>



<p>Enjoy building your web applications with IntelliJ IDEA, and happy developing!</p>



<p><em>If you need more advanced tools (dedicated debugger, test runners, test UI tooling, support for all frontend frameworks including Angular, Vue, advanced refactorings, and more) for full-stack application development, you can try them with the Ultimate subscription trial. The trial provides 30 days of full access – no credit card required.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>IntelliJ IDEA&#8217;s New Kotlin Coroutine Inspections, Explained</title>
		<link>https://blog.jetbrains.com/idea/2026/03/intellij-idea-s-new-kotlin-coroutine-inspections-explained/</link>
		
		<dc:creator><![CDATA[Irina Mariasova]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 10:00:58 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/IJ-social-BlogFeatured-1280x720-1-1.png</featuredImage>		<category><![CDATA[kotlin]]></category>
		<category><![CDATA[coroutines]]></category>
		<category><![CDATA[inspections]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=689112</guid>

					<description><![CDATA[This article was written by an external contributor. Every technology has its misuses, and different ecosystems use different approaches to prevent them. In the Kotlin ecosystem, I believe the philosophy has always been to make APIs so good that correct usage is simple and intuitive, while misuse is harder and more complicated. This differs from [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><em>This article was written by an external contributor.</em></p>


    <div class="about-author ">
        <div class="about-author__box">
            <div class="row">
                                                            <div class="about-author__box-img">
                            <img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2025/10/image-96.png" alt="" loading="lazy">
                        </div>
                                        <div class="about-author__box-text">
                                                    <h4>Marcin Moskała</h4>
                                                <p>Marcin is a highly experienced developer and Kotlin instructor, founder of Kt. Academy, an official JetBrains partner specializing in Kotlin training. He is also a Google Developers Expert and a well-known contributor to the Kotlin community. Marcin is the author of several widely recognized books, including <em data-start="450" data-end="468">Effective Kotlin</em>, <em data-start="470" data-end="489" data-is-only-node="">Kotlin Coroutines</em>, <em data-start="491" data-end="510">Functional Kotlin</em>, <em data-start="512" data-end="529">Advanced Kotlin</em>, <em data-start="531" data-end="550">Kotlin Essentials</em>, and <em data-start="556" data-end="589">Android Development with Kotlin</em>.</p>
<p><a href="https://kt.academy/" target="_blank" rel="noopener">Website</a></p>
                    </div>
                            </div>
        </div>
    </div>



<p>Every technology has its misuses, and different ecosystems use different approaches to prevent them. In the Kotlin ecosystem, I believe the philosophy has always been to make APIs so good that correct usage is simple and intuitive, while misuse is harder and more complicated. This differs from JavaScript, which has plenty of legacy practices (like using == instead of ===, or <code>var</code> instead of <code>let/const</code>) and relies more on warnings. However, not everything can be enforced by good design, and Kotlin also uses warnings to guide developers in writing better code.&nbsp;</p>



<p>Today, IntelliJ IDEA introduces a set of new inspections for the Kotlin coroutines library. I’ve seen these issues in many codebases and addressed them through my books, articles, and workshops. These patterns often show up, so let’s walk through why they are problematic and how to handle them correctly.&nbsp;</p>



<p>Note: These inspections are also available in Android Studio. You can check how IntelliJ IDEA versions map to Android Studio versions <a href="https://plugins.jetbrains.com/docs/intellij/android-studio-releases-list.html#2025" target="_blank" rel="noopener">here</a>.&nbsp;</p>



<h2 class="wp-block-heading"><code>awaitAll()</code>and <code>joinAll()</code></h2>



<p>Available since IntelliJ IDEA 2025.2</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-34.png" alt="" class="wp-image-689987"/></figure>



<p>If you use map <code>{ it.await() }</code>, IntelliJ IDEA will suggest <code>awaitAll()</code>. If you use <code>forEach { it.join() }</code>, it will suggest <code>joinAll()</code>. Why? These alternatives are cleaner, and <code>awaitAll()</code> is also more efficient and better represents waiting for multiple tasks, as it waits for all elements concurrently rather than one after another.&nbsp;</p>



<p><code>awaitAll()</code> also behaves more efficiently in the presence of exceptions. Imagine awaiting 100 coroutines, and the fiftieth throws an exception. <code>awaitAll()</code> will immediately rethrow the exception, unlike map <code>{ it.await() }</code>, which would wait for the first 49 coroutines before throwing the exception. In most cases, this behavior cannot be observed because of other exception propagation mechanisms.&nbsp;</p>



<h2 class="wp-block-heading"><code>currentCoroutineContext()</code> over <code>coroutineContext</code></h2>



<p>Available since IntelliJ IDEA 2025.2</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image_2.png" alt="" class="wp-image-689310"/></figure>



<p>All suspending functions can access the context of the coroutine in which they are called. Traditionally, this was done via the <code>coroutineContext</code> property. The problem is that <code>CoroutineScope</code>, which is implicitly available in coroutine starters, such as launch, <code>coroutineScope</code>, and <code>runTest</code>, has a property with the same name. This can be confusing and lead to issues. Consider the following example:&nbsp;</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image12.png" alt="" class="wp-image-689321"/></figure>



<p>This code tests the <code>mapAsync</code> function and checks whether it correctly propagates context from the caller to the transformation. It is incorrect. Within the transformation, we could read the caller context from the <code>coroutineContext</code>, but not in this situation. This lambda is defined inside <code>runTest</code>, and the <code>coroutineContext</code> property from <code>CoroutineScope</code> (provided by <code>runTest</code>) takes priority over the top-level <code>coroutineContext</code> property. This kind of mistake is quite common, which is why the <code>currentCoroutineContext()</code> function was introduced to read the context of the coroutine that runs a suspending function. You should use it instead of <code>coroutineContext</code>.&nbsp;</p>



<h2 class="wp-block-heading"><code>runBlocking</code> inside a suspending function</h2>



<p>Available since IDEA 2025.2</p>



<p>Using <code>runBlocking</code> inside suspending functions is a serious issue. It blocks the calling thread, which defeats the purpose of coroutines.</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image10-2.png" alt="" class="wp-image-689332"/></figure>



<p>So what can you use instead? That depends on what you want to achieve. In most cases, you don’t need it. If you need to create a coroutine scope, use <code>coroutineScope { … }</code>. If you need to change context, use <code>withContext(ctx) { … }</code>.<br>Watch out for situations where a suspending function calls a regular function that uses runBlocking. Opt for making this function suspend to avoid making a blocking call.&nbsp;</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image9-1.png" alt="" class="wp-image-689343"/></figure>



<h2 class="wp-block-heading">Unused <code>Deferred</code></h2>



<p>Available since IntelliJ IDEA 2025.3</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-29.png" alt="" class="wp-image-689126"/></figure>



<p>This inspection appears when you use async without ever using its result. In such cases, you should use launch instead. This is the key difference between launch and <code>async</code>: <code>async</code> returns a result and is expected to await this result, while <code>launch</code> produces no result.&nbsp;</p>



<p>Because of this, exception handling differs. <code>async</code> doesn’t call <code>CoroutineExceptionHandler</code> because it is expected to throw an exception from await and propagate it this way.&nbsp;</p>



<h2 class="wp-block-heading"><code>Job</code> used as an argument in a coroutine starter</h2>



<p>Available since IntelliJ IDEA 2025.3</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-33.png" alt="" class="wp-image-689227"/></figure>



<p>I’ve been looking forward to this inspection for years! Using <code>Job</code> as an argument to a coroutine starter causes issues, and it’s something I’ve seen in many projects. I covered this anti-pattern in my book and workshops, but it still appears quite often. This inspection should help clarify the correct approach. Let’s look at why <code>Job</code> shouldn’t be used as an argument for a coroutine.&nbsp;</p>



<p>The key misunderstanding here is that <code>Job</code> cannot be overridden by an argument. If you use any other context, it will be used in the coroutine and its children, but not <code>Job</code>. Every coroutine creates its own job. A job contains a coroutine’s state and relations – it cannot be shared or enforced from outside. The <code>Job</code> that is used as an argument isn’t going to be a job of this coroutine. Instead, it overrides <code>Job</code> from the scope and becomes a parent. This breaks structured concurrency.</p>



<p>For example: Using <code>withContext(SupervisorJob()) { … }</code> behaves very differently from <code>supervisorScope { … }</code>.&nbsp;</p>



<p><code>supervisorScope</code> creates a child coroutine of the caller of this function, and it uses a supervisor job (it doesn’t propagate its children’s exceptions). On the other hand, <code>withContext(SupervisorJob())</code> creates a regular coroutine, which is a child of <code>SupervisorJob</code> and has no relation to the caller.&nbsp;</p>



<p>Consider the code below. An exception in the first launch propagates to <code>withContext</code> (which uses regular <code>Job</code>), cancels the other child coroutines, and is then rethrown. <code>SupervisorJob()</code> has no effect. In some cases, it can even be harmful, as it breaks structured concurrency. If the caller of <code>withContext(SupervisorJob())</code> is cancelled, that cancellation won’t propagate, which will result in a memory leak.&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import kotlinx.coroutines.*

val handler = CoroutineExceptionHandler { _, e ->
   println("Exception:  ${e.message}")
}

fun main(): Unit = runBlocking(handler) {
   // DON'T DO THAT!
   withContext(SupervisorJob()) {
       launch {
           delay(1000)
           throw Error("Some error")
       }
       launch {
           delay(2000)
           println("AAA")
       }
   }
  println("Done")
}
// (1 sec)
// Exception in thread "main"...</pre>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-30.png" alt="" class="wp-image-689146"/></figure>



<p>Using <code>supervisorScope</code> would prevent this problem:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import kotlinx.coroutines.*

val handler = CoroutineExceptionHandler { _, e ->
   println("Exception:  ${e.message}")
}

fun main(): Unit = runBlocking(handler) {
  supervisorScope {
      launch {
          delay(1000)
          throw Error("Some error")
      }
      launch {
          delay(2000)
          println("AAA")
      }
  }
  println("Done")
}
// (1 sec)
// Exception:  Some error
// (1 sec)
// AAA
// Done</pre>



<p>A <code>Job</code> used as an argument breaks the relationship with the caller. In the case below, <code>updateToken</code> won’t be related to the caller of <code>getToken</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">suspend fun getToken(): Token = coroutineScope {
   val token = tokenRepository.fetchToken()
   launch(Job()) { // Poor practice
       tokenRepository.updateToken(token)
   }
   token
}</pre>



<p>This is generally discouraged, as it breaks structured concurrency. The standard approach would be to sequentially call <code>updateToken</code>:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">suspend fun getToken(): Token {
   val token = tokenRepository.fetchToken()
   tokenRepository.updateToken(token)
   return token
}</pre>



<p>If we really want to detach <code>updateToken</code> from <code>getToken</code>, a better practice would be to start the launch on a different scope, like the backgroundScope we define in our application for background tasks. With this approach, the new coroutine is still attached to a scope, just a different one:&nbsp;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">suspend fun getToken(): Token {
   val token = tokenRepository.fetchToken()
   backgroundScope.launch { // Acceptable
       tokenRepository.updateToken(token)
   }
   return token
}</pre>



<h2 class="wp-block-heading"><code>suspendCancellableCoroutine</code> instead of <code>suspendCoroutine</code></h2>



<p>Available since IntelliJ IDEA 2025.3</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-32.png" alt="" class="wp-image-689233"/></figure>



<p>To suspend a coroutine, use <code>suspendCancellableCoroutine</code>. Its predecessor, <code>suspendCoroutine</code>, does not support cancellation and should be avoided.<br><code>suspendCancellableCoroutine</code> is a low-level API rarely used in application code, but often used by libraries that support suspending calls.&nbsp;</p>



<h2 class="wp-block-heading">Suspicious implicit <code>CoroutineScope</code> receiver</h2>



<p>Available since IntelliJ IDEA 2025.3, but this inspection is disabled by default and must be enabled manually.</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image13.png" alt="" class="wp-image-689354"/></figure>



<p>Implicit receivers within lambdas can be confusing. In the above example, <code>async</code> calls are executed on the scope created by <code>coroutineScope</code> because <code>collectLatest</code> doesn’t provide its own scope. This can lead to memory leaks. When a new value reaches <code>collectLatest</code>, it should cancel processing of the previous one. In this example, it cannot cancel the <code>async</code> coroutines, as they are attached to <code>coroutineScope</code>, not to <code>collectLatest</code>. To avoid this, define <code>coroutineScope</code> inside <code>collectLatest</code>, not outside it. This inspection highlights such cases to prevent these issues.&nbsp;</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image-31.png" alt="" class="wp-image-689175"/></figure>



<h2 class="wp-block-heading">Simpler operations for flow processing</h2>



<p>Available since IntelliJ IDEA 2026.1 (currently in EAP)</p>



<figure class="wp-block-image size-full"><img style="width:100% !important; height:auto !important; max-width:100% !important;" decoding="async" loading="lazy" src="https://blog.jetbrains.com/wp-content/uploads/2026/03/image_1-1.png" alt="" class="wp-image-689366"/></figure>



<p>You may already know these from collection or sequence processing:<br>If you use <code>filterNotNull</code> after map, you’ll get the suggestion to use <code>mapNotNull</code>. If you use filter <code>{ it is T }</code>, the IDE will suggest using <code>filterNotNull&lt;T&gt;</code>.<br>These suggestions are now also available for flows!&nbsp;</p>



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



<p>IntelliJ IDEA continues to help you write better code – not only by advancing its AI tools and agents, but also by improving the core development experience. There are still many inspections I would love to see in the IDE, but the current set already brings significant value.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>IntelliJ IDEA 2025.3.4 is Out!</title>
		<link>https://blog.jetbrains.com/idea/2026/03/intellij-idea-2025-3-4/</link>
		
		<dc:creator><![CDATA[Julia Shashkova]]></dc:creator>
		<pubDate>Tue, 17 Mar 2026 17:25:08 +0000</pubDate>
		<featuredImage>https://blog.jetbrains.com/wp-content/uploads/2026/03/IJ-social-BlogFeatured-2025-3-4-1.png</featuredImage>		<category><![CDATA[releases]]></category>
		<category><![CDATA[bug-fix-update]]></category>
		<category><![CDATA[intellij-idea]]></category>
		<guid isPermaLink="false">https://blog.jetbrains.com/?post_type=idea&#038;p=688872</guid>

					<description><![CDATA[We’ve just released IntelliJ IDEA 2025.3.4. This update introduces full support for Java 26 along with several notable improvements. You can update to this version from inside the IDE, using the Toolbox App, or using snaps if you are a Ubuntu user. You can also download it from our website. Here are the most notable [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>We’ve just released IntelliJ IDEA 2025.3.4. This update introduces <strong>full support for Java 26</strong> along with several notable improvements.</p>



<p>You can update to this version from inside the IDE, using the <a href="https://www.jetbrains.com/toolbox-app/" target="_blank" rel="noopener">Toolbox App</a>, or using snaps if you are a Ubuntu user. You can also download it from our <a href="https://www.jetbrains.com/idea/download/" target="_blank" rel="noopener">website</a>.</p>



<p>Here are the most notable improvements:</p>



<ul>
<li>Resolved an issue where running an HTTP request could trigger a different request in the same file. [<a href="https://youtrack.jetbrains.com/issue/IJPL-66727" target="_blank" rel="noopener">IJPL-66727</a>]</li>



<li>Local changes refresh in large Perforce projects now works as expected. [<a href="https://youtrack.jetbrains.com/issue/IJPL-236557" target="_blank" rel="noopener">IJPL-236557</a>]</li>



<li>The <em>Dependencies</em> tab now opens correctly when using the <em>Analyze Cyclic Dependencies</em> feature. [<a href="https://youtrack.jetbrains.com/issue/IJPL-206236" target="_blank" rel="noopener">IJPL-206236</a>]</li>
</ul>



<p>For a comprehensive overview of the fixes, see the <a href="https://youtrack.jetbrains.com/articles/IDEA-A-2100662645" data-type="link" data-id="https://youtrack.jetbrains.com/articles/IDEA-A-2100662645" target="_blank" rel="noopener">release notes</a>. If you spot any issues, let us know via the <a href="https://youtrack.jetbrains.com/issues/IDEA" target="_blank" rel="noreferrer noopener">issue tracker</a>.</p>



<p>Happy developing!</p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
