I was answering a question on StackOverflow which stated that the NamedParameterJdbcTemplate won't throw an exception when the query is null.

Whilst creating a test for this I did notice that an exception was being thrown but not the exception that I expected. I was expecting an IllegalArgumentException from the NamedParameterUtils with a proper error message stating the SQL cannot be null.

Instead however I was greeted with an exception from the ConcurrentLruCache.

java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null

    at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
    at org.springframework.util.ConcurrentLruCache.get(ConcurrentLruCache.java:101)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getParsedSql(NamedParameterJdbcTemplate.java:483)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.batchUpdate(NamedParameterJdbcTemplate.java:379)
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.batchUpdate(NamedParameterJdbcTemplate.java:370)
    at com.apress.springboot3recipes.jdbc.JdbcCustomerRepositoryTest.insertNewCustomer(JdbcCustomerRepositoryTest.java:42)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

Stating that the key cannot be null.

While an exception is still being thrown (and it is a NullPointerException) it does feel like the wrong exception here. Looks like a regression from the introduction/rewrite of the ConcurrentLruCache. It might be better to copy (or move?) the check from the NamedParameterUtils as a fail fast to the NamedParameterJdbcTemplate instead.

Spring Version 6.1.0-SNAPSHOT but probably applies to earlier versions as well.