spring-projects/spring-data-keyvalue

SpelEvaluationException - retrieving and ordering from redis repository in GraalVM

daniel-naegele opened this issue · 1 comments

On spring-boot 3.2.3 GraalVM Java 21 when you have a repository, like:

@Repository
public interface SomeObjectRepository extends CrudRepository<SomeObject, String> {
    List<SomeObject> findAllOrderByOtherId();
}

and a redis hash class, like

@RedisHash("some-object")
public class SomeObject implements Serializable {
    @Id
    private String id;
    private int otherId;
}

I receive exceptions like this:

2024-02-23T11:11:02.763Z ERROR 1 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.spri
ngframework.expression.spel.SpelEvaluationException: EL1003E: A problem occurred whilst attempting to construct an object of type 'org.springframework.util.comparator.NullSafeComparator' using arguments '(org.springframework
.util.comparator.ComparableComparator,java.lang.Boolean)'] with root cause                                                                                                                                                      
                                                                                                                                                                                                                                
org.springframework.expression.spel.SpelEvaluationException: EL1005E: Type cannot be found 'org.springframework.util.comparator.NullSafeComparator'                                                                             
        at org.springframework.expression.spel.support.StandardTypeLocator.findType(StandardTypeLocator.java:129) ~[na:na]                                                                                                      
        at org.springframework.expression.spel.support.ReflectiveConstructorResolver.resolve(ReflectiveConstructorResolver.java:64) ~[na:na]                                                                                    
        at org.springframework.expression.spel.ast.ConstructorReference.findExecutorForConstructor(ConstructorReference.java:206) ~[na:na]                                                                                      
        at org.springframework.expression.spel.ast.ConstructorReference.createNewInstance(ConstructorReference.java:173) ~[na:na]                                                                                               
        at org.springframework.expression.spel.ast.ConstructorReference.getValueInternal(ConstructorReference.java:115) ~[na:na]                                                                                                
        at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:61) ~[na:na]                                                                                                          
        at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:97) ~[na:na]                                                                                                     
        at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:119) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:6.1.4]                                                                  
        at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:178) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:6.1.4]                                                              
        at org.springframework.data.keyvalue.core.SpelPropertyComparator.compare(SpelPropertyComparator.java:133) ~[na:na]                                                                                                      
        at java.base@21.0.2/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) ~[na:na]                                                                                                                               
        at java.base@21.0.2/java.util.TimSort.sort(TimSort.java:220) ~[na:na]                                                                                                                                                   
        at java.base@21.0.2/java.util.Arrays.sort(Arrays.java:1308) ~[na:na]                                                                                                                                                    
        at java.base@21.0.2/java.util.ArrayList.sort(ArrayList.java:1804) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:na]                                                                                                
        at org.springframework.data.redis.core.RedisQueryEngine.execute(RedisQueryEngine.java:87) ~[na:na]                                                                                                                      
        at org.springframework.data.redis.core.RedisQueryEngine.execute(RedisQueryEngine.java:59) ~[na:na]                                                                                                                      
        at org.springframework.data.keyvalue.core.QueryEngine.execute(QueryEngine.java:73) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                                                            
        at org.springframework.data.keyvalue.core.AbstractKeyValueAdapter.find(AbstractKeyValueAdapter.java:75) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                                       
        at org.springframework.data.keyvalue.core.KeyValueTemplate.lambda$find$6(KeyValueTemplate.java:343) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                                           
        at org.springframework.data.keyvalue.core.KeyValueTemplate.execute(KeyValueTemplate.java:314) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                                                 
        at org.springframework.data.keyvalue.core.KeyValueTemplate.executeRequired(KeyValueTemplate.java:329) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                                         
        at org.springframework.data.keyvalue.core.KeyValueTemplate.find(KeyValueTemplate.java:341) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                                                    
        at org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery.doExecute(KeyValuePartTreeQuery.java:136) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                         
        at org.springframework.data.keyvalue.repository.query.KeyValuePartTreeQuery.execute(KeyValuePartTreeQuery.java:111) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                           
        at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                        
        at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:3.2.3]                                          
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164) ~[na:na]                                                                           
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143) ~[na:na]                                                                             
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:6.1.4]                                                  
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[na:na]                                                                                                 
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:6.1.4]                                                  
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220) ~[na:na]                                                                                                                    
        at jdk.proxy4/jdk.proxy4.$Proxy58.findAllByRadioOrderByAudioconId(Unknown Source) ~[na:na]                                                                                                                              
        at java.base@21.0.2/java.lang.reflect.Method.invoke(Method.java:580) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:na]                                                                                             
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) ~[na:na]                                                                                                                  
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:6.1.4]                                          
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:6.1.4]                                                  
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[na:na]                                                                      
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[de.radiohost.nxtradio.NxtRadioServiceApplication:6.1.4]                                                  
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220) ~[na:na]                                                                                                                    
        at jdk.proxy4/jdk.proxy4.$Proxy58.findAllOrderByOtherId(Unknown Source) ~[na:na]                                                                                                                              

I had to register reflection for ComparableComparator.class, NullSafeComparator.class and Comparator.class (Constructors and Methods) to use the findAllOrderByOtherId method.

Thank you @daniel-naegele for reporting the issue. We'll take care of this.