Advanced Features of Clojure Atoms
Most Clojure apps use atoms for managing state,
changing state with the swap! or reset! functions:
(def inventory (atom {:cheese 1 :bread 2}))
; Use swap! to update the atom with a function. In this example:
; Use the 'assoc' function to update the atom. The extra parameters are forwarded to 'assoc'
(swap! inventory assoc :cheese 3)
=> {:cheese 3, :bread 2}
; deref returns the current state. The @ prefix is 'syntactic' sugar to do the same
(str "use deref " (deref inventory) " or @ " @inventory " to get the value of the atom")
=> "use deref {:cheese 3, :bread 2} or @ {:cheese 3, :bread 2} to get the value of the atom"
; Use 'reset!' to reset the state to a specific value.
(reset! inventory {:cheese 0 :bread 0})
=> {:cheese 0, :bread 0}In my Java/C# mind, an atom is an AtomicReference / Interlocked.CompareExchange. However, atoms do have more high-level features. Let’s take a look.
Automated Tests Advice, C# Edition
This post is part of C# Advent Calendar 2021.
I do like writing automated tests, for two reasons. First, it gives me a fast feedback loop. Testing on the fully running app is usually time-consuming compared to running a test. Second, over time it gives some confidence that changes in the code didn’t break your application in unexpected ways.
Basic Process information via /proc
When you need information about a process in Linux,
there are tons of command lines tools, like ps, htop, lsof etc.
I often do not remember the flags to get the information I want.
Luckily, Linux has the /proc file system which gives details on every process.
Most Unix-like operation systems have it, but the formats differ.
I only take a look at the Linux version here.
Tests Not Running: JUnit 5, Maven and Spring Boot Magic
I recently worked on an existing Spring Boot based codebase. Everything looked fine and kept adding new features and improving the codebase. I wrote my tests and run the test suite in my IDE. My changes got into production and everything looked fine.
A few weeks later I took a look at the Continues Integration Servers logs of that project and noticed that the tests are not running. That is no good. My local setup is not a reliable environment, for example, I can forget to check in a file into version control. And I usually run a reduced set of tests and rely on the CI system to run the whole tests suite.
When a Pipe isn't enough: TTYs in Java
I needed to launch Docker containers in Java and pipe the result pack to some other place. This included interacting with that container directly via standard in/out. Nothing easier than that, you can do this with docker like this:
docker run -it ubuntu:20.04
Ok, then lets launch it via Java:
var processCreation = new ProcessBuilder("docker", "run", "-it", "ubuntu:20.04");
processCreation.redirectErrorStream();
processCreation.redirectOutput();
processCreation.redirectInput();
var process = processCreation.start();
redirectToRightPlace(process.getInputStream());
redirectToRightPlace(process.getErrorStream());
redirectToRightPlace(process.getOutputStream());
int exitCode = process.waitFor();Unfortunately, you get this error back from the process:
the input device is not a TTY
Event when you ignore this error, interactive apps like a shell, text editors etc won’t work properly. So, what is this TTY anyway?


