Java – One Year Later

It’s been a little over a year since I started developing in Java full-time again. A retrospective is overdue!

Workplace takeaways

Communication. This may not seem like a Java-related skill, but I cannot overstate how many times stopping to ask questions, even if they seem a bit silly, saved our entire team hours of unnecessary work. On the converse, I can tell you how frustrated I’ve felt when work was duplicated because of the lack of communication or, even worse, wrong communication. 😅 Thankfully, I’ve been blessed with a team that is overall communicative and has been increasingly so in the last few months. Go team!!! 😎

Convention over configuration is nice, but shared knowledge is prime! Spring Boot gives developers a huge break by inserting smart defaults whilst allowing for easy overriding. Couple this with Spring Data JPA and sensible namespacing and you have yourself a web application setup that rivals the likes of Ruby on Rails and Django. However, good tooling does not equal superior code. If your team doesn’t actually understand the APIs and patterns of a convention-over-configuration setup, it is better in my opinion to aim for a lower level setup, such as JDBC or Spring Framework 5 or even Servlets, until sufficient training or knowledge sharing can take place in your team.

What’s happened in the Java universe

During this time, Java has noticeably evolved to the point that, by next year, I expect many developers’ boilerplate code to signficantly differ from how it looked last year.

Java 13 and 14 have rolled out with some notable changes. Records are a preview feature to simplify immutable objects, eliminating the need for manually creating getters & setters or depending on a 3rd party library to do so.

record Customer(String name, String address, String phoneNumber) {}

Text blocks are also in preview, Python style:

var explanation = """
Winter fights to stay.
Sweet Spring always wins her way.
Flowers bloomed today!


And switch expressions finally break 😁 us away from the older, cumbersome syntax. They are also standard and no longer in preview as of Java 14. Here’s an example of the arrow syntax:

private static double getMaximumDose(String ageGroup) {
    int result = switch (ageGroup) {
        case "infant", "toddler" -> 0.5;
        case "preteen" -> 1.0;
        case "teen", "adult", "senior" -> 2.0;
        default -> -1.0;
    return result;

Java 8 is still a big deal, and is going to continue to be a big deal for quite a while. According to Snyk, 2 in 3 developers still use Java 8 in 2020, 6 years after its release. Oracle plans to commercially support Java 8 until 2030 for a price.

Java EE is now Jakarta thanks to Oracle donating its APIs, but forbidding the use of the javax namespace.

Micronaut made its debut as a potential Spring rival in the serverless space, executing dependency injections at compile time instead of at runtime.

Kotlin is the 2nd most popular JVM language.


Avoiding Null Pointer Exceptions in Java

There is a form of driving called “defensive driving”. Defensive drivers anticipate accidents and bad drivers. This lowers the chances of getting into accidents. It has saved me from several bad accidents.

Similarly, we can avoid the scary NullPointerException if we know how to anticipate it. Knowing how to anticipate it will save us from bad coding accidents.

For example, what is wrong with this if check?

if (aString.equals("yes")) { /* do stuff */ }

It’s assuming that aString has been initialized. If a string is not initialized, it will be null! This happens more often than you might expect. It is better to write this:

if ("yes".equals(aString)) { /* do stuff */ } 

I edited a POJO recently that was meant to be a deserialized JSON object. The business requirements said I needed to remove any leading or trailing whitespace. Thankfully, the String.trim() method can do this for me in a single line! I placed it in the setter like this:

public class Person {
  private String firstName;

  public String getFirstName() { return this.firstName; }

  public void setFirstName(String firstName) { 
    this.firstName = firstName.trim(); 

Seems innocent enough. 😉

Imagine my frustration when converting a JSON to this object was throwing a com.fasterxml.jackson.databind.JsonMappingException with a not-so-helpful explanation of “N/A”. What was happening?

Apparently, if firstName is null in JSON, setFirstName was calling trim() on a null object!

In conclusion, what I need to do is check to make sure that the String parameter in setFirstName is not null. There’s more than one way to check, but I chose a ternary operator:

public class Person {
  private String firstName;

  public String getFirstName() { return this.firstName; }

  public void setFirstName(String firstName) { 
    this.firstName = (firstName == null) ? null : firstName.trim(); 

What was the first time you encountered a confusing null pointer and what did you do to avoid it? Discuss.