Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Spring allows declaration of invalid method with keyword "contains" in Firestore repository #2155

Closed
ghost opened this issue Jan 31, 2020 · 3 comments · Fixed by #2164
Closed
Assignees
Labels
firestore Firestore Native mode support

Comments

@ghost
Copy link

ghost commented Jan 31, 2020

This is our Firestore repository:

public interface UserSubscriptionsDocumentRepository extends FirestoreReactiveRepository<UserSubscriptionsDocument> {

    Flux<UserSubscriptionsDocument> findAllByEventTypesContainsAndOrgIdsContains(String eventType, String transportOwner);

}

Our Firestore document looks like this:

@Document(collectionName = "userSubscriptions")
@AllArgsConstructor
@NoArgsConstructor
public class UserSubscriptionsDocument {

    @DocumentId
    @NotNull
    public String userId;
    @NotNull
    public List<String> orgIds;
    @NotNull
    public List<String> eventTypes;

}

However, when we call the method "findAllByEventTypesContainsAndOrgIdsContains", we get this error:

2020-01-31 11:05:22.304 ERROR 2876 --- [ parallel-3] o.s.integration.handler.LoggingHandler : java.lang.IllegalStateException: Retries exhausted: 3/3
at reactor.core.publisher.FluxRetryWhen.lambda$null$0(FluxRetryWhen.java:279)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:378)
at reactor.core.publisher.FluxIndex$IndexSubscriber.onNext(FluxIndex.java:95)
at reactor.core.publisher.DirectProcessor$DirectInner.onNext(DirectProcessor.java:333)
at reactor.core.publisher.DirectProcessor.onNext(DirectProcessor.java:142)
at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:89)
at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onError(FluxRetryWhen.java:163)
at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:126)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:819)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:589)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:569)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.onError(FluxFlatMap.java:441)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:386)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:203)
at reactor.core.publisher.FluxJust$WeakScalarSubscription.request(FluxJust.java:99)
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:137)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:363)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:171)
at reactor.core.publisher.FluxJust.subscribe(FluxJust.java:70)
at reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:53)
at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.resubscribe(FluxRetryWhen.java:186)
at reactor.core.publisher.FluxRetryWhen$RetryWhenOtherSubscriber.onNext(FluxRetryWhen.java:232)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.tryEmit(FluxFlatMap.java:530)
at reactor.core.publisher.FluxFlatMap$FlatMapInner.onNext(FluxFlatMap.java:972)
at reactor.core.publisher.MonoDelay$MonoDelayRunnable.run(MonoDelay.java:117)
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68)
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: org.springframework.cloud.gcp.data.firestore.FirestoreDataException: Unsupported predicate keyword: CONTAINING (1): [IsContaining, Containing, Contains]
at org.springframework.cloud.gcp.data.firestore.repository.query.PartTreeFirestoreQuery.lambda$createBuilderWithFilter$0(PartTreeFirestoreQuery.java:139)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.cloud.gcp.data.firestore.repository.query.PartTreeFirestoreQuery.createBuilderWithFilter(PartTreeFirestoreQuery.java:121)
at org.springframework.cloud.gcp.data.firestore.repository.query.PartTreeFirestoreQuery.execute(PartTreeFirestoreQuery.java:91)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:618)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:605)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy109.findAllByEventTypesContainsAndOrgIdsContains(Unknown Source)
at io.project.transportnotification.domain.SubscriptionService.handleWaypointStatusTransitionEvent(SubscriptionService.java:50)
at io.project.transportnotification.infrastructure.messaging.MessagingConfiguration.lambda$handleWaypointStatusTransitionEvent$0(MessagingConfiguration.java:25)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:378)
... 22 more

Why doesn't Spring throw an exception on startup when a method is declared that can't be executed?

@meltsufin meltsufin added the firestore Firestore Native mode support label Jan 31, 2020
@dmitry-s
Copy link
Contributor

We check that when the method is executed, you can see the exception we throw:

Caused by: org.springframework.cloud.gcp.data.firestore.FirestoreDataException: Unsupported predicate keyword: CONTAINING (1): [IsContaining, Containing, Contains]

I'm not sure if it's possible to check that on startup. @mp911de any ideas how that could be implemented?

Thanks

@mp911de
Copy link

mp911de commented Jan 31, 2020

We currently have no way to discover whether a query keyword is supported by a store or not. The PartTreeQuery creator is the component that decides over the implementation. Invoking the query creator requires actual arguments. What we check is whether the keyword matches a known keyword from PartTree. You could perform a check yourself when constructing PartTreeFirestoreQuery by iterating over Parts in PartTree and rejecting unsupported keywords.

@dmitry-s
Copy link
Contributor

Thanks @mp911de !

I'll look into this approach.

dmitry-s added a commit that referenced this issue Feb 3, 2020
* improve PartTree parts validation; fixes #2155
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
firestore Firestore Native mode support
Development

Successfully merging a pull request may close this issue.

3 participants