OData using $filter on an $expand not working

0
Hi Mendix Community,   I'm trying to filter an association with Odata, but I can't seem to use a $filter keyword in the brackets of the $expand. I'm not entirely sure where I am going wrong with this, I'm led to believe that this should work, but the error I'm getting makes it seem like this might not be supported. I'm calling the OData service from an app that was not developed in Mendix. Any advice would be appreciated!    Here's an example of the call I'm trying and the error I'm getting:   /v1/Accounts/?$expand=UserRoles($filter=Name eq 'Admin')   {    "error": {        "code": "400",        "message": "Server cannot process the given uri."    }}   -------- java.lang.Exception: ')' expected but '$' found    at com.mendix.integration.odata.publish.uriparser.ODataUriPackratParser.parseThis(ODataUriPackratParser.scala:140)    at com.mendix.integration.odata.publish.uriparser.ODataUriPackratParser.parseIfPresent$1(ODataUriPackratParser.scala:20)    at com.mendix.integration.odata.publish.uriparser.ODataUriPackratParser.$anonfun$parseODataQuery$4(ODataUriPackratParser.scala:35)    at scala.util.Success.flatMap(Try.scala:266)    at com.mendix.integration.odata.publish.uriparser.ODataUriPackratParser.$anonfun$parseODataQuery$3(ODataUriPackratParser.scala:34)    at scala.util.Success.flatMap(Try.scala:266)    at com.mendix.integration.odata.publish.uriparser.ODataUriPackratParser.$anonfun$parseODataQuery$2(ODataUriPackratParser.scala:33)    at scala.util.Success.flatMap(Try.scala:266)    at com.mendix.integration.odata.publish.uriparser.ODataUriPackratParser.parseODataQuery(ODataUriPackratParser.scala:32)    at com.mendix.integration.odata.publish.ODataPathParser$.parseQuery(ODataPathParser.scala:133)    at com.mendix.integration.odata.publish.ODataPathParser$.$anonfun$parseODataQuery$1(ODataPathParser.scala:109)    at com.mendix.integration.odata.publish.ODataModule.$anonfun$parseODataPath$2(ODataModule.scala:89)    at scala.util.Using$.resource(Using.scala:296)    at com.mendix.integration.odata.publish.ODataModule.makeReusable$1(ODataModule.scala:81)    at com.mendix.integration.odata.publish.ODataModule.parseODataPath(ODataModule.scala:86)    at com.mendix.integration.odata.publish.ODataModule.$anonfun$handle$1(ODataModule.scala:58)    at scala.util.Success.flatMap(Try.scala:266)    at com.mendix.integration.odata.publish.ODataModule.handle(ODataModule.scala:57)    at com.mendix.integration.requesthandlers.ServiceRequestHandler.processRequest(ServiceRequestHandler.scala:23)    at com.mendix.externalinterface.connector.RequestHandler.doProcessRequest(RequestHandler.java:37)    at com.mendix.external.connector.MxRuntimeConnector.$anonfun$doProcessRequest$2(MxRuntimeConnector.scala:68)    at com.mendix.external.connector.MxRuntimeConnector.$anonfun$doProcessRequest$2$adapted(MxRuntimeConnector.scala:68)    at com.mendix.util.classloading.Runner$.withContextClassLoader(Runner.scala:20)    at com.mendix.external.connector.MxRuntimeConnector.doProcessRequest(MxRuntimeConnector.scala:68)    at com.mendix.external.connector.MxRuntimeConnector.$anonfun$processRequest$1(MxRuntimeConnector.scala:34)    at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)    at com.mendix.modules.opentelemetry.OpenTelemetryUtilImpl$.$anonfun$withCurrentContextFrom$1(OpenTelemetryUtilImpl.scala:18)    at scala.util.Using$.resource(Using.scala:296)    at com.mendix.modules.opentelemetry.OpenTelemetryUtilImpl$.withCurrentContextFrom(OpenTelemetryUtilImpl.scala:17)    at com.mendix.external.connector.MxRuntimeConnector.processRequest(MxRuntimeConnector.scala:34)    at com.mendix.basis.impl.MxRuntimeImpl.processRequest(MxRuntimeImpl.scala:1088)    at com.mendix.m2ee.appcontainer.server.handler.RuntimeServlet.service(RuntimeServlet.scala:40)    at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)    at org.eclipse.jetty.ee8.servlet.ServletHolder.handle(ServletHolder.java:640)    at org.eclipse.jetty.ee8.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1374)    at org.eclipse.jetty.ee8.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:175)    at org.eclipse.jetty.ee8.servlet.FilterHolder.doFilter(FilterHolder.java:171)    at org.eclipse.jetty.ee8.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1348)    at org.eclipse.jetty.ee8.servlet.ServletHandler.doHandle(ServletHandler.java:454)    at org.eclipse.jetty.ee8.nested.ScopedHandler.nextHandle(ScopedHandler.java:181)    at org.eclipse.jetty.ee8.nested.SessionHandler.doHandle(SessionHandler.java:519)    at org.eclipse.jetty.ee8.nested.ScopedHandler.nextHandle(ScopedHandler.java:181)    at org.eclipse.jetty.ee8.nested.ContextHandler.doHandle(ContextHandler.java:885)    at org.eclipse.jetty.ee8.nested.ScopedHandler.nextScope(ScopedHandler.java:152)    at org.eclipse.jetty.ee8.servlet.ServletHandler.doScope(ServletHandler.java:423)    at org.eclipse.jetty.ee8.nested.ScopedHandler.nextScope(ScopedHandler.java:150)    at org.eclipse.jetty.ee8.nested.SessionHandler.doScope(SessionHandler.java:503)    at org.eclipse.jetty.ee8.nested.ScopedHandler.nextScope(ScopedHandler.java:150)    at org.eclipse.jetty.ee8.nested.ContextHandler.doScope(ContextHandler.java:830)    at org.eclipse.jetty.ee8.nested.ScopedHandler.handle(ScopedHandler.java:117)    at org.eclipse.jetty.ee8.nested.ContextHandler.handle(ContextHandler.java:1443)    at org.eclipse.jetty.ee8.nested.HttpChannel$RequestDispatchable.dispatch(HttpChannel.java:1289)    at org.eclipse.jetty.ee8.nested.HttpChannel.dispatch(HttpChannel.java:616)    at org.eclipse.jetty.ee8.nested.HttpChannel.handle(HttpChannel.java:459)    at org.eclipse.jetty.ee8.nested.ContextHandler$CoreContextHandler$CoreToNestedHandler.handle(ContextHandler.java:2450)    at org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:1064)    at org.eclipse.jetty.server.Server.handle(Server.java:182)    at org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:662)    at org.eclipse.jetty.server.internal.HttpConnection.onFillable(HttpConnection.java:416)    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:322)    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99)    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:480)    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:443)    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)    at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:201)    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:311)    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979)    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209)    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164)    at java.base/java.lang.Thread.run(Thread.java:1583)  
asked
2 answers
0

From what I’ve found, Mendix Published OData does not support using $filter inside $expand. Instead, Mendix applies the root $filter first and then performs the $expand. You could try filtering via the association in the root filter, like this:

 

/v1/Accounts?$filter=UserRoles/any(r:r/Name eq 'Admin')&$expand=UserRoles

 

Could you try this request and see if it works on your endpoint?

answered
0

Okay so I played around with the accepted answer some more, since it wasn't giving me the result I expected with other associations. This approach is great if you want to filter users that have a particular user role, but if a particular account has Admin role and User role it'll still return both those in the result set.

eg. 

 /v1/Accounts?$filter=UserRoles/any(r:r/Name eq 'Admin')&$expand=UserRoles

{

ID: 123,

Name: "John Doe",

...

"UserRoles": [

{

                    "ID": 27303072740933634,

                    "Name": "User",

                    "Description": ""

},

{                    "ID": 27303072740933633,

                    "Name": "Admin",

                    "Description": "" 

}

]

}

 

Which is great, but not quite what I want. I want the roles that do not match my query to be filtered out from the result set.

TL;DR this isn't currently supported by Mendix.

 

(https://docs.mendix.com/refguide10/supported-odata-operations/#filtering-by-association)

answered