<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on Java Operator SDK</title><link>https://aerben.github.io/josdk-docs-test/blog/news/</link><description>Recent content in Posts on Java Operator SDK</description><generator>Hugo</generator><language>en</language><atom:link href="https://aerben.github.io/josdk-docs-test/blog/news/index.xml" rel="self" type="application/rss+xml"/><item><title>Welcome read-cache-after-write consistency!</title><link>https://aerben.github.io/josdk-docs-test/blog/2026/03/13/welcome-read-cache-after-write-consistency/</link><pubDate>Fri, 13 Mar 2026 00:00:00 +0000</pubDate><guid>https://aerben.github.io/josdk-docs-test/blog/2026/03/13/welcome-read-cache-after-write-consistency/</guid><description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt;
In version 5.3.0 we introduced strong consistency guarantees for updates with a new API.
You can now update resources (both your custom resource and managed resources)
and the framework will guarantee that these updates will be instantly visible
when accessing resources from caches,
and naturally also for subsequent reconciliations.&lt;/p&gt;
&lt;p&gt;I briefly &lt;a href="https://www.youtube.com/watch?v=HrwHh5Yh6AM&amp;amp;t=1387s"&gt;talked about this&lt;/a&gt; topic at KubeCon last year.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;public&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;UpdateControl&lt;/span&gt;&lt;span style="color:#ce5c00;font-weight:bold"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000"&gt;WebPage&lt;/span&gt;&lt;span style="color:#ce5c00;font-weight:bold"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;reconcile&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;(&lt;/span&gt;&lt;span style="color:#000"&gt;WebPage&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;webPage&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;,&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;Context&lt;/span&gt;&lt;span style="color:#ce5c00;font-weight:bold"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000"&gt;WebPage&lt;/span&gt;&lt;span style="color:#ce5c00;font-weight:bold"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;context&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;)&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;{&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;ConfigMap&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;managedConfigMap&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#ce5c00;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;prepareConfigMap&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;(&lt;/span&gt;&lt;span style="color:#000"&gt;webPage&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;);&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#8f5902;font-style:italic"&gt;// apply the resource with new API&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;context&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;.&lt;/span&gt;&lt;span style="color:#c4a000"&gt;resourceOperations&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;().&lt;/span&gt;&lt;span style="color:#c4a000"&gt;serverSideApply&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;(&lt;/span&gt;&lt;span style="color:#000"&gt;managedConfigMap&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;);&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#8f5902;font-style:italic"&gt;// fresh resource instantly available from our update in the caches&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;var&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;upToDateResource&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#ce5c00;font-weight:bold"&gt;=&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;context&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;.&lt;/span&gt;&lt;span style="color:#c4a000"&gt;getSecondaryResource&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;(&lt;/span&gt;&lt;span style="color:#000"&gt;ConfigMap&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;.&lt;/span&gt;&lt;span style="color:#c4a000"&gt;class&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;);&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#8f5902;font-style:italic"&gt;// from now on built-in update methods by default use this feature;&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#8f5902;font-style:italic"&gt;// it is guaranteed that resource changes will be visible for next reconciliation&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#204a87;font-weight:bold"&gt;return&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt; &lt;/span&gt;&lt;span style="color:#000"&gt;UpdateControl&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;.&lt;/span&gt;&lt;span style="color:#c4a000"&gt;patchStatus&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;(&lt;/span&gt;&lt;span style="color:#000"&gt;alterStatusObject&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;(&lt;/span&gt;&lt;span style="color:#000"&gt;webPage&lt;/span&gt;&lt;span style="color:#000;font-weight:bold"&gt;));&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#000;font-weight:bold"&gt;}&lt;/span&gt;&lt;span style="color:#f8f8f8"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In addition to that, the framework will automatically filter events for your own updates,
so they don&amp;rsquo;t trigger the reconciliation again.&lt;/p&gt;</description></item><item><title>How to guarantee allocated values for next reconciliation</title><link>https://aerben.github.io/josdk-docs-test/blog/2025/05/22/how-to-guarantee-allocated-values-for-next-reconciliation/</link><pubDate>Thu, 22 May 2025 00:00:00 +0000</pubDate><guid>https://aerben.github.io/josdk-docs-test/blog/2025/05/22/how-to-guarantee-allocated-values-for-next-reconciliation/</guid><description>&lt;div class="alert alert-primary" role="alert"&gt;&lt;div class="h4 alert-heading" role="heading"&gt;Deprecated&lt;/div&gt;
&lt;p&gt;Read-cache-after-write consistency feature replaces this functionality. (since version 5.3.0)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It provides this functionality also for secondary resources and optimistic locking
is not required anymore. See the &lt;a href="https://aerben.github.io/josdk-docs-test/docs/documentation/reconciler/#read-cache-after-write-consistency-and-event-filtering"&gt;docs&lt;/a&gt; and
related &lt;a href="https://aerben.github.io/josdk-docs-test/blog/2026/03/13/welcome-read-cache-after-write-consistency/"&gt;blog post&lt;/a&gt; for details.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;p&gt;We recently released v5.1 of Java Operator SDK (JOSDK). One of the highlights of this release is related to a topic of
so-called
&lt;a href="https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#representing-allocated-values"&gt;allocated values&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To describe the problem, let&amp;rsquo;s say that our controller needs to create a resource that has a generated identifier, i.e.
a resource which identifier cannot be directly derived from the custom resource&amp;rsquo;s desired state as specified in its
&lt;code&gt;spec&lt;/code&gt; field. To record the fact that the resource was successfully created, and to avoid attempting to
recreate the resource again in subsequent reconciliations, it is typical for this type of controller to store the
generated identifier in the custom resource&amp;rsquo;s &lt;code&gt;status&lt;/code&gt; field.&lt;/p&gt;</description></item><item><title>From legacy approach to server-side apply</title><link>https://aerben.github.io/josdk-docs-test/blog/2025/02/25/from-legacy-approach-to-server-side-apply/</link><pubDate>Tue, 25 Feb 2025 00:00:00 +0000</pubDate><guid>https://aerben.github.io/josdk-docs-test/blog/2025/02/25/from-legacy-approach-to-server-side-apply/</guid><description>&lt;p&gt;From version 5 of Java Operator SDK &lt;a href="https://kubernetes.io/docs/reference/using-api/server-side-apply/"&gt;server side apply&lt;/a&gt;
is a first-class feature and is used by default to update resources.
As we will see, unfortunately (or fortunately), using it requires changes for your reconciler implementation.&lt;/p&gt;
&lt;p&gt;For this reason, we prepared a feature flag, which you can flip if you are not prepared to migrate yet:
&lt;a href="https://github.com/operator-framework/java-operator-sdk/blob/main/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java#L493"&gt;&lt;code&gt;ConfigurationService.useSSAToPatchPrimaryResource&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Setting this flag to false will make the operations done by &lt;code&gt;UpdateControl&lt;/code&gt; using the former approach (not SSA).
Similarly, the finalizer handling won&amp;rsquo;t utilize SSA handling.
The plan is to keep this flag and allow the use of the former approach (non-SSA) also in future releases.&lt;/p&gt;</description></item><item><title>Using k8s' ETCD as your application DB</title><link>https://aerben.github.io/josdk-docs-test/blog/2025/01/16/using-k8s-etcd-as-your-application-db/</link><pubDate>Thu, 16 Jan 2025 00:00:00 +0000</pubDate><guid>https://aerben.github.io/josdk-docs-test/blog/2025/01/16/using-k8s-etcd-as-your-application-db/</guid><description>&lt;h1 id="faq-is-kubernetes-etcd-the-right-database-for-my-application"&gt;FAQ: Is Kubernetes’ ETCD the Right Database for My Application?&lt;/h1&gt;
&lt;h2 id="answer"&gt;Answer&lt;/h2&gt;
&lt;p&gt;While the idea of moving your application data to Custom Resources (CRs) aligns with the &amp;ldquo;Cloud Native&amp;rdquo; philosophy, it often introduces more challenges than benefits. Let’s break it down:&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="top-reasons-why-storing-data-in-etcd-through-crs-looks-appealing"&gt;Top Reasons Why Storing Data in ETCD Through CRs Looks Appealing&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Storing application data as CRs enables treating your application’s data like infrastructure:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitOps compatibility:&lt;/strong&gt; Declarative content can be stored in Git repositories, ensuring reproducibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure alignment:&lt;/strong&gt; Application data can follow the same workflow as other infrastructure components.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id="challenges-of-using-kubernetes-etcd-as-your-applications-database"&gt;Challenges of Using Kubernetes’ ETCD as Your Application’s Database&lt;/h3&gt;
&lt;h4 id="technical-limitations"&gt;Technical Limitations:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Size Limitations 🔴:&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>