
1. Overview
Exceptions in Java may help us find and fix bugs. But what happens when the exception message is null, leaving us scratching our heads for clues?
In this quick tutorial, let’s look into this issue.
2. Introduction to the Problem
As usual, let’s understand the problem through an example:
class Team {
private String name;
//... getters and setters
}
class Player {
private static Logger LOG = LoggerFactory.getLogger(Player.class);
private String name;
private Team team;
public Player(String name) {
this.name = name;
}
void output() {
try {
if (team != null) {
LOG.info("Player:{}, Team:{}", name.toUpperCase(), team.getName().toUpperCase());
} else {
throw new IllegalArgumentException("Team is null");
}
} catch (Exception e) {
LOG.error("Error occurred:" + e.getMessage());
}
}
//... getters and setters
}
As the code above shows, we have a Player referencing a Team instance. In the output() method, we throw an IllegalArgumentException with a meaningful message when the current Player‘s team is null. Further, the entire output() body is wrapped in a try-catch block.
Next, let’s create a Player instance to invoke output():
Player kai = new Player("Kai");
kai.setTeam(new Team());
kai.output();
As the example shows, we called kai.output() after creating kai.
If we run this code with JDK prior to JDK 14, we’ll see this output:
10:03:54.016 [main] ERROR com.baeldung...Player -- Error occurred: null
The null exception message is confusing and not helpful in discovering what went wrong.
Next, let’s understand why this happens and how to avoid confusing null messages.
3. Understanding What a null Exception Message Indicates
Usually, when we see a null exception message in Java, it typically means the exception was thrown without a message. For example, a NullPointerException() was thrown when the application ran with JDK earlier than JDK14.
If we look at the code carefully, the Player instance (kai) does have a non-null Team reference. However, we haven’t set the Team.name property. That is, team.getName() is null. Therefore, team.getName().toUpperCase() throws an unexpected NullPointerException.
Before JDK14, NullPointerException didn’t have a message, so the output shows a null message.
JEP 358 has been implemented in JDK14. Therefore, starting from JDK14, NullPointerException has a detailed message to indicate what led to the exception. For example, if we run the same code with JDk17, the output looks like this:
10:23:53.016 [main] ERROR com.baeldung...Player -- Oops! Error occurred.Cannot invoke "String.toUpperCase()" because the return value of "com.baeldung...Team.getName()" is null
This time, the message pointed out what caused the NullPointerException, which helped guide us to the root cause and fix the bug.
However, sometimes, we have to work with older JDKs. So, next, let’s see how to avoid confusing null exception messages.
4. Stack Trace Instead of Messages
The stack trace is our starting point when we encounter exceptions and want to find their root cause. So, we should include its stack trace when we output an exception.
A common to get a stack trace is calling the Exception.printStackTrace() method:
void outputWithStackTrace() {
try {
// ... same code
} catch (Exception e) {
e.printStackTrace();
}
}
We only replace the LOG.error() call with e.printStackTrace() in the catch block. Now, if we create the same Player kai and call kai.outputWithStackTrace(), we get this output:
java.lang.NullPointerException
at com.baeldung...Player.outputWithStackTrace(ExceptionGetMessageNullUnitTest.java:48)
...
Even without a message, the stack trace tells us we encountered a NullPointerException and the exact line of code where the exception occurred. This gives us a focus point.
Sometimes, we still want to use a logger to manage application error messages. For example, we are using SLF4J in our examples. Therefore, we can use SLF4J to log exceptions:
void outputWithStackTraceLog() {
try {
// ... same code
} catch (Exception e) {
LOG.error("Error occurred.", e);
}
}
Now, if we call kai.outputWithStackTraceLog(), we get the error log:
10:36:31.961 [main] ERROR com.baeldung...Player -- Error occurred.
java.lang.NullPointerException
at com.baeldung...Player.outputWithStackTraceLog(ExceptionGetMessageNullUnitTest.java:60)
...
As the output shows, this error log is helpful for us in finding and fixing the “Team.name is null” issue.
5. Conclusion
In this article, we’ve discussed why we may get null exception messages and explored how to obtain exceptions’ stack traces that help locate the root cause.
As always, the complete source code is available over on GitHub.
The post How to Diagnose a Null Exception Message in Java first appeared on Baeldung.