For some reason I can see that object was passed not null, but in key expression it is null already.
I am trying to read some data from DB and add it to the cache. Here are my methods.
public void preloadCache() {
List<Statistic> allData = repository.findAll();
log.info("Data found {}", allData.size());
allData.forEach(cacheService::populateQuarterStatisticCache);
}
It calls separate service
@Service
@Slf4j
public class CacheService {
@CachePut(value = "quarterStatistic", key = "#statistic.type + '-' + #statistic.location")
public QuarterBusinessesStatistic populateQuarterStatisticCache(Statistic statistic) {
log.info("Loading statistic into cache: {}-{}", statistic.getType(), statistic.getLocation());
return statistic.getData();
}
}
Logs shows me that there is one object and it is not null
[nio-8080-exec-1] StatisticClient : Data found 1
[nio-8080-exec-1] CacheService : Preloading statistic into cache: restaurant-New York
But next line of the log tells me SpelEvaluationException: EL1007E: Property or field 'type' cannot be found on null
If I am changing key in my @CachePut annotation to key = "#statistic?.type + '-' + #statistic?.location"
there will be no exceptions. But in the cache I will see stored object by null-null
key
I can debug it and see that my object is not null. Logs also prove that. But in key expression it is null for some reason.
Does anybody had the same?
Note: I tried to change key to something like
#statistic.getType() + '-' + #statistic.getLocation()
- same result
My pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>MyService</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>21</java.version>
<spring-boot.version>3.3.5</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
From the comments it is apparent that positional parameters, #a0
do work and named parameters #statistic
fails. This is an indication that your maven-compiler-plugin
isn't setup properly.
From your pom.xml
your maven-compiler-plugin
is configured as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
Now with Spring Boot 3 (or rather Spring Framework 6.1) is is needed to enable compilation with parameter name retention. You need to configure this in your maven-compiler-plugin
.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<release>${java.version}</release>
<parameters>true</parameters>
</configuration>
</plugin>
This will keep the parameter names in the class file and will make #statistic
work.
An easier way is, as you are using Spring Boot, is to remove this maven-compiler-plugin
al together and use the spring-boot-starter-parent
which does all of this (and more) already.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
</parent>