Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update field of a property with complex type in OData Client V2 #658

Open
alceroni opened this issue Dec 4, 2024 · 3 comments
Open

Update field of a property with complex type in OData Client V2 #658

alceroni opened this issue Dec 4, 2024 · 3 comments
Assignees

Comments

@alceroni
Copy link

alceroni commented Dec 4, 2024

Ask the Question

I am using the SAP Cloud SDK version 5.14.0 in Java to connect to a SAP PM Instance with OData. I am using the version 2 of the OData client.

In the data model the entity QualityNotification has a property notifheaderExport with a complex type NotifheaderExport. In the object NotifheaderExport I am changing the value of the property shortText, and then I would like to use the OData client to update the value of the property with a PATCH request.

When I execute the request using the generated QualityNotificationUpdateFluentHelper, I get an error back, because the client is not sending any changed fields at all. The reason is clear by looking at the method getChangedFields() in VdmObject that is used by serializeEntityForUpdatePatch() of ODataEntitySerializer, since the method is not recursing down into properties with complex type.

The expectation is that it would send a JSON Object of the form:

{ "NotifheaderExport": { "ShortText": "blah blah" } }

If I manually send a PATCH request with an HTTP Client and the above JSON as an object, it works.

Is there a way to do this using the generated OData Client V2? If there is, what am I doing wrong?

@alceroni alceroni added the question Further information is requested label Dec 4, 2024
@newtork
Copy link
Contributor

newtork commented Dec 4, 2024

Currently deep update is only supported for one-to-one navigation properties.
This excludes:

  • One-to-many navigation properties - Related issue here
  • Complex properties - I was under the impression, OData standard wouldn't support complex property updates on subset of values. I thought it would reset all unspecified version to null. How does it behave in your case with NotifheaderExport - are the remaining fields null after patching ShortText only?

If you confirm, the patch on a single field on a complex property is working for you without information loss, then we would consider your issue as feature request. If you want to be stakeholder for this request, please let us know your expected timeline and priority.

@alceroni
Copy link
Author

alceroni commented Dec 5, 2024

Yes, I can confirm you that if we manually assemble a PATCH request with only the changed fields of the complex property and send it to our server it works. We had to activate patching in the OData interface on the SAP side though as it was initially disabled.

Unfortunately the one-to-one navigation option is not possible for us, since NotifheaderExport is not an independent entity and changing that would require extensive work.

I would gladly be the stakeholder for this feature request. I am working for a big utility company and we are trying to migrate our old SOAP services to OData in order to upgrade to SAP S/4HANA. Not being able to update single fields of existing entities would be a showstopper. So priority for us would be pretty high.

Of course, I can write code to assemble these patch requests, bypassing the ODataEntitySerializer, but it would be great if the OData SDK would work off-the-shelf.

As for the timeline, we are working on it right now, so it would be great to have it as soon as is for you possible, or at least know when the change would be planned.

@jjtang1985 jjtang1985 added feature request and removed question Further information is requested labels Dec 6, 2024
@alceroni
Copy link
Author

Hi everyone.
In order to circumvent the problem and continue testing our OData API, I implemented myself the serialization code and injected it in the generated classes using string replacement. The serialization code itself looks like that:

        private String getSerializedEntityForPatch(VdmEntity<?> entity) {
		var jsonObject = GSON.toJsonTree(entity).getAsJsonObject();
		removeUnchangedFields(jsonObject, entity);
		return GSON.toJson(jsonObject);
	}

	private void removeUnchangedFields(JsonObject jsonObject, VdmObject<?> entity) {
		var changedFields = entity.getChangedFields();
		entity.toMapOfFields().forEach((key, value) -> {
			if (value instanceof VdmComplex complexProperty) {
				var childJsonObject = (JsonObject) jsonObject.get(key);
				removeUnchangedFields(childJsonObject, complexProperty);
				if (childJsonObject.isEmpty()) {
					jsonObject.remove(key);
				}
			} else if (!changedFields.containsKey(key)) {
				jsonObject.remove(key);
			}
		});
	}

The PATCH request produced using the result of this serialization as body managed to change the update fields of the complex properties in the entity. The code itself is pretty generic, although it doesn't take into account custom or excluded fields because we don't use them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants