Apparently the starterkit for getting started with Jakarta has been updated to Jakarta 11 and can be found at https://start.jakarta.ee/.
Thursday, 13 August 2026
Thursday, 30 July 2026
Adding snippets of code in JavaDoc
Recently saw a short of the always impressive [1] José Paumard.
It shows how to add snippets of code to your javadoc, and also add those snippets of code to your test suite.
I didn't know how to add them in Maven, but the reference [2] was be helpful.
So, first of all, we need, like, "production code" that refers to code snippets in the JavaDoc. In the example below there are both an inline snippet as well as a reference to a snippet elsewhere.
Then we have to define our external snippet for getAddress() as referred to above, inside AddressTest with appropriate zones.
Now this AddressTest is part of a Maven project, and is available in the src/test/java directory, as you would expect. So we need to provide this directory in the pom.xml via --snippet-path, as follows:
In the javadoc, when you generate it using "mvn javadoc:javadoc" it will look as follows:
The great part is that the Unit test also is regularly run.
I like it a lot!
P.S. the @snippet and assorted JavaDoc tags have a plethora of different options. For example for highlighting code.
References
- [1] How can you add a snippet of code in your JavaDoc? - Cracking the Java Coding Interview
- https://www.youtube.com/shorts/ZNe_-Z1qxp8
- [2] Configuring Maven For Compiled And Tested Code In Javadoc
- https://nipafx.dev/javadoc-snippets-maven/
- [3] Oracle Java - 3 Programmer's Guide to Snippets
- https://docs.oracle.com/en/java/javase/22/javadoc/programmers-guide-snippets.html
- Baeldung - Code Snippets in Java API Documentation
- https://www.baeldung.com/java-doc-code-snippets
Tuesday, 21 July 2026
GraalVM 25.1 Innovation
In short for those of us who want to stay on the lts, there's GraalVM 25.
And for those who want new things in incremental releases for testing, there's GraalVM 25.1 Innovation.
References
- Medium.com - GraalVM 25.1 is here! 🎉
- https://medium.com/graalvm/graalvm-25-1-is-here-13829606982e
Thursday, 4 June 2026
Angular Signals
Angular introduced Signals1 in Angular 17. You can find a mention of it in the release notes3 along with other fantastic goodies. From what I hear it's a big thing that solves some of the problems with updating two-way data-bindings without having to go through the entire tree of components and examining all the state (wich zone.js used to do.)
However, it's not a one-size-fits-all. Observables are still highly relevant, it's just that sometimes you use Signals and sometimes you use Observables2.
From what I gather, Signals can be used for highly synchronous code and one of those is to use them in the UI. Where Observables are convenient if the value is not immediately available (so time-based) like with REST calls.
You can learn about it all and try it out at [4], apparently.
There's plenty of youtube videos out there that introduce the concept too, apparently.
References
- [1] Angular - Angular Signals
- https://angular.dev/guide/signals
- [2] Medium - Angular Signals: Best Practices
- https://medium.com/@eugeniyoz/angular-signals-best-practices-9ac837ab1cec
- [3] Angular Blog - Introducing Angular v17
- https://blog.angular.dev/introducing-angular-v17-4d7033312e4b
- [4] Angular Home
- https://angular.dev/
Monday, 25 May 2026
Azul completed its acquisition of Payara in December 2025
Azul, the guys from the Zulu JDK, has aquired Payara.
I thought I'd mention it here, as I am using Payara in my hobby project.
There's a message on what it means for the Community version of Payara at [1] on https://foojay.io.
References
- [1] foojay.io - A New Chapter for the Payara Community
- https://foojay.io/today/a-new-chapter-for-the-payara-community/
Saturday, 11 April 2026
Desktop Icons on GNOME
GNOME has traditionally always been one to prefer the benefits of a clean Desktop.
But I'm not one for traditions.
GNOME Extensions
There's an GNOME extention available called Desktop Icons NG (DIN)1.
If you have installed it, you can see if you properly have it by "gnome-extensions show ding@rastersoft.com".
Once you install it, you can query to see if it is enabled using "gnome-extensions list --enabled", it should contain at least ding@rastersoft.com
Enabling it would probably help: "gnome-extensions enable ding@rastersoft.com" if it's not there.
You're likely to have to logout and log back in, to load extensions.
Extra steps
What I needed to do was:
- copy the application file (thingy.desktop) from /usr/share/applications somewhere and then drag it onto my Desktop.
- Make it Executable
- Set it to "Allow launching"
References
- [1] Desktop Icons NG (DING) by rastersoft
- https://extensions.gnome.org/extension/2087/desktop-icons-ng-ding/
Wednesday, 8 April 2026
VoxxedDays 2026
So, I went to VoxxedDays on April 1st and 2nd.1
Some of it was very interesting, and I've retained some notes and links written below.
- Spec-driven development2
- It seems to be a way to specify the wanted behaviour of your software in such a way that AI can successfully create your software based on your spec. Not entirely convinced of this.
- Lion3
- Lion is a set of highly performant, accessible and flexible Web Components.
- PicNic4
PicNic is a online greengrocer/supermarket which is running a Blog on the challenges on scaling up. Quite interesting.
Some interesting things for example are providing fresh products (bread for instance) within a certain timeframe.
- Programming Rules your IDE can tell you about.
- https://github.com/jborgers/PMD-jPinpoint-rules
- Compressed OOPs in the JVM
- https://www.baeldung.com/jvm-compressed-oops
- A good explanation of generics
- https://bramjanssens.nl/generics/
- Reduce Object Header Size and Save Memory in Java 25
- https://www.baeldung.com/java-object-header-reduced-size-save-memory
The sessions are online now at YouTube. See [5].
References
- [1] VoxxedDays Amsterdam
- https://amsterdam.voxxeddays.com/
- [2] What Is Spec-Driven Development? A Complete Guide
- https://www.augmentcode.com/guides/what-is-spec-driven-development
- [3] Github - Ing/Lion
- https://github.com/ing-bank/lion
- [4] PicNic - Blog
- https://blog.picnic.nl/
- [5] YouTube - VoxxedDays 2026 Sessions
- https://youtube.com/playlist?list=PLRsbF2sD7JVoK114W2u9HTK4ftHn_taT1&si=WmiCtfuhEyTtu0lg
Monday, 16 March 2026
Kotlin: lots of functions
I like Kotlin (sometimes) as it has a large and rich number of convenient functions to use.
In Java, we tend to reach for our Guava1 or Apache Commons Lang2 to get the same functionality.
But it does tend to make it a bit hard to decide which to use, especially as I (as most people I hope) do not know the entire dictionary of available functions in Kotlin.
Luckily there's of course colleagues who can help, and my IDE also does a pretty good task of suggesting better ways.
Case in point:
val coupon: Coupon? = items.map { it.coupon }.filter { it != null }.firstOrNull()
I do know the code above can be made simpler.
val coupon: Coupon? = items.mapNotNull { it.coupon }.firstOrNull()
There, the mapNotNull() is a very convenient function that I use all the time.
But this time my IDE complained again and told me to use .firstNotNullOfOrNull
val coupon: Coupon? = items.firstNotNullOfOrNull { it.coupon }
It's fine by me, to use this, but I didn't know this function exists.
Also, the name seems a bit long and it took a minute to understand the meaning.
References
- [1] GitHub - Google Guava
- https://github.com/google/guava
- [2] Maven Repository - Apache Commons Lang (3)
- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
Thursday, 12 February 2026
AssertJ + AutoCloseableSoftAssertions + Kotlin
I've been playing around with AutoCloseableSoftAssertions, as I don't want to have to remind myself to call .assertAll()
But I also wanted to see if I can replace entire rows of assertThat statements in a simple manner, without many changes.
And I think I have found a way in Kotlin.
Let's start with the basics:
Let's try some SoftAssertions, so we can have many asserts that are all evaluated, instead of the Test stopping upon the first failed assert.
Okay, now AutoCloseableSoftAssertions is a convenient class that calls the .assertAll() as part of the final block in a try-with-resources:
Now, in the case above, we have to prefix our assertThat() calls with "it.". There's one more step that we can use to remove this.
Wrapping all this in a function for easy use will end up in:
Now, a stack of assertThat() statements can be encompassed with assertAll{} without any other changes to get the full advantages of SoftAssertions.
Might be overkill, but this was a fun example in Kotlin.
Try-with-resources
So you might have noticed that AutoClosableSoftAssertions is used in a try-with-resources block.
The small advantage you have, is that if there is an unexpected Exception thrown during your asserts, the ".assertAll()" will still be called, because it's part of the "AutoCloseable.close()".
I don't know how much this advantage is, as the unexpected Exception breaks the test anyways, but there it is.
Thursday, 5 February 2026
Retrieving Bookmarks from your Firefox - The Hard Way
Yeah, so I turned my old workstation into a server and no longer have access using a graphical interface.
Normally, this is fine, as I am using it as a server.
But I forgot to export my Firefox bookmarks.
Hopefully I can examine the sqllite database using reference [1] to retrieve my bookmarks.
I open the file /home/mrbear/.mozilla/firefox/xvosm5y9.default/places.sqlite and selecting the tab "Browse data" found the table moz_bookmarks.
It contains all bookmarks and folders and contains references to the moz_places table (using the moz_bookmarks.fk).
The moz_places table contains the actual urls.
References
- [1] DB Browser for SQLLite
- https://sqlitebrowser.org
Monday, 26 January 2026
Git: Cleaning up
Sometimes, our IDE can make a mess of things (mostly because we did something wrong, though).
And in order to fix it, sometimes we have to get rid of all unversioned files, so that we have a clean git repository and then create a new Project in our IDE.
This helps as it forces the IDE to recreate its config files from scratch.
This blog is just a small note on how to clean your git repository of all unversioned files.
A dry run would look like this:
A proper clean would look like this:
Options:
- -n
- dry run
- -d
- also recursively delete unversioned directories.
- -x
- ignore .git-ignore rules (convenient for cleaning up buildproducts and IDE config files)
Output of a dry run would look something like this:
Would remove .DS_Store
Would remove .idea/
Would remove mrbear-parent/mrbear-app/target/
Would remove mrbear-stubs/.gradle/
Would remove mrbear-stubs/.kotlin/
Would remove mrbear-stubs/build/
See also "git restore" or "git reset".
References
- git-clean - Remove untracked files from the working tree
- https://git-scm.com/docs/git-clean
Thursday, 15 January 2026
Kotlin : NullSafety + Defaults
So, I had a discussion with my colleague about null safety and how it can be non-intuitive if you're not yet used to it.
So we had the following code:
In a lot of REST applications, an Exception may be thrown when a resource does not exist. But it's important to differentiate between "no resource" and "oh no! An exception occurred! We're in trouble!".
That's what this example code does.
So, what did the "getStatus" method do exactly?
This causes the test to fail.
The code should have been "?: false", but doing that does look weird.
A clearer solution would be:
The problem with Kotlin might be that there's alot of "?." and "?:" and "!!" and quite frankly it makes it hard to read.
What do you think?
Sunday, 11 January 2026
Trying out the Github Command Line
So it's possible and quite convenient to use hardcode git commands to checkout Github repositories. It works fine, once you get the SSH keys sorted out and all that.
I tend to use IntelliJ to checkout new github repositories, as it is soo much easier to point and click.
This always happens to me, when I find myself having to do things I don't do often. Because once you have a repo checked out, that's basically the end of all the complicated stuff and you just get to work.
Checking out using Git
I still prefer using Git to checkout a new repository for now4.
The way this works is just do "git clone git@github.com:username/repo.git". You can find this url in the repository on the GitHub website.
However, an ssh key must be available on your GitHub account for the computer/client you're using.
First generate such an ssh key on your computer, using reference [5].
For example: "ssh-keygen -t ed25519 -C "mrbear@mrbear.com"".
Add your ssh key to the ssh-useragent, using "ssh-add ~/.ssh/id_ed25519".
You should see:
Enter passphrase for /home/mmrbear/.ssh/id_ed25519:
Identity added: /home/mrbear/.ssh/id_ed25519 (mrbear@mrbear.com)
Then you can add the generated key to your Github account using the website, using reference [6].
After that, you can finally just clone your repo as mentioned above.
Installation
GitHub has a command line interface nowadays1. It's easy to install2.I'm using Fedora, so all it takes on my end is to "sudo dnf install gh".
There used to be a tool called "hub", apparently, which is basically a git wrapper for GitHub. It was an unofficial tool. You can find the differences discusses in [3].
Using the CLI
Logging in using "gh auth login".
? Where do you use GitHub? GitHub.com
? What is your preferred protocol for Git operations on this host? SSH
? Upload your SSH public key to your GitHub account? Skip
? How would you like to authenticate GitHub CLI? Login with a web browser
! First copy your one-time code: DFGF-JFDB
Press Enter to open https://github.com/login/device in your browser...
✓ Authentication complete.
- gh config set -h github.com git_protocol ssh
✓ Configured git protocol
✓ Logged in as mrbear
Then the command "gh issue list" shows me open issues.
Works! Quite nice!
References
- [1] GitHub - Take GitHub to the command line
- https://cli.github.com/
- [2] Installing gh on Linux and BSD
- https://github.com/cli/cli/blob/trunk/docs/install_linux.md
- [3] GitHub - GitHub CLI & hub
- https://github.com/cli/cli/blob/trunk/docs/gh-vs-hub.md
- [4] GitHub - Cloning a repository
- https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository
- [5] GitHub - Generating a new SSH key and adding it to the ssh-agent
- https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
- [6] GitHub - Adding a new SSH key to your account
- https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account
Sunday, 28 December 2025
NFS - Network File System
Network File System (NFS) is used to mount external sources of files between Linux/Unix servers.
Nowadays, I think most people use SAMBA (SMB) as that also allows Windows to join the club, but I decided to try NFS (again).
I used to work with NFS back in the past, but it seems to still be viable.
We will be sharing the directory /mnt/raid.
I've edited the file /etc/exports.d/raid.exports to contain2:
- rw
- read and write access
- sync
- is the default, makes certain new requests only get a reply when changes have been committed to stable storage
- no_root_squash
- By default root files are re-mapped to nobody, to prevent write-access etc. in my case, I wish to edit files using root. I don't mind the security consequences very much in my home situation
To apply changes to this file, run "exportfs -ra" or restart the NFS server.
Start services:
# systemctl enable nfs-server.service
Check the status:
# systemctl status nfs-server.service
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; preset: disabled)
Drop-In: /usr/lib/systemd/system/service.d
└─10-timeout-abort.conf
/run/systemd/generator/nfs-server.service.d
└─order-with-mounts.conf
Active: active (exited) since Sat 2026-08-22 12:50:43 CEST; 1h 14min ago
Invocation: ee60721a4aa3491b9a6eab2882173531
Docs: man:rpc.nfsd(8)
man:exportfs(8)
Main PID: 2073 (code=exited, status=0/SUCCESS)
Mem peak: 2.1M
CPU: 44ms
Aug 22 12:50:43 device-209.home systemd[1]: Starting nfs-server.service - NFS server and services...
Aug 22 12:50:43 device-209.home systemd[1]: Finished nfs-server.service - NFS server and services.
On the client
To view all mountable directories of a certain server, try this:
watson:/mnt/raid on /mnt/raid type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,fatal_neterrors=none,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.2.1,local_lock=none,addr=192.168.2.6)
Or of course try "cat /proc/mounts".
Then, on the client, mount the directory:
Surprisingly, I did not have to actually change any configuration of the NFS service.
Works surprisingly well.
Warning! Ports in Fedora Server are closed by default
If you look at [3], you'll see you have to open up the NFS ports in the firewall configuration:
success
# firewall-cmd --reload
success
Update notice: added a part about reconfiguring the firewall.
References
- [1] Fedora Server User Documentation - File sharing with NFS – Installation
- https://docs.fedoraproject.org/en-US/fedora-server/services/filesharing-nfs-installation/
- [2] My Blog - My Current MDADM Setup
- https://randomthoughtsonjavaprogramming.blogspot.com/2024/09/my-current-mdadm-setup.html
- [3] Fedora Server User Documentation - File sharing with NFS - Activation
- https://docs.fedoraproject.org/en-US/fedora-server/services/filesharing-nfs-installation/#_activation
Friday, 12 December 2025
Git: Deleting old local branches
Just looking at old local branches. They tend to proliferate, especially if you have a release cadence.
To list the local branches (the default), or list the branches according to a pattern, see the two examples directly below.
git branch --list "V2022*"
Small explanation of the output of the command:
- existing branches are listed
- the current branch will be highlighted in green and marked with an asterisk
- any branches checked out in linked worktrees will be highlighted in cyan and marked with a plus sign
I'm usually only interested in local branches, but "-r" shows remote-tracking branches and "-a" shows both remote and local branches, if you're interested.
Removing branches
Bear in mind that branches that are used by a worktree cannot be deleted. Remove the worktree first.
Actually, I really like that behaviour.
Checking old branches
Apparently you can sort the list of branches based on last comitterdate.
In the example above, you'll see branches that have been committed to recently at the top.
Finding a commit
This is nice, you can find which branches contain a certain commit quickly.
Unfortunately, we're currently using git as a local repo, and svn remote, so there's a disconnect between commit hashes.
References
- Git - git branch documentation
- https://git-scm.com/docs/git-branch
- StackOverflow - Can you delete multiple branches in one command with Git?
- https://stackoverflow.com/questions/3670355/can-you-delete-multiple-branches-in-one-command-with-git
Friday, 28 November 2025
Kotlin: From List To Map
So I've been trying to make a Map from a List in Kotlin, and as I have not much experience with Kotlin and not much experience with Maps, I turn to the Internet.
Funnily enough, after getting it working, my IDE keeps giving me subtle hints that it can be shorter and more concise.
I thought it would be nice to put the steps here.
val primaryKeys = listOf(12L, 15L, 16L, 22L, 204L) val firstTry = primaryKeys.map { it to getUser(it) }
In the example above it's not a Map yet, but it's a good first step.
As you can tell, it transforms your list into another List of type List<Pair<Long, User>>.
Kotlin has a toMap() method that does what we want.
@Test fun testListToMapConversion() { val primaryKeys = listOf(12L, 15L, 16L, 22L, 204L) val map = primaryKeys.map { it to getUser(it) }.toMap() assertThat(map).isEqualTo( mapOf( 12L to User(12L, "Bob"), 15L to User(15L, "Jimmy"), 16L to User(16L, "Jack"), 22L to User(22L, "Henry"), 204L to User(204L, "William") ) ) }
Now my IDE tells me this can be shortened.
@Test fun testListToMapConversion() { val primaryKeys = listOf(12L, 15L, 16L, 22L, 204L) val map = primaryKeys.associate { it to getUser(it) } assertThat(map).isEqualTo( mapOf( 12L to User(12L, "Bob"), 15L to User(15L, "Jimmy"), 16L to User(16L, "Jack"), 22L to User(22L, "Henry"), 204L to User(204L, "William") ) ) }
Now my IDE tells me this can be shortened AGAIN!
@Test fun testListToMapConversion() { val primaryKeys = listOf(12L, 15L, 16L, 22L, 204L) val map = primaryKeys.associateWith { getUser(it) } assertThat(map).isEqualTo( mapOf( 12L to User(12L, "Bob"), 15L to User(15L, "Jimmy"), 16L to User(16L, "Jack"), 22L to User(22L, "Henry"), 204L to User(204L, "William") ) ) }
Nice!
References
- Syntax Highlighter
- https://highlight.hohli.com/
Thursday, 20 November 2025
Kotlin: Redundant SAM constructor
Kotlin lambdas are fully compatible with Java functional interfaces.
But sometimes you need to give Kotlin a little nudge, using a SAM constructor.
SAM constructors (Single Abstract Method) allow you to convert a lambda expression to an instance of a functional interface. The syntax is pretty straightforward.
The message in the title appears when you use a SAM constructor, when you don't have to. Kotlin is smart enough to create the appropriate anonymous class without us being specific in most cases.
I notice this happening sometimes when I have IntelliJ convert my Java class automatically to Kotlin.
A simple example:
public Builder addMapping(FieldMetadata field, Supplier<?> valueSupplier) {...}
val fieldMapping = FieldMapping.builder()
.addMapping(OrderItemField.ITEM_NR), Supplier { orderRepository.getOrderItem })
.build()
val fieldMapping = FieldMapping.builder()
.addMapping(OrderItemField.ITEM_NR) { orderRepository.getOrderItem }
.build()
References
- Medium - Idiomatic Kotlin: Lambdas and SAM constructors
- https://medium.com/tompee/idiomatic-kotlin-lambdas-and-sam-constructors-fe2075965bfb
Thursday, 13 November 2025
Rename .java to .kt
So, I've suddenly recently noticed that whenever I commit a change into Git in IntelliJ that contains a conversion of a .java file into a .kt (Kotlin) file, IntelliJ will automatically make a previous commit containing the comment "Rename .java to .kt" which contains ONLY the renaming of the file.
I thought this was odd, but the reason behind it is that this commit helps Git to bind the two files together in the History.
If you do not have this single commit, (for example, if you're merging this to your integration branch or whatever and you squash your commits), you lose the history. It means Git will see the .java file as a file that has been deleted and the .kt file as a new file that has been added.
Some people complain, but it really depends on what is important to you:
- do you want to preserve your history in Git for a file
- do you want to see the changing the filename as belonging to your commit (and your ticketnumber in de comments)
Ideally, you should bear in mind IntelliJ does this, so you can at least edit the Commit Message of the renaming to include your ticketnr and original comment and such.
Settings
Can you turn this setting off? Yes, you can. There's a checkbox in the settings of the Git Commit dialog.
Unfortunately, this interesting setting only appears when you have indeed converted a Java file into a Kotlin file.
References
Monday, 3 November 2025
JFall 2025
So last year I was unable to get tickets. They sold out pretty quickly (like in the first three minutes, I hear?).
I expected not to be able to attend this year either, but I added myself to the waiting list and hoped for the best.
Apparently, I was in luck! I have tickets!
I am planning on attending the following:
- Catching the 137-Killer: A Java Memory Forensics Investigation
Martijn Dashorst - Java; our personal career companion
Peter Schuler Ragna Gerretsen - Why You Should Build Agents on the JVM
Rod Johnson - Java 25 - Better Language, Better APIs, Better Runtime
Nicolai Parlog - xz: The day the internet (almost) died
Reinier Zwitserloot Roel Spilke - curl | bash | hacked: The Unseen Dangers in Your Dev Lifecycle
Steve Poole - Benchmarking Project Valhalla
Cay Horstmann - The Wait is Over: Foreign Function & Memory (FFM) API brings modern Java to the Raspberry Pi
Frank Delporte
However, there's several that I also would have liked to see. I'll await those on the YouTubes.
It'll take place coming Thursday, 6th of November 2025.
References
- NLJUG - JFall
- http://jfall.nl/
Thursday, 23 October 2025
No "new" keyword in Kotlin
So I was wondering what my opinion is about that.
I don't like it a lot, as now it seems like calling a constructor looks similar to calling a method.
The only difference that's visible is that the constructor begins with a capital, and then only if you properly follow the coding style guidelines.
I noticed that where Java prefers clarity of purpose, Kotlin prefers brevity (and sacrifices clarity for this).
In Java the "new" keyword does a lot of heavy lifting, that is not part of the constructor. The constructor merely sets the internal structure of an object-to-be to appropriate values. The responsibility of actually making the object, registering it in de Heap, doing the pointer bits, is indicated by the new keyword.
What are your opinions?
References
- Reddit - Is keyword new redundant?
- https://www.reddit.com/r/java/comments/1n0m7cg/is_keyword_new_redundant/
- Kotlin Documentation - Classes
- https://kotlinlang.org/docs/classes.html


