I'm having an issue with trying to implement ReactiveQueryByExampleExecutor into my repository in my application
Stack trace:
Caused by: java.lang.IllegalArgumentException: Failed to create query for method public abstract reactor.core.publisher.Mono org.springframework.data.repository.query.ReactiveQueryByExampleExecutor.exists(org.springframework.data.domain.Example)! No property exists found for type Solution!
at org.springframework.data.r2dbc.repository.query.PartTreeR2dbcQuery.<init>(PartTreeR2dbcQuery.java:70)
at org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory$R2dbcQueryLookupStrategy.resolveQuery(R2dbcRepositoryFactory.java:187)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lookupQuery(QueryExecutorMethodInterceptor.java:99)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$mapMethodsToQuery$1(QueryExecutorMethodInterceptor.java:92)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Collections$UnmodifiableCollection$1.forEachRemaining(Collections.java:1052)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.mapMethodsToQuery(QueryExecutorMethodInterceptor.java:94)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.lambda$new$0(QueryExecutorMethodInterceptor.java:84)
at java.base/java.util.Optional.map(Optional.java:265)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.<init>(QueryExecutorMethodInterceptor.java:84)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:332)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297)
at org.springframework.data.util.Lazy.getNullable(Lazy.java:211)
at org.springframework.data.util.Lazy.get(Lazy.java:95)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300)
at org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactoryBean.afterPropertiesSet(R2dbcRepositoryFactoryBean.java:143)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1790)
... 70 more
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property exists found for type Solution!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:94)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:382)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:358)
at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:311)
at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:293)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:276)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:82)
at org.springframework.data.repository.query.parser.PartTree$OrPart.lambda$new$0(PartTree.java:251)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:252)
at org.springframework.data.repository.query.parser.PartTree$Predicate.lambda$new$0(PartTree.java:381)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:382)
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:94)
at org.springframework.data.r2dbc.repository.query.PartTreeR2dbcQuery.<init>(PartTreeR2dbcQuery.java:66)
... 94 more
Repo :
import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
import org.springframework.data.repository.reactive.ReactiveSortingRepository;
public interface MeetingSolverRepository extends ReactiveSortingRepository<Solution, Long>, ReactiveQueryByExampleExecutor<Solution> {
}
Service :
@Slf4j
@Service
@RequiredArgsConstructor
public class MeetingSolverServiceImpl implements MeetingSolverService {
private final MeetingSolverRepository meetingSolverRepository;
@Override
public Flux<Solution> findAll(Solution solution) {
Example<Solution> example = Example.of(solution);
return meetingSolverRepository.findAll(example);
}
}
Object :
import lombok.Data;
import org.springframework.data.annotation.Id;
@Data
public class Solution {
@Id
private Long id;
private Integer tenant;
private Long meetingId;
private Long periodId;
private Long studentId;
private Long teacherId;
private Long roomId;
}
DB config :
import dev.miku.r2dbc.mysql.MySqlConnectionConfiguration;
import dev.miku.r2dbc.mysql.MySqlConnectionFactory;
import io.r2dbc.spi.ConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
import org.springframework.data.r2dbc.connectionfactory.R2dbcTransactionManager;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.lang.NonNull;
import org.springframework.transaction.ReactiveTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.reactive.TransactionalOperator;
@Configuration
@EnableR2dbcRepositories
@EnableTransactionManagement
public class R2DBCConfiguration extends AbstractR2dbcConfiguration {
@Value("${spring.datasource.host}") private String host;
@Value("${spring.datasource.port}") private Integer port;
@Value("${spring.datasource.schema-name}") private String database;
@Value("${spring.datasource.username}") private String username;
@Value("${spring.datasource.password}") private String password;
@Bean
@NonNull
@Override
public ConnectionFactory connectionFactory() {
return MySqlConnectionFactory.from(
MySqlConnectionConfiguration.builder()
.host(host)
.port(port)
.user(username)
.password(password)
.database(database)
.build());
}
@Bean({"r2dbcDatabaseClient"})
@Primary
public DatabaseClient databaseClient() {
return DatabaseClient.create(connectionFactory());
}
@Bean
public ReactiveTransactionManager reactiveTransactionManager(ConnectionFactory connectionFactory) {
return new R2dbcTransactionManager(connectionFactory);
}
@Bean
public TransactionalOperator transactionalOperator(ReactiveTransactionManager reactiveTransactionManager) {
return TransactionalOperator.create(reactiveTransactionManager);
}
}
It looks like it's checking the solution object for the exists property and count and so on. I'm assuming I'm missing something in my setup?
Any help would be greatly appreciated. Thank you.
I don't think Spring Data R2DBC org.springframework.data.r2dbc.repository.support.SimpleR2dbcRepository
implements the ReactiveQueryByExampleExecutor
Unlike its non-reactive counterpart SimpleJpaRepository
in Spring Data JPA that implements the non-reactive QueryByExampleExecutor
Extending your repository interfaces using ReactiveQueryByExampleExecutor
interface and expecting Springboot to auto-configure a ReactiveQueryByExampleExecutor
implementation will NOT work (as of Spring Data R2DBC 1.0) and Spring Data will assume the unimplemented methods from ReactiveQueryByExampleExecutor
are entity property queries hence the exception.
The solutions may be either
a) Implement your own ReactiveQueryByExampleExecutor based on your requirements,
b) switch to Spring Data Mongo if it is an option, or
c) wait for the community to implement a solution. I believe there is an open issue in Github for this. Good luck!