Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpelEvaluationException: Attempted to call method on null context object

I'm trying to do a simple cache task. I have a Holiday object, which has two fields: referenceDate and isHoliday. I then have a method that will make a HTTP request to a rest api in order to check if a date is a holiday or not. What I want to achieve is: if the current cached Holiday object has the same referenceDate as the one passed as a parameter, return the cached value. I have a specific class to perform that check. Here is the code:

Holiday class

@AllArgsConstructor
@Getter
public class Holiday {
    public LocalDate referenceDate;
    public boolean isHoliday;
}

CacheService class

@DomainService
public class CacheService {

    @Autowired
    private CacheManager cacheManager;

    public boolean isReferenceDateCached(final LocalDate referenceDate){
        final Holiday holiday = (Holiday) cacheManager.getCache("holiday").get("holidaycheck");
        return(holiday.getReferenceDate().equals(referenceDate));
    }
}

HolidatInfraService class

@AllArgsConstructor
@Service
@Slf4j
public class HolidayInfraService {

    @Autowired
    private final CacheService cacheService;

    @Cacheable(value = "holiday", key = "holidaycheck", condition = "#cacheService.isReferenceDateCached(#holidayDateToCheck)")
    public Holiday isHoliday(final LocalDate holidayDateToCheck) {
        //some code to call a rest api
    }

}

And this is the error I get from my unit test when I try to holidayInfraService.isHoliday(someDate):

org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method isReferenceDateCached(java.time.LocalDate) on null context object

From this exception message seems pretty obvious that cacheService is null. However, when I debbuged the code and got inside isHoliday, cacheService is not null. Maybe it hasn't been autowired yet by the time the annotation runs? It is also the first time I'm working with SPEL, so maybe something there too. If in fact cacheService is not autowired yet, is there a workaround?

like image 469
Pelicer Avatar asked Sep 12 '25 04:09

Pelicer


1 Answers

Because you are using the @Cacheable(...) annotation, Spring will evaluate that SpEL expression with the context class MethodBasedEvaluationContext. This will set the root object to be a CacheExpressionRootObject, and property lookups will be performed using that root object.

Since you are trying to refer to a property on a bean, the easiest solution would be to directly reference that bean in the SpEL expression. This is done with an @ (e.g. @myBeanName). Spring will then look for a bean with that name in the ApplicationContext. Remember that a bean defined without an explicit name will be named using the lower camel-came of the class name. For example, a class with the name MyBeanName will have a bean name of myBeanName.

Try changing your condition= block to

@Cacheable(value = "holiday", key = "holidaycheck", condition = "@cacheService.isReferenceDateCached(#holidayDateToCheck)")
public Holiday isHoliday(final LocalDate holidayDateToCheck) {
    //some code to call a rest api
}
like image 160
Ben Avatar answered Sep 13 '25 23:09

Ben