In my previous article about Java Virtual Threads I focused on different pinning cases caused by the synchronized construct. Some of the presented cases were far from being evident just by looking at the code. That’s why I believe that actively monitoring our apps for pinning is a must.
We don’t know if the pinning happens in our app if we’re not monitoring it. We don’t know how frequently it occurs.
If you heard about Java Virtual Threads, you also heard about the pinning phenomenon. Yet, many articles I found online stop at “replace synchronized with ReentrantLock and don’t use native methods or foreign functions”. While I don’t want to discuss the second part here, I think good-old synchronized deserves a bit more attention.
Note: If you are not familiar with Virtual Threads pinning, I suggest starting with the official Virtual Threads documentation.
Not all Java releases receive the same attention from the community. The ones marked as “LTS” have a much higher chance of broad adoption (even if many of us don’t fully understand what the “LTS” means). This alone makes the recently released Java 21 a serious contender.
I believe it’s the most influential Java release since Java 8. Just not all of its groundbreaking aspects are already evident to everybody…
Quite some time ago, JUnit’s @CsvAnnotation caught my attention. It turned out so interesting, that I dedicated it a separate blog post and a significant part of a conference talk. It also inspired me to create a new way of writing parameterized tests with JUnit 5.
The JUnit 5 FormattedSource library allows defining test case arguments in a human-readable way, following a user-defined format. As a result, it can be used to improve tests readability.
Keeping our domain (business) logic together is usually a really good idea. It not only makes it easier to reason about the most important part of our code but also increases its cohesion. Yet, decoupling the domain code from all the rest (orchestration, persistence, etc.) can be tricky.
In this post, I’d like to share a simple pattern that helps me with that. The amazing Unit Testing Principles, Practices, and Patterns book calls it the CanExecute/Execute pattern.
Database migrations are a standard way of dealing with database schema changes, especially in the relational world. No matter which solution we choose (e.g. Flyway or Liquibase in the Java ecosystem), the number of migrations usually grows together with the project itself. An unfortunate side effect is that the test execution time grows as well.
An effective way of speeding up our test execution in such cases is to squash (compact) all the existing migrations into a single file.
The very last days of the old year are probably a good time to think about the next one. Although we already learned how inaccurate any predictions can be, it still feels like an interesting exercise to me. Let’s try to predict the tech future just a little bit… š®
I have to warn you, that everything you’ll read here is just a reflection of my own gut feeling. It’s a bunch of guesses based on news, observations, and discussions with my colleagues (š).
The JVM has spoiled us with its cleverness. It makes so many decisions behind the scenes, that lots of us gave up on looking at what’s inside. Memory-related discussions are probably more likely to appear at a conference or during a job interview than at “real” work. Of course, depending on what you work on.
Java apps are often run in containers these days. Built-in container awareness makes the JVM respect various container-specific limits (e.
We create APIs all the time - and I don’t have only libraries and frameworks in mind. Every piece of code that’s intended to be called by another piece of code is an API, in some sense. It’s our job to define an interface, which will be used to achieve whatever is expected.
While discussing various API designs, we often focus on “how it’s gonna look” first. Does it allow fluent calls?
Java records should be no longer considered as a “new concept”. Introduced in early 2020 (with version 14) have already been adopted in many projects and organizations. Yet, while we all know that they provide getters, equals, hashCode, and toString for free, there is one feature that still feels a bit unknown. Let’s see how compact constructors can help us write more idiomatic code.
Record construction Recent versions of Java come with concise syntax for declaring records:
Running tests sequentially seems to be the current status quo in the Java community, despite the number of CPU cores our computers have these days. On the other hand, executing all of them in parallel may look great on paper, but it’s often easier said than done, especially in the already existing projects.
With version 5.3, the JUnit framework has introduced experimental support for the parallel test execution, which can allow selective test parallelization driven by the code.
Parameterized tests are definitely my favorite feature of JUnit 5. Defining multiple sets of arguments for the same test can significantly reduce the amount of the test code. Recent additions to the JUnit 5 enable us to write such tests in a whole different way, improving both readability and expressiveness.
This article won’t be yet another primer/overview (like this great introduction from @nipafx). Instead, I’d like to show some not-so-obvious ways of defining test inputs in an elegant, tabular way with JUnit 5.
While browsing Twitter a few days ago, I’ve been reminded about a quite controversial topic in the Java community, which (apparently) still is using interface default methods. To be honest, I’ve been a bit skeptical as well when I’ve first seen them coming as a part of Java 8. However, today I’ll write a few words in defense of default methods, as when used carefully, they can turn out to be extremely handy.
Syntactic sugar (like the introduction of var) is often not enough to convince somebody (especially non-developer) to move forward. This is one of the reasons why Java 8, almost 7 years after its first release, is still widely used. However, many things have improved apart from the syntax. When taking all of them into account, it may turn out that you can’t afford to run Java 8 anymore. And no, I don’t mean migrating the code, but simply updating the JVM used as a runtime!
What could be kind of surprise even for some experienced Java programmers, the java.util.Stream interface extends java.lang.AutoCloseable. This (in theory) puts it on par with files, DB connections, and other resources requiring manual closing. Should we close all our Streams in the same way as any other resources?
In this post, I’d like to explain which Streams have to be closed and how the closing actually works. We will also go through some of the interesting under-documented properties of this feature.
At the end of 2018, I had a pleasure to give a talk at Testwarez - the oldest testing-oriented conference organized in Poland. The recording recently appeared on YouTube, so I decided to take this opportunity to figure out what has changed through the past few months in terms of tools that I presented.
The goal of my talk was to present some practices and open source tools for improving the overall security of Java-based projects.
I have to admit, that when I first saw Project Lombok few years ago it was quite odd to me. The whole “annotation thing” and code pieces appearing “magically” inside the classes made me skeptical. A few years later, I’m now a fan of using Lombok in my Java projects for many reasons. Not all of its users know, that Lombok has more than just reducing the boilerplate code to offer.
I want to share with you some of my thoughts about using Apache Solr (especially SolrCloud) on production. In one of the projects I’m participating in, we are using it to provide Near-Real-Time (NRT) searching along with frequent updates to the indexes. Here are some tips, that helped our project stand still on production environment against hundreds of simultaneous requests per second.
This post is focused on the memory related aspects of the Solr configuration.
Luke, I am Your Father! In his first day at the new job, Bob created the following class:
import java.util.Arrays; import java.util.List; /** * Returns a sum of given numbers. * @author Bob */ public class NumberSumCalculator { public int sum(List<Integer> integers) { int sum = 0; if (integers != null) { for (Integer integer : integers) { sum += integer; } } return sum; } } He was so proud of it, so he put the @author Javadoc tag with his name at the top.
Tests are the light side of programming. Period. Running test cases is one of the fundamental duty of every build automation system - including Maven. Even if it’s a kind of ritual and the determinant of style, every experienced programmer knows that sometimes things just have to be MacGavyered instantly. But how to fold up a late night app version using only Maven, bottle of ketchup and an old shoelace if our tests just don’t pass?