<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Nicolas Frankel on foojay.io - Friends Of OpenJDK</title><link>https://foojay.io/today/author/nicolas-frankel/</link><description>Articles written by Nicolas Frankel on foojay.io - Friends Of OpenJDK</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 20 Sep 2026 05:51:17 +0000</lastBuildDate><atom:link href="https://foojay.io/today/author/nicolas-frankel/index.xml" rel="self" type="application/rss+xml"/><item><title>World geography gotchas</title><link>https://foojay.io/today/world-geography-gotchas/</link><pubDate>Sun, 20 Sep 2026 05:51:17 +0000</pubDate><guid>https://foojay.io/today/world-geography-gotchas/</guid><description>&lt;p&gt;Years ago, a colleague of mine told me about two pockets of foreign land surrounded by Switzerland: &lt;a href="https://osm.org/go/0Ck2o6xg-" target="_blank" rel="noopener noreferrer"&gt;Campione d&amp;rsquo;Italia&lt;/a&gt; and &lt;a href="https://osm.org/go/0C1ZlDk" target="_blank" rel="noopener noreferrer"&gt;Büsingen am Hochrhein&lt;/a&gt;, respectively Italy and Germany. Both are &lt;em&gt;enclaves&lt;/em&gt; of their respective country in Swiss territory:&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;An enclave is a part of the territory of a state that is enclosed within the territory of another state. To distinguish the parts of a state entirely enclosed in a single other state, they are called true enclaves. A true enclave cannot be reached without passing through the territory of a single other state that surrounds it.&lt;/p&gt;</description></item><item><title>Build an AI Agent (From Scratch)</title><link>https://foojay.io/today/build-an-ai-agent-from-scratch/</link><pubDate>Mon, 07 Sep 2026 05:52:13 +0000</pubDate><guid>https://foojay.io/today/build-an-ai-agent-from-scratch/</guid><description>&lt;p&gt;This review is about &lt;a href="https://www.manning.com/books/build-an-ai-agent-from-scratch?utm_source=frankel&amp;amp;utm_medium=affiliate&amp;amp;utm_campaign=affiliate&amp;amp;a_aid=frankel" target="_blank" rel="noopener noreferrer"&gt;Build an AI Agent (From Scratch)&lt;/a&gt; by Jungjun Hur and Younghee Song from Manning.&lt;/p&gt;&#10;&lt;h2 id="facts"&gt;Facts&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;10 chapters&lt;/li&gt;&#10;&lt;li&gt;$29.29 (at the time of this writing)&lt;/li&gt;&#10;&lt;li&gt;315 pages&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="chapters"&gt;Chapters&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Building your first LLM agent&#10;&lt;ol&gt;&#10;&lt;li&gt;What is an AI agent?&lt;/li&gt;&#10;&lt;li&gt;The brain of AI agents: LLMs&lt;/li&gt;&#10;&lt;li&gt;Enabling actions: Tool use&lt;/li&gt;&#10;&lt;li&gt;Implementing a basic ReAct agent&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Developing advanced agent capabilities&#10;&lt;ol&gt;&#10;&lt;li&gt;Building knowledge bases with RAG&lt;/li&gt;&#10;&lt;li&gt;Adding memory to your agent&lt;/li&gt;&#10;&lt;li&gt;Planning and reflection for complex tasks&lt;/li&gt;&#10;&lt;li&gt;Empowering agents with code execution&lt;/li&gt;&#10;&lt;li&gt;Orchestrating multi-agent systems&lt;/li&gt;&#10;&lt;li&gt;Evaluating agents&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="pros-and-cons"&gt;Pros and cons&lt;/h2&gt;&#10;&lt;p&gt;At Manning, I consider the following two books to be references:&lt;/p&gt;</description></item><item><title>AI-assisted genealogy</title><link>https://foojay.io/today/ai-assisted-genealogy/</link><pubDate>Mon, 31 Aug 2026 05:51:48 +0000</pubDate><guid>https://foojay.io/today/ai-assisted-genealogy/</guid><description>&lt;p&gt;My son recently came to me to brag about using AI to find our ancestors. While the results were correct, I didn&amp;rsquo;t learn anything new, as it stopped at my grandparents. I was never very interested in my genealogy, but I decided to see if AI would be a good tool for this. TL;DR: Yes, it is, and even more than that. In a little less than one month, I managed to gather more than 600 individuals and get back 12 generations in some branches.&lt;/p&gt;</description></item><item><title>Solving Gradle metadata and Renovate integration</title><link>https://foojay.io/today/solving-gradle-metadata-and-renovate-integration/</link><pubDate>Wed, 19 Aug 2026 05:53:45 +0000</pubDate><guid>https://foojay.io/today/solving-gradle-metadata-and-renovate-integration/</guid><description>&lt;p&gt;My current company has settled on using Gradle. It doesn&amp;rsquo;t make me &lt;a href="https://blog.frankel.ch/final-take-gradle/" target="_blank" rel="noopener noreferrer"&gt;very happy&lt;/a&gt;, but you need to learn to work with constraints. Plus, I must admit that the developers who actually implemented the build files did a pretty good job overall: they used Kotlin instead of Groovy, they moved code to regular plugins, etc.&lt;/p&gt;&#10;&lt;p&gt;This week, I worked on improvements to a new project and set up Renovate. Renovate is similar to Dependabot in that it checks for new versions of your dependencies and automatically creates PRs for you. However, I quickly noticed that merges of new dependency versions failed the build. Here&amp;rsquo;s the full story on why, and how I fixed the issue.&lt;/p&gt;</description></item><item><title>GitHub agentic workflows and Renovate</title><link>https://foojay.io/today/github-agentic-workflows-and-renovate/</link><pubDate>Mon, 03 Aug 2026 05:54:08 +0000</pubDate><guid>https://foojay.io/today/github-agentic-workflows-and-renovate/</guid><description>&lt;p&gt;I&amp;rsquo;ve been a big fan of Renovate for &lt;a href="https://blog.frankel.ch/renovate-alternative-dependabot/" target="_blank" rel="noopener noreferrer"&gt;a couple of years already&lt;/a&gt;. Renovate scans your repositories, detects outdated package versions, and opens pull requests to automatically bump them. It&amp;rsquo;s similar to Dependabot in that it keeps your dependencies up to date. If I had to compare them in one sentence, I&amp;rsquo;d say Renovate is less integrated in the GitHub ecosystem, but handles more ecosystems and, more importantly, is extensible. My current company is a happy Renovate user, and I already started to use it in some repositories.&lt;/p&gt;</description></item><item><title>On programming languages, targets, and platforms</title><link>https://foojay.io/today/on-programming-languages-targets-and-platforms/</link><pubDate>Wed, 24 Jun 2026 17:22:32 +0000</pubDate><guid>https://foojay.io/today/on-programming-languages-targets-and-platforms/</guid><description>&lt;p&gt;I started as a Java developer, but for some time now, I have broadened my horizons. Recently, I thought about how early languages were dedicated to a single target and platform, and now they are broadening their focus. In this post, I want to write down my thoughts in the hope that it may be useful to others, probably to my future self.&lt;/p&gt;&#10;&lt;h2 id="definitions"&gt;Definitions&lt;/h2&gt;&#10;&lt;p&gt;You may have been wondering about the title terms. I&amp;rsquo;m pretty sure that if you read this post, you have a pretty good picture of what a programming language is. Some may disagree on some finer points or raise a hair-splitting one, but it&amp;rsquo;s not a PhD thesis, only a post on my blog. I must define what I mean by &lt;strong&gt;target&lt;/strong&gt; and &lt;strong&gt;platform&lt;/strong&gt; in the context of this post before going further.&lt;/p&gt;</description></item><item><title>Seasons time-lapse - the video</title><link>https://foojay.io/today/seasons-time-lapse-the-video/</link><pubDate>Tue, 09 Jun 2026 12:45:51 +0000</pubDate><guid>https://foojay.io/today/seasons-time-lapse-the-video/</guid><description>&lt;p&gt;In the &lt;a href="https://blog.frankel.ch/seasons-time-lapse/1/" target="_blank" rel="noopener noreferrer"&gt;first post&lt;/a&gt; of this series, I focused on the project foundations: what should I do to create a video from photos taken from the same position year after year? I dedicated the &lt;a href="https://blog.frankel.ch/seasons-time-lapse/2/" target="_blank" rel="noopener noreferrer"&gt;second part&lt;/a&gt; to aligning images. It wasn&amp;rsquo;t as easy as I expected. I stumbled upon new concepts, such as and .&lt;/p&gt;&#10;&lt;p&gt;In this third and final post, I want to tackle the video creation itself, explain some &amp;ldquo;artistic&amp;rdquo; decisions, and leave the door open to future work.&lt;/p&gt;</description></item><item><title>AI gateways: why and how</title><link>https://foojay.io/today/ai-gateways-why-and-how/</link><pubDate>Wed, 03 Jun 2026 08:38:19 +0000</pubDate><guid>https://foojay.io/today/ai-gateways-why-and-how/</guid><description>&lt;p&gt;Before working for 2 years on the Apache APISIX API gateway, I was mainly oblivious to API gateways. It&amp;rsquo;s only by working with them that I understood their value. Decoupling the client and the server unlocks a lot of options: &lt;a href="https://foojay.io/authentication-api-gateway/"&gt;moving authentication to the API Gateway&lt;/a&gt;, &lt;a href="https://foojay.io/secure-api-practices-apisix/1/"&gt;securing&lt;/a&gt; &lt;a href="https://foojay.io/secure-api-practices-apisix/2/"&gt;APIs&lt;/a&gt;, &lt;a href="https://foojay.io/implement-idempotency-key-apisix/"&gt;deduplicating API requests&lt;/a&gt;, etc.&lt;/p&gt;&#10;&lt;p&gt;In this post, I want to describe how the same pattern applies to AI.&lt;/p&gt;&#10;&lt;h2 id="ai-gateways"&gt;AI gateways&lt;/h2&gt;&#10;&lt;p&gt;AI gateways work in a similar way. They proxy requests and responses between an AI client and its LLM backend(s). Likewise, it unlocks many improvements:&lt;/p&gt;</description></item><item><title>Seasons time-lapse - alignment</title><link>https://foojay.io/today/seasons-time-lapse-alignment/</link><pubDate>Thu, 28 May 2026 16:28:48 +0000</pubDate><guid>https://foojay.io/today/seasons-time-lapse-alignment/</guid><description>&lt;p&gt;In the &lt;a href="https://blog.frankel.ch/seasons-time-lapse/1/" target="_blank" rel="noopener noreferrer"&gt;previous post&lt;/a&gt;, I described the Seasons project: a time-lapse of hundreds of pictures taken from nearly the same viewpoint over the years. The hardest challenge wasn&amp;rsquo;t taking the pictures or assembling them, but aligning them.&lt;/p&gt;&#10;&lt;p&gt;You might have noticed the &lt;em&gt;nearly&lt;/em&gt; part about viewpoint in the above paragraph. Indeed, it&amp;rsquo;s an approximation. I&amp;rsquo;m a human being, not a tripod. The position changes ever so slightly, and so does the exact angle. My phone has changed over the years, from a Samsung S10 to an S21, and now I&amp;rsquo;m using an iPhone 14 Pro. Each of them has a different camera with a different focal length. The resulting photos look similar but are definitely not identical: slightly different scales and angles. Without any correction, the landscape appears to be moving a lot.&lt;/p&gt;</description></item><item><title>Seasons time-lapse - the foundations</title><link>https://foojay.io/today/seasons-time-lapse-the-foundations/</link><pubDate>Thu, 21 May 2026 19:56:04 +0000</pubDate><guid>https://foojay.io/today/seasons-time-lapse-the-foundations/</guid><description>&lt;p&gt;I live close to nature. I regularly go for a run in the countryside. Over several years, during my runs, I&amp;rsquo;ve taken pictures from the same position, always roughly the same angle. I had a vague idea in the back of my mind, as an &amp;ldquo;artistic&amp;rdquo; project. One day, I&amp;rsquo;d turn those photos into a time-lapse video, one that would show the passage of seasons across a single place.&lt;/p&gt;&#10;&lt;p&gt;Spoiler, here&amp;rsquo;s the work in progress:&lt;/p&gt;</description></item><item><title>Tokensparsamkeit for coding assistants</title><link>https://foojay.io/today/tokensparsamkeit-for-coding-assistants/</link><pubDate>Wed, 13 May 2026 08:24:31 +0000</pubDate><guid>https://foojay.io/today/tokensparsamkeit-for-coding-assistants/</guid><description>&lt;p&gt;You make decisions with data. Most businesses assumed that the most data, the better the decision. Then, several factors put a halt to the hoarding of always more data. and its localized counterparts, and the cost of storage. However, before it happened, the Datensparsamkeit approach already existed.&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;Datensparsamkeit is a German word that&amp;rsquo;s difficult to translate properly into English. It&amp;rsquo;s an attitude to how we capture and store data, saying that we should only handle data that we really need.&lt;/p&gt;</description></item><item><title>Designing a team of agents</title><link>https://foojay.io/today/designing-a-team-of-agents/</link><pubDate>Thu, 07 May 2026 20:00:48 +0000</pubDate><guid>https://foojay.io/today/designing-a-team-of-agents/</guid><description>&lt;p&gt;I continue to experiment with AI in the context of software engineering. I&amp;rsquo;m fortunate that my team supports me in exploring different ways to improve our daily work. This week, I designed a team of &lt;strong&gt;autonomous&lt;/strong&gt; agents to implement features, from design to implementation.&lt;/p&gt;&#10;&lt;h2 id="why-autonomous-agents"&gt;Why autonomous agents?&lt;/h2&gt;&#10;&lt;p&gt;A long time ago, we were delighted when the IDE offered auto-completion. In the previous two years, things have changed. A lot.&lt;/p&gt;&#10;&lt;p&gt;Coding assistants have become our primary interfaces for coding. We still use IDEs, at least I do. Yet, I had an IDE licensing issue two weeks ago, and I continued to code even without it. The assistant automatically compiles and tests after every change. While it was forced on me, I believe it could be a valuable test for seasoned programmers: can you replace your IDE with your coding assistant, or are they complementary?&lt;/p&gt;</description></item><item><title>Three Mastodon issues because of Cloudflare Bot protection</title><link>https://foojay.io/today/three-mastodon-issues-because-of-cloudflare-bot-protection/</link><pubDate>Mon, 27 Apr 2026 18:56:21 +0000</pubDate><guid>https://foojay.io/today/three-mastodon-issues-because-of-cloudflare-bot-protection/</guid><description>&lt;p&gt;I noticed some time ago that three &lt;a href="https://mastodon.top/@frankel" target="_blank" rel="noopener noreferrer"&gt;Mastodon&lt;/a&gt; features had stopped working on my blog. Each of them seemed like a separate problem, but they had the same root cause. In this blog post, I want to describe these issues and the simple fix.&lt;/p&gt;&#10;&lt;h2 id="domain-verification"&gt;Domain verification&lt;/h2&gt;&#10;&lt;p&gt;Mastodon allows you to prove that you own a domain. The mechanism requires two steps:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Add a &lt;code&gt;&amp;lt;link rel=&amp;quot;me&amp;quot;&amp;gt;&lt;/code&gt; tag in your pages, pointing to your Mastodon profile&lt;/li&gt;&#10;&lt;li&gt;Add your website URL to your Mastodon profile&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;When Mastodon crawls your page and finds the backlink, it displays a green checkmark next to your URL in your profile.&lt;/p&gt;</description></item><item><title>Making illegal state unrepresentable</title><link>https://foojay.io/today/making-illegal-state-unrepresentable/</link><pubDate>Tue, 21 Apr 2026 18:50:02 +0000</pubDate><guid>https://foojay.io/today/making-illegal-state-unrepresentable/</guid><description>&lt;p&gt;A couple of years ago, I wrote that &lt;a href="https://blog.frankel.ch/builder-pattern-finite-state-machine/" target="_blank" rel="noopener noreferrer"&gt;The Builder pattern is a finite state machine!&lt;/a&gt;. A state machine consists of states and transitions between them. As a developer, I want to make illegal states unrepresentable, &lt;em&gt;i.e.&lt;/em&gt;, users of my API can&amp;rsquo;t create non-existent transitions. My hypothesis is that only a static typing system allows this at compile-time. Dynamic typing systems rely on runtime validation.&lt;/p&gt;&#10;&lt;p&gt;In this blog post, I will show that it holds true, with a caveat. If your model has many combinations, you also need generics and other niceties to avoid too much boilerplate code. My exploration will use Python, Java, Kotlin, Rust, and Gleam. With that background in mind, let&amp;rsquo;s move on to the model itself.&lt;/p&gt;</description></item><item><title>A GitHub agentic workflow</title><link>https://foojay.io/today/a-github-agentic-workflow/</link><pubDate>Tue, 14 Apr 2026 14:31:26 +0000</pubDate><guid>https://foojay.io/today/a-github-agentic-workflow/</guid><description>&lt;p&gt;Last month, I became aware of &lt;a href="https://github.github.com/gh-aw/" target="_blank" rel="noopener noreferrer"&gt;GitHub agentic workflows&lt;/a&gt;. I read the site carefully, but the use cases weren&amp;rsquo;t very exciting to me. I tried the &lt;a href="https://github.github.com/gh-aw/blog/2026-01-13-meet-the-workflows-documentation/" target="_blank" rel="noopener noreferrer"&gt;continuous documentation&lt;/a&gt; It didn&amp;rsquo;t work out initially, and because of my lack of involvement, I left it as it was. However, I succeeded in another one that I want to describe in this post.&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; With lessons learned here, I managed to make the documentation workflow work! Every relevant change now creates a new PR, which reflects the changes in the &lt;code&gt;README&lt;/code&gt;, the wiki, Copilot&amp;rsquo;s &lt;code&gt;instructions.md&lt;/code&gt;, and the changelog.&lt;/p&gt;</description></item><item><title>Experimenting with AI subagents</title><link>https://foojay.io/today/experimenting-with-ai-subagents/</link><pubDate>Tue, 07 Apr 2026 11:58:05 +0000</pubDate><guid>https://foojay.io/today/experimenting-with-ai-subagents/</guid><description>&lt;p&gt;I like to analyze codebases I start working on, or that I left for months. I ask my coding assistant, case in point, Copilot CLI: &amp;ldquo;analyze the following codebase and report to me improvements and possible bugs.&amp;rdquo; It&amp;rsquo;s vague enough to leave room for crappy feedback, but also for some interesting insights.&lt;/p&gt;&#10;&lt;p&gt;I did it last week on a code base. Copilot returned a list of a dozen items. I asked it to create a GitHub issue for each, with the relevant labels, including priority.&lt;/p&gt;</description></item><item><title>One tip for successful OpenTelemetry projects</title><link>https://foojay.io/today/one-tip-for-successful-opentelemetry-projects/</link><pubDate>Tue, 31 Mar 2026 17:45:56 +0000</pubDate><guid>https://foojay.io/today/one-tip-for-successful-opentelemetry-projects/</guid><description>&lt;p&gt;Leading your organization to use OpenTelemetry is a challenge. In addition to all the usual project hurdles, you&amp;rsquo;ll face one of these two situations: convince your teams to use OpenTelemetry, or convince them to move from the telemetry tool they are already using to OpenTelemetry. Most people don&amp;rsquo;t want to change. You&amp;rsquo;ll need lots of effort and baby steps. My tip is the following: the fewer the changes, the higher your chances of success. In this post, I want to tackle a real-world use case and describe which tools you can leverage to reduce the necessary changes.&lt;/p&gt;</description></item><item><title>The Software Architect Elevator</title><link>https://foojay.io/today/the-software-architect-elevator/</link><pubDate>Tue, 24 Mar 2026 20:28:33 +0000</pubDate><guid>https://foojay.io/today/the-software-architect-elevator/</guid><description>&lt;p&gt;I don&amp;rsquo;t think it&amp;rsquo;s necessary to introduce Gregor Hohpe. I&amp;rsquo;m a big fan, having read &lt;a href="https://www.enterpriseintegrationpatterns.com/" target="_blank" rel="noopener noreferrer"&gt;Enterprise Integration Patterns&lt;/a&gt;, and I&amp;rsquo;ve recommended the book ever since. When I spoke at the &lt;a href="https://conferences.isaqb.org/software-architecture-gathering/session/make-your-security-policy-auditable/" target="_blank" rel="noopener noreferrer"&gt;Software Architecture Gathering&lt;/a&gt; in 2024, I was fortunate enough to meet him and purchase this book. I&amp;rsquo;m the happy owner of a signed copy.&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;Modern architects don&amp;rsquo;t try to be the smartest people in the room–they make everyone else smarter. They ride the &lt;em&gt;Architect Elevator&lt;/em&gt; from the penthouse, where the business strategy is set, to the engine room, where the enabling technologies are implemented. They shun popular buzzwords in favor of decision discipline and clear communication across levels.&lt;/p&gt;</description></item><item><title>Writing an agent skill</title><link>https://foojay.io/today/writing-an-agent-skill/</link><pubDate>Tue, 17 Mar 2026 15:36:30 +0000</pubDate><guid>https://foojay.io/today/writing-an-agent-skill/</guid><description>&lt;p&gt;Most developers now use coding assistants. I do too—Copilot at work, Claude Code at home. As a developer, I prefer not to repeat myself. This post explains why and how to avoid repetition as a skill.&lt;/p&gt;&#10;&lt;h2 id="dont-repeat-yourself"&gt;Don&amp;rsquo;t Repeat Yourself&lt;/h2&gt;&#10;&lt;p&gt;The principle has been present in the software development field for ages. The idea is that if you copy and paste code in multiple places and a bug appears, you&amp;rsquo;ll need to fix the bug in all these places. The more the number of duplications, the more chances you&amp;rsquo;ll miss one of them when fixing.&lt;/p&gt;</description></item><item><title>Pi-hole behind Tailscale</title><link>https://foojay.io/today/pi-hole-behind-tailscale/</link><pubDate>Wed, 11 Mar 2026 18:20:08 +0000</pubDate><guid>https://foojay.io/today/pi-hole-behind-tailscale/</guid><description>&lt;p&gt;As I age, I become increasingly cautious about my privacy. The slope the world is sliding on is also a big, unfortunate incentive. I have been eying Pi-hole for some time: in this post, I want to explain what it does, how to install it on a &lt;a href="https://www.raspberrypi.com/" target="_blank" rel="noopener noreferrer"&gt;Raspberry Pi&lt;/a&gt;, and how to integrate it with &lt;a href="https://tailscale.com/" target="_blank" rel="noopener noreferrer"&gt;Tailscale&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="my-take-on-privacy"&gt;My take on privacy&lt;/h2&gt;&#10;&lt;p&gt;Privacy, or more specifically &lt;em&gt;digital privacy&lt;/em&gt;, is the ability to protect oneself from the constant data collection by legitimate companies and malicious actors alike when online. Given that going online represents the bulk nowadays, if not the entirety, of one&amp;rsquo;s activity on a digital system, it&amp;rsquo;s a constant battle. Moreover, some places are more or less inclined to protect their people&amp;rsquo;s privacy. I&amp;rsquo;m quite safe in the European Union, and my Californian friends enjoy a similar level of privacy by law.&lt;/p&gt;</description></item><item><title>JVM timing options</title><link>https://foojay.io/today/jvm-timing-options/</link><pubDate>Mon, 23 Feb 2026 16:45:39 +0000</pubDate><guid>https://foojay.io/today/jvm-timing-options/</guid><description>&lt;p&gt;For as long as I have been coding in Java, we have had requirements to measure the execution time of blocks of code. While the current good practice is to use OpenTelemetry&amp;rsquo;s traces, not every company has reached this stage yet. Plus, some of the alternatives are OpenTelemetry-compatible. Let&amp;rsquo;s see them in order.&lt;/p&gt;&#10;&lt;h2 id="the-basic-option"&gt;The basic option&lt;/h2&gt;&#10;&lt;p&gt;The basic option is what we have been doing for ages, and what the other options rely on anyway. It&amp;rsquo;s based on the following API: &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#currentTimeMillis" target="_blank" rel="noopener noreferrer"&gt;System.currentTimeMillis()&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Migrating from Jekyll to Hugo... or not</title><link>https://foojay.io/today/migrating-from-jekyll-to-hugo-or-not/</link><pubDate>Wed, 18 Feb 2026 19:29:45 +0000</pubDate><guid>https://foojay.io/today/migrating-from-jekyll-to-hugo-or-not/</guid><description>&lt;p&gt;Most of my blog posts are lessons learned. I&amp;rsquo;m trying to achieve something, and I document the process I used to do it. This one is one of the few where, in the end, I didn&amp;rsquo;t achieve what I wanted. In this post, I aim to explain what I learned from trying to migrate from Jekyll to Hugo, and why, in the end, I didn&amp;rsquo;t take the final step.&lt;/p&gt;&#10;&lt;h2 id="context"&gt;Context&lt;/h2&gt;&#10;&lt;p&gt;I started this blog on WordPress. After several years, I decided to &lt;a href="https://blog.frankel.ch/managing-publications-jekyll/" target="_blank" rel="noopener noreferrer"&gt;migrate to Jekyll&lt;/a&gt;. I have been happy with &lt;a href="https://jekyllrb.com/" target="_blank" rel="noopener noreferrer"&gt;Jekyll&lt;/a&gt; so far. It&amp;rsquo;s based on Ruby, and though I&amp;rsquo;m no Ruby developer, I was able to create a few plugins.&lt;/p&gt;</description></item><item><title>From a JAR to a full-fledged MacOS app</title><link>https://foojay.io/today/from-a-jar-to-a-full-fledged-macos-app/</link><pubDate>Thu, 05 Feb 2026 10:15:05 +0000</pubDate><guid>https://foojay.io/today/from-a-jar-to-a-full-fledged-macos-app/</guid><description>&lt;p&gt;A couple of years ago, I developed a small &lt;a href="https://blog.frankel.ch/state-jvm-desktop-frameworks/2/" target="_blank" rel="noopener noreferrer"&gt;Kotlin GUI&lt;/a&gt; to help me rename my files in batch. I actually created it with &lt;a href="https://blog.frankel.ch/focus/state-jvm-desktop-frameworks/" target="_blank" rel="noopener noreferrer"&gt;different JVM frameworks&lt;/a&gt; to compare their relative merits. In any case, I didn&amp;rsquo;t use it up until last week. And then, I was surprised to see that it didn&amp;rsquo;t work to rename a network volume, although it had in the past. In this brief post, I aim to describe the issue and its solution.&lt;/p&gt;</description></item><item><title>Feedback on checked exceptions and lambdas</title><link>https://foojay.io/today/feedback-on-checked-exceptions-and-lambdas/</link><pubDate>Mon, 02 Feb 2026 18:29:03 +0000</pubDate><guid>https://foojay.io/today/feedback-on-checked-exceptions-and-lambdas/</guid><description>&lt;p&gt;I got a lot of interesting feedback on &lt;a href="https://blog.frankel.ch/checked-exceptions-lambdas/" target="_blank" rel="noopener noreferrer"&gt;Checked exceptions and lambdas&lt;/a&gt;. Let&amp;rsquo;s start with my own: after writing the post, I realized I had written a &lt;a href="https://blog.frankel.ch/exceptions-lambdas/" target="_blank" rel="noopener noreferrer"&gt;similar post&lt;/a&gt; some time ago.&lt;/p&gt;&#10;&lt;h2 id="mistakes-i-made"&gt;Mistakes I made&lt;/h2&gt;&#10;&lt;p&gt;I made a mistake in the code regarding Apache Commons Lang 3, where I mistakenly used the &lt;code&gt;recover()&lt;/code&gt; function, which is actually from Vavr.&lt;/p&gt;&#10;&lt;p&gt;Apache Commons Lang provides a regular utility function, which mimics the custom code we wrote last week. Vavr offers the &lt;code&gt;Try&lt;/code&gt; class, which encapsulates methods that throw checked exceptions. It also bridges Java to a more functional style.&lt;/p&gt;</description></item><item><title>Checked exceptions and lambdas</title><link>https://foojay.io/today/checked-exceptions-and-lambdas/</link><pubDate>Mon, 19 Jan 2026 09:00:29 +0000</pubDate><guid>https://foojay.io/today/checked-exceptions-and-lambdas/</guid><description>&lt;p&gt;Java&amp;rsquo;s checked exceptions were a massive improvement over C&amp;rsquo;s error-handling mechanism. As time passed and experience accumulated, we collectively concluded that we weren&amp;rsquo;t there yet. However, Java&amp;rsquo;s focus on stability has kept checked exceptions in its existing API.&lt;/p&gt;&#10;&lt;p&gt;Java 8 brought lambdas after the &amp;ldquo;checked exceptions are great&amp;rdquo; trend. None of the functional interface methods accepts a checked exception. In this post, I will demonstrate three different approaches to making your legacy exception-throwing code compatible with lambdas.&lt;/p&gt;</description></item><item><title>From Cloudflare Zero-trust to Tailscale</title><link>https://foojay.io/today/from-cloudflare-zero-trust-to-tailscale/</link><pubDate>Mon, 12 Jan 2026 20:04:31 +0000</pubDate><guid>https://foojay.io/today/from-cloudflare-zero-trust-to-tailscale/</guid><description>&lt;p&gt;I have spent some time last year implementing &lt;a href="https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/" target="_blank" rel="noopener noreferrer"&gt;Cloudflare Tunnels&lt;/a&gt; on my &lt;a href="https://blog.frankel.ch/home-assistant/6/" target="_blank" rel="noopener noreferrer"&gt;Home Assistant&lt;/a&gt; and my &lt;a href="https://blog.frankel.ch/second-cloudflare-tunnel/" target="_blank" rel="noopener noreferrer"&gt;Synology NAS&lt;/a&gt;. On Mastodon, I had not one but two commenters advertising for Tailscale:&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://mastodon.top/@frankel/115639107167365460" target="_blank" rel="noopener noreferrer"&gt;https://mastodon.top/@frankel/115639107167365460&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;I decided to give it a try and migrate my servers and devices to Tailscale. In this post, I want to describe how I did. Thanks to Heiko Does and higgins for prompting me to look further!&lt;/p&gt;&#10;&lt;h2 id="what-is-tailscale-how-and-why"&gt;What is Tailscale, how and why?&lt;/h2&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;A Zero Trust identity-based connectivity platform that replaces your legacy VPN, SASE, and PAM and connects remote teams, multi-cloud environments, CI/CD pipelines, Edge &amp;amp; IoT devices, and AI workloads.&lt;/p&gt;</description></item><item><title>2025 in retrospective</title><link>https://foojay.io/today/2025-in-retrospective/</link><pubDate>Mon, 05 Jan 2026 11:44:20 +0000</pubDate><guid>https://foojay.io/today/2025-in-retrospective/</guid><description>&lt;p&gt;From the beginning, the focus of this blog has been technical, very rarely organizational. I broke this unwritten rule &lt;a href="https://blog.frankel.ch/je-suis-charlie/" target="_blank" rel="noopener noreferrer"&gt;once&lt;/a&gt; in 2015. I began writing retrospectives in 2023 on the year that had passed. Let&amp;rsquo;s continue the tradition, but with a wider scope than before. The situation warrants it.&lt;/p&gt;&#10;&lt;h2 id="more-chaos"&gt;More chaos&lt;/h2&gt;&#10;&lt;p&gt;It&amp;rsquo;s a hard realization to admit, but the world is spiraling deeper and deeper into chaos. Russia&amp;rsquo;s invasion of Ukraine has now dragged into its third year, and still, neither the European Union nor NATO has mustered the resolve to intervene militarily. Every day brings fresh reports of Russian war crimes, met only with our silent complicity. The strongest response we seem capable of is to &amp;ldquo;strongly condemn.&amp;rdquo;&lt;/p&gt;</description></item><item><title>YOW! 2025</title><link>https://foojay.io/today/yow-2025/</link><pubDate>Wed, 17 Dec 2025 08:59:55 +0000</pubDate><guid>https://foojay.io/today/yow-2025/</guid><description>&lt;p&gt;I have been eyeing the &lt;a href="https://yowcon.com/" target="_blank" rel="noopener noreferrer"&gt;YOW!&lt;/a&gt; conferences for probably more than a decade. They occur in Australia, and feature top industry experts. I was thus overjoyed when they invited me to speak on the YOW! tour earlier this year. Here&amp;rsquo;s a summary of my amazing time there.&lt;/p&gt;&#10;&lt;h2 id="my-participation"&gt;My participation&lt;/h2&gt;&#10;&lt;p&gt;YOW! takes place in three different cities:]Melbourne, Brisbane, and Sidney. I presented my brand new talk on &lt;a href="https://yowcon.com/melbourne-2025/sessions/3613/webassembly-on-kubernetes" target="_blank" rel="noopener noreferrer"&gt;WebAssembly on Kubernetes&lt;/a&gt; in each city. It stems from an &lt;a href="https://blog.frankel.ch/webassembly-kubernetes/" target="_blank" rel="noopener noreferrer"&gt;earlier article&lt;/a&gt;, which I reworked and updated. YOW! will probably release the video soon.&lt;/p&gt;</description></item><item><title>My second Cloudflare Tunnel</title><link>https://foojay.io/today/my-second-cloudflare-tunnel/</link><pubDate>Tue, 02 Dec 2025 20:59:58 +0000</pubDate><guid>https://foojay.io/today/my-second-cloudflare-tunnel/</guid><description>&lt;p&gt;I decided to stop using Twitter, but for my own content and supporting Ukraine against its barbarian invaders, I understood the contemporary media landscape was quite fragmented. I bet on Mastodon, Bluesky, and LinkedIn. My flow is the following: when I read a piece I find interesting, I schedule it for publication. The problem is that every social media platform has a different scheduler: Mastodon has the &lt;a href="https://www.scheduler.mastodon.tools/" target="_blank" rel="noopener noreferrer"&gt;Mastodon scheduler&lt;/a&gt;, LinkedIn has an in-built feature, and Bluesky has&amp;hellip; nothing. I had enough.&lt;/p&gt;</description></item><item><title>My first real Rust project</title><link>https://foojay.io/today/my-first-real-rust-project/</link><pubDate>Tue, 25 Nov 2025 17:03:42 +0000</pubDate><guid>https://foojay.io/today/my-first-real-rust-project/</guid><description>&lt;p&gt;I have been learning Rust for a couple of years, and using it for pet projects and &lt;a href="https://github.com/nfrankel/opentelemetry-tracing/tree/master/inventory" target="_blank" rel="noopener noreferrer"&gt;demos&lt;/a&gt; alike. Working for a JVM-heavy company, I thought it would be my fate forever. Last week, I had a nice surprise: I convinced my management that using Rust for a particular project was the right choice. It&amp;rsquo;s not a huge project, but I want to describe my experience using Rust in a &amp;ldquo;real&amp;rdquo; project.&lt;/p&gt;</description></item></channel></rss>