javaobjectnullpointerexceptionhessian

Object.requireNonNull skip nullable String


My desktop client communicates with the server through Hessian.

Clients call search API method to find member by passed string teamId.

public Member findMemberByTeamId(FeedProvider provider, String teamId)
{
    Objects.requireNonNull(provider, "Provider can't be a null");
    Objects.requireNonNull(teamId, "Team id can't be a null");

    long starttime = System.currentTimeMillis();

    logger.debug("Started searching member: provider={}, teamId={}", provider, teamId);

    return dao.findMemberByTeamId(provider, teamdId);
}

But I got exception:

[WEB-68] [Service] ERROR Error occurred while downloading member: provider = Hedgehog, teamId = null org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [SELECT * FROM TEAM WHERE ID = ?]; ORA-01722: invalid number ; nested exception is java.sql.SQLSyntaxErrorException:

Inside the logs I found following line:
[WEB-34] [Service] DEBUG Started searching member: provider=Hedgehog, teamId=null

If I connect to my server directly and call search API method with teamId = null, I get the NPE:

Exception in thread "main" java.lang.NullPointerException: Team id can't be a null
    at java.util.Objects.requireNonNull(Objects.java:228)

Solution

  • Problems like this one are quite often caused by a misinterpretation of what you see reported:

    [WEB-34] [Service] DEBUG Started searching member: provider=Hedgehog, teamId=null
    

    This means that teamId either really is null, or is the String object containing the word "null". Unfortunately, there is nothing visible in the output to make the distinction. But the fact that you are already checking for null in your code, and not catching it, would mean that either there's a problem with your code or the variable is set to the string "null". As it turned out, it was indeed the string "null". (Other possibilities might have been that the code you see in your IDE was not the code you actually ran, which can sometimes happen due to e.g. configuration issues.)

    But why on earth would your method be passed a String object containing "null"? A common cause is that the caller is converting from an Integer (for example, it might be an integer column from a JDBC connection where nulls are allowed in that column). It then gets the Integer object and converts it using String.valueOf(Object) before passing it to your method. If the Integer object contained an actual int, that would result in the string representation of that int. If it contained null, it would result in the string "null".

    So a possible fix is to look at the caller of findMemberByTeamId and catch nulls before they get converted to String.