add application and service principal owner with msgraph-sdk-java

Michael 0 Reputation points
2024-03-15T08:53:31.2566667+00:00

Following the documentation, I tried to add an owner for an application and a service principal as follows:

val referenceCreate= ReferenceCreate()
referenceCreate.odataId = "https://graph.microsoft.com/v1.0/directoryObjects/$owner"

graphClient.applications().byApplicationId(application.id.toString()).owners().ref().post(referenceCreate)
graphClient.servicePrincipals().byServicePrincipalId(servicePrincipal.id.toString()).owners().ref().post(referenceCreate)

This code leads to an Exception like:

com.microsoft.graph.models.odataerrors.ODataError: An unexpected 'EndOfInput' node was found when reading from the JSON reader. A 'StartObject' node was expected.

	at com.microsoft.graph.models.odataerrors.ODataError.createFromDiscriminatorValue(ODataError.java:36)
	at com.microsoft.kiota.serialization.JsonParseNode.getObjectValue(JsonParseNode.java:210)
	at com.microsoft.kiota.http.OkHttpRequestAdapter.lambda$throwIfFailedResponse$0(OkHttpRequestAdapter.java:672)
	at com.microsoft.kiota.ApiExceptionBuilder.<init>(ApiExceptionBuilder.java:26)
	at com.microsoft.kiota.http.OkHttpRequestAdapter.throwIfFailedResponse(OkHttpRequestAdapter.java:671)
	at com.microsoft.kiota.http.OkHttpRequestAdapter.sendPrimitive(OkHttpRequestAdapter.java:341)
	at com.microsoft.graph.serviceprincipals.item.owners.ref.RefRequestBuilder.post(RefRequestBuilder.java:105)
	at com.microsoft.graph.serviceprincipals.item.owners.ref.RefRequestBuilder.post(RefRequestBuilder.java:91)
	at xx.xxx.xxx.xxxxx.service.TestAppRegistrationService.create(TestAppRegistrationService.kt:52)

...

I can avoid this problem by creating two instances of ReferenceCreate:

val applicationOwnerReference = ReferenceCreate()
val servicePrincipalOwnerReference = ReferenceCreate()

applicationOwnerReference.odataId = "https://graph.microsoft.com/v1.0/directoryObjects/$owner"
servicePrincipalOwnerReference.odataId = "https://graph.microsoft.com/v1.0/directoryObjects/$owner"

graphClient.applications().byApplicationId(application.id.toString()).owners().ref().post(applicationOwnerReference)
graphClient.servicePrincipals().byServicePrincipalId(servicePrincipal.id.toString()).owners().ref().post(applicationOwnerReference)

Can someone explain why this is happening? Is this behavior intended?

Regards, Michael

Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
10,524 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Azar 18,295 Reputation points
    2024-03-15T09:14:42.0566667+00:00

    Hey there Michael

    Thats a good question and thanks for using QandA platform.

    So when you initially create a ReferenceCreate object and set its odataId, the object holds a reference to that URL. bt, when you reuse the same ReferenceCreate object for both application and service principal owners, it seems that there might be some internal state management issue with the SDK causing unexpected behavior. (I guess)

    For a workaround create a separate instances of ReferenceCreate for each operation. Each instance maintains its own state and doesn't interfere with the other, hope that removves the issue you are facing.

    And regarding whether this is intended or not, without knowning the specifics of the Microsoft Graph SDK for Java, it's difficult to say definitively. but, based on the observed behavior and your workaround, it seems like reusing the same instance of ReferenceCreate for multiple operations might not be properly handled by the SDK, leading to unexpected errors.

    If this helps kindly accept the answer thanks much.


  2. Ramses Sanchez Hernandez 0 Reputation points Microsoft Employee
    2024-04-04T20:50:07.9033333+00:00

    This behavior is due to the backing store. Basically, after the object is sent the first time the backing store kicks in and tracks whether any values have been changed, since the value for OdataID remains the same, the value is not parsed for the second request and we get a JSON value of {}. The behavior is partially explained here. In order to avoid this, as we see above is to create two reference objects, an alternative is to add the following between the two post requests:

    
            referenceCreate.getBackingStore().setReturnOnlyChangedValues(false);
    
            referenceCreate.getBackingStore().setIsInitializationCompleted(false);
    
    
    0 comments No comments