This project reproduces an issue with Spring Cloud GCP Spanner where null elements inside arrays cause a NullPointerException during deserialization when reading entities from the database.
When saving an entity with a List<Long> field (mapped to Spanner's ARRAY<INT64> column type) that contains null elements (e.g., [1L, null]), the following behavior occurs:
- ✅ Save operation succeeds - The entity is successfully written to Spanner
- ✅ existsById() succeeds - The entity can be verified as existing
- ❌ findById() fails - Reading the entity back throws
NullPointerException
CREATE TABLE example_entity (
id INT64 NOT NULL,
values ARRAY<INT64>
) PRIMARY KEY (id)java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "sourceValue" is null
The error occurs in Spring Data Spanner's conversion layer when attempting to deserialize the array from Spanner. The converter doesn't properly handle null elements within arrays, even though:
- Spanner itself supports null values in arrays
- The data is successfully stored in the database
- Java 17
- Docker and Docker Compose
- Maven (or use included
mvnw)
-
Start the Spanner Emulator
docker-compose up -d
This starts:
- Spanner emulator on ports 9010 (gRPC) and 9020 (HTTP)
- Instance initialization to create the
emulatorinstance and database
-
Run the Test
./mvnw testThe test will:
- Create the
example_entitytable - Save an
ExampleEntitywithvalues = [1L, null] - Verify the entity exists
- Attempt to retrieve the entity (this will fail with NullPointerException)
- Create the
[ERROR] Errors:
[ERROR] ExampleTest.testSaveAndFindById:49 » NullPointer Cannot invoke "Object.getClass()" because "sourceValue" is null
ExampleEntity.java- Entity with aList<Long>field that can contain nullsExampleRepository.java- Spring Data repository extendingSpannerRepositoryExampleTest.java- Test that reproduces the issueapplication.properties- Configuration to connect to the Spanner emulator
The application is configured to use the local Spanner emulator:
spring.cloud.gcp.spanner.emulator.enabled=true
spring.cloud.gcp.spanner.emulator-host=localhost:9010
spring.cloud.gcp.spanner.project-id=emulator
spring.cloud.gcp.spanner.instance-id=emulator
spring.cloud.gcp.spanner.database=emulatordocker-compose down