While managing concurrency solves rate-limiting issues, another silent budget-killer remains: unresponsive, frozen code.
Continue reading →
While working on a Spring Boot 4 service using Java 25, I wanted to protect my external API calls as these can go down every now and then.
For this I used Resilience4j @CircuitBreaker and @Retry annotations, and put a @Cacheable on top.
Three annotations stacked on a single method, what could possibly go wrong?
It turns out that the order in which they are applied by default is probably not the one you want.
This makes your circuit breaker count every retry attempt as a separate failure.
And once the circuit opens it even blocks data that is sitting right there in your cache.
Here is what happens by default, and how I changed it.
Continue reading →
In our projects we have been using ArchUnit for years to write unit tests that fail when the code no longer follows the architecture we chose.
Over the last year, we’ve written more and more of these tests.
What changed? Our audience grew.
These tests no longer just help fellow developers stick to the architecture; they help our coding agents too.
Coding agents are getting quite good at making larger changes to existing codebases.
Give an agent a task, some context and a test suite, and it often finds its way surprisingly well.
But one type of context is much harder to provide: the architecture we intended.
That is exactly the gap ArchUnit fills.
In this blog post I explain why ArchUnit becomes more valuable when working with coding agents, and I show some rules that actually help to guide them.
The list is far from complete, but I hope it inspires you to capture your own architecture in rules, whether you write them yourself or let your agent do it.
Continue reading →
In my journey away from the mouse and trackpad, I found Neovim recommended often.
Having developed in Java for over 13 years, I’ve relied heavily on IDEs like IntelliJ or NetBeans for most of that time.
I decided to step outside those walls to see what lay beyond.
Continue reading →
Since Java 9 the methods requireNonNullElse and requireNonNullElseGet are part of the java.util.Objects class. The method requireNonNullElse accepts two arguments. The first argument is an object that will be returned if that object is not null. The second argument is an object to be returned when the first argument is null. With this method you can replace the following ternary operator if (a != null) ? a : b (or if (a == null) ? b : a) with Objects.requireNonNullElse(a, b).
The method requireNonNullElseGet allows to define a Supplier function as second argument. The Supplier is only invoked when the first argument is null, so it is lazy and will only be invoked when the first argument is null.
Continue reading →
Kotlin is null-safe, a quote I hear often from Kotlin developers.
And yet, I still managed to get a NullPointerException while converting a java.util.Optional to a nullable Kotlin value…
Continue reading →
Java and Python are both excellent tools, and even though programmers usually like nothing better
than debating which language, framework, or editor is best, that is not the goal of this post. Each
language has strengths and weaknesses, but what I consider interesting is that Java and Python
complement each other so well. However, systems using multiple languages face increased
complexity in deployment, maintenance, testing, integration, and interoperability.
This post aims to answer two main questions through a set of practical hands-on
experiments.
Continue reading →
SDKMAN! is as powerful tool to install and manage software development kits (SDKs) and tools, like Java, Groovy, Gradle, Maven, Spring Boot and Quarkus. If you want to see if a new version of a SDK or tool is available, you can use the sdk upgrade command. This command will list all outdated SDKs and tools. The installed version and the latest version are shown for each SDK and tool. To see if a single SDK or tool is outdated, you can use the name of the SDK or tool as argument to the sdk upgrade command.
Continue reading →
When you enable the /observe endpoints you can configure them to be served on a different port than the application. By default the endpoints are available on the same port as the application. But you can define an extra named socket with another port number in the configuration of the WebServer instance. And in the configuration of the ObserveFeature instance you can define the socket name that should be used for the observe endpoints.
Continue reading →
In a previous post you learned how to add information to the /observe/info endpoint. You can also add Git information to the endpoint. For example you can add the Git commit id so you can see check, when the application is running in a production environment, which Git commit for the code was deployed. In order to achieve this you must first generate a properties file with all Git information. The next step is to process this file in your Helidon SE application and add the properties to the /observe/info endpoint.
Continue reading →
It is possible to add an endpoint to Helidon SE that can show information about the application. You can add custom information to this endpoint. In order to enable the endpoint you need to add the dependency io.helidon.webserver.observe:helidon-webserver-observe-info to your pom.xml file. This will add the endpoint /observe/info to your application. You can add key-value pairs to your configuration or code that will be exposed in the endpoint.
Continue reading →
You can configure a memory health check in Helidon SE. A memory health check will return a status of UP if the memory usage is below a certain threshold percentage and DOWN if the memory usage is above the threshold percentage. The default threshold percentage is 98%. To add the memory health check you need to add the dependency io.helidon.health:helidon-health-checks to your pom.xml file. This dependency contains three health checks: disk space usage, memory usage and dead lock detection.
To configure the memory health check you need to set the configuration property server.features.observe.observers.health.helidon.health.memory.thresholdPercent to the threshold percentage. Alternatively you can set the threshold percentage in your application code.
Continue reading →