agrestio / agrest

Server-side Java REST Framework for easy access to data graphs from various backends
https://agrest.io
Apache License 2.0
82 stars 34 forks source link

Child relationship of a dynamic relationship fails to resolve #500

Closed andrus closed 2 years ago

andrus commented 2 years ago

A relationship that is a child of a custom relationship fails to resolve properly. The model looks like this:

E4 --custom--> E3 --standard_cayenne--> E2

The exception below is thrown by the following disabled test: GET_EntityOverlay_PerRequestIT.test_OverlaidRelationship_ExpOnParent_Nested(). This is the first case were a relationship resolver strategy should depend on the navigation path of the request and has to be determined dynamically at request time. "E3->E2" should use standard Cayenne strategy (ViaQueryWithParentExpResolver) when navigated from E3, and some other strategy (e.g. ViaQueryWithParentIdsResolver) when navigated from E4 to E3 to E2

Caused by: java.lang.IllegalStateException: No such relationship: E4.custom
    at io.agrest.cayenne.processor.CayenneQueryAssembler.resolveParentQualifier(CayenneQueryAssembler.java:125)
    at io.agrest.cayenne.processor.CayenneQueryAssembler.resolveParentQualifier(CayenneQueryAssembler.java:147)
    at io.agrest.cayenne.processor.CayenneQueryAssembler.createQueryWithParentQualifier(CayenneQueryAssembler.java:96)
    at io.agrest.cayenne.processor.select.ViaQueryWithParentExpResolver.doOnParentQueryAssembled(ViaQueryWithParentExpResolver.java:42)
    at io.agrest.resolver.BaseNestedDataResolver.onParentQueryAssembled(BaseNestedDataResolver.java:14)
    at io.agrest.NestedResourceEntity.onParentQueryAssembled(NestedResourceEntity.java:70)
    at io.agrest.resolver.BaseDataResolver.afterQueryAssembled(BaseDataResolver.java:22)
    at io.agrest.resolver.BaseNestedDataResolver.onParentQueryAssembled(BaseNestedDataResolver.java:15)
    at io.agrest.NestedResourceEntity.onParentQueryAssembled(NestedResourceEntity.java:70)
    at io.agrest.resolver.BaseDataResolver.afterQueryAssembled(BaseDataResolver.java:22)
    at io.agrest.resolver.BaseRootDataResolver.assembleQuery(BaseRootDataResolver.java:19)
    at io.agrest.runtime.processor.select.AssembleQueryStage.doExecute(AssembleQueryStage.java:21)
    at io.agrest.runtime.processor.select.AssembleQueryStage.execute(AssembleQueryStage.java:13)
    at io.agrest.runtime.processor.select.AssembleQueryStage.execute(AssembleQueryStage.java:9)
    at io.agrest.processor.Processor.lambda$andThen$0(Processor.java:20)
    at io.agrest.processor.Processor.lambda$andThen$0(Processor.java:18)
    at io.agrest.runtime.DefaultSelectBuilder.get(DefaultSelectBuilder.java:183)
    at io.agrest.cayenne.GET_EntityOverlay_PerRequestIT$Resource.getE4_WithE3(GET_EntityOverlay_PerRequestIT.java:251)
andrus commented 2 years ago

I have an idea of a fix - make Cayenne NestedDataResolvers internally change resolver strategy based on the structure of their parent path (e.g. for "parent exp" strategy go "parent exp -> parent ids -> parent getter", for "parent ids" go "parent ids -> parent getter".