Batch response: Improved error handling when "UserCollectionResponse" is returned but discrimiator is set to "User"
andnorxor opened this issue · comments
Graph Core Version: 3.1.9
Kiota Version: 1.1.7
Affected Method: com.microsoft.graph.core.requests.ResponseBodyHandler#handleResponse
Edit: Added a comment explaining the reason of this behavior and changed the issue title.
Microsoft Graph core returns an object with all properties set to null, if the response body contains a nested structure.
Expected behavior
com.microsoft.graph.core.requests.ResponseBodyHandler#handleResponse
should parse nested response objects. And maybe throw an error if a response can not be parsed.
Actual behavior
com.microsoft.graph.core.requests.ResponseBodyHandler#handleResponse
returns a object with all properties set to null
.
Steps to reproduce the behavior
Execute the following request using the Graph API: POST https://graph.microsoft.com/v1.0/$batch
Body is GET users?$filter=identities/any(c:c/issuerAssignedId eq '<the issuer Assigned id>' and c/issuer eq 'contoso.com')&$select=id,displayName,email,UserPrincipalName,identities,accountEnabled
{
"requests": [
{
"id": "d26195f1-aa54-461f-9119-aa98687ea27e",
"url": "/users?%24filter=identities%2Fany% ... ",
"method": "GET",
"headers": {
"accept": "application/json"
}
}
]
}
Response: shortended just to show the structure. Note the nested structure in the body which causes the erroneous behavior.
{
"responses": [
{
"id": "766378b9-df71-473d-909a-da07fa9f10c5",
"status": 200,
"headers": {...},
"body": {
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(id,displayName,email,userPrincipalName,identities,accountEnabled)",
"value": [
{
"id": "<some Id>",
"displayName": "John Doe",
"userPrincipalName": "cpim_something",
"accountEnabled": false,
"identities": [...]
}
]
}
}
]
}
The image shows the structure of parseNode
in com.microsoft.graph.core.requests.ResponseBodyHandler#handleResponse
for a Request that CAN NOT be parsed:
The image shows the structure of parseNode
in com.microsoft.graph.core.requests.ResponseBodyHandler#handleResponse
for a request that CAN be parsed:
Remarks
I verified this by unnesting the structure and re-parsing the response:
ByteArrayInputStream unnestedResponse = new ByteArrayInputStream(((java.util.ArrayList)((JsonArray)((com.google.gson.internal.LinkedTreeMap.Node)((com.google.gson.internal.LinkedTreeMap)((JsonObject)((JsonParseNode)parseNode).currentNode).members).entrySet().toArray()[1]).getValue()).elements).get(0).toString().getBytes());
String contentType = body.contentType().type() + "/" + body.contentType().subtype();
this.parseNodeFactory
.getParseNode(contentType, unnestedResponse)
.getObjectValue(this.factory);
An intermediate fix (not yet tested) could be to provide your own implementation of ResponseBodyHandler
when invoking com.microsoft.graph.core.content.BatchResponseContentCollection#getResponseById(java.lang.String, com.microsoft.kiota.ResponseHandler)
I apologize for the confusion earlier; the issue actually originated from my misunderstanding. The query users?$filter=identities
returns a UserCollectionResponse. Consequently, I should be utilizing UserCollectionResponse::createFromDiscriminatorValue
instead of User::createFromDiscriminatorValue
.
This suggests that an enhancement could be to introduce error handling for cases where an inappropriate discriminator value is provided, which might not be parseable under the current method. This could prevent similar misunderstandings in the future. Thank you for your patience.
Thanks for reporting this @andnorxor and for the suggested improvement.