Search code examples
sap-cloud-sdk

Attempt to create simple Contact gives error: PATCH requests require components to be updated


I am currently using SDK version 3.39.0 and version 0004 of the API_MKT_CONTACT service definition to create a new Contact in Marketing Cloud with the following code:

ContactOriginData contact =
        ContactOriginData.builder()
            .originOfContact(origin)
            .originTimestamp(ZonedDateTime.now())
            .externalContactID(pii.getId().toString())
            .firstName(pii.getFirstName())
            .lastName(pii.getLastName())
            .language(pii.getLanguage())
            .countryReg(pii.getRegion())
            .build();

// use low level API as a work around for https://github.com/SAP/cloud-sdk/issues/156
ODataRequestUpdate contactRequest = service
          .updateContactOriginData(contact)
          .withHeader("Sap-Cuan-RequestTimestamp", getFormattedTime(System.currentTimeMillis()))
          .withHeader("Sap-Cuan-SequenceId", "UpdatePatch")
          .withHeader("Sap-Cuan-SourceSystemType", "EXT")
          .withHeader("Sap-Cuan-SourceSystemId", "sdk-test")
          .toRequest();

String servicePath = "/sap/opu/odata/SAP/API_MKT_CONTACT_SRV;v=0004";
ODataRequestBatch requestBatch =  new ODataRequestBatch(servicePath, ODataProtocol.V2);
requestBatch.beginChangeset().addUpdate(contactRequest).endChangeset();
HttpClient httpClient = HttpClientAccessor.getHttpClient(destination);
ODataRequestResultMultipartGeneric batchResult = requestBatch.execute(httpClient);

Running this produces the following error:

{
  "error": {
    "code": "/IWFND/CM_MGW/096",
    "message": {
      "lang": "en",
      "value": "PATCH requests require components to be updated"
    },
    "innererror": {
      "application": {
        "component_id": "CEC-MKT-DM-IC",
        "service_namespace": "/SAP/",
        "service_id": "API_MKT_CONTACT_SRV",
        "service_version": "0004"
      },
      "transactionid": "3B63A2A6CC920630E0060492A51E7EE7",
      "timestamp": "20210310210334.4378960",
      "Error_Resolution": {
        "SAP_Transaction": "For backend administrators: use ADT feed reader \"SAP Gateway Error Log\" or run transaction /IWFND/ERROR_LOG on SAP Gateway hub system and search for entries with the timestamp above for more details",
        "SAP_Note": "See SAP Note 1797736 for error analysis (https://service.sap.com/sap/support/notes/1797736)",
        "Batch_SAP_Note": "See SAP Note 1869434 for details about working with $batch (https://service.sap.com/sap/support/notes/1869434)"
      },
      "errordetails": []
    }
  }
}

However, if I execute a similar request in postman it works without issue:

Request Payload:

--batch
Content-Type: multipart/mixed; boundary=changeset

--changeset
Content-Type: application/http
Content-Transfer-Encoding: binary

PATCH ContactOriginData(ContactOrigin='<ContactOrigin>',ContactID='24D8F7F6-440D-44F8-A24B-552435477688') HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 172
Sap-Cuan-RequestTimestamp: '2021-03-10T14:07:00.000'
Sap-Cuan-SequenceId: UpdatePatch
Sap-Cuan-SourceSystemType: EXT
Sap-Cuan-SourceSystemId: postman-test

{"OriginDataLastChgUTCDateTime":"/Date(1615410479885)/","EmailAddress":"[email protected]","FirstName":"Samantha","LastName":"Cook","Country":"US","Language":"EN"}

--changeset--
--batch--

Response Payload:

--1D7E85E6BC66B34E61ACF0EF3964CBD90
Content-Type: multipart/mixed; boundary=1D7E85E6BC66B34E61ACF0EF3964CBD91
Content-Length:       430

--1D7E85E6BC66B34E61ACF0EF3964CBD91
Content-Type: application/http
Content-Length: 262
content-transfer-encoding: binary

HTTP/1.1 204 No Content
Content-Length: 0
dataserviceversion: 2.0
sap-message: {"code":"HPA_STAGING_AREA/037","message":"Payload is processed via staging area. See Import Monitor for details.","target":"","severity":"info","transition":false,"details":[]}


--1D7E85E6BC66B34E61ACF0EF3964CBD91--

--1D7E85E6BC66B34E61ACF0EF3964CBD90--

I should note that I have also tried using .replacingEntity() which doesn't work either and produces a completely different error:

Inline component is not defined or not allowed (HTTP PUT)

Is there something with the SDK that I am missing or not using correctly? Any help would be appreciated!

Cheers!


Solution

  • To update an entity you should get it from the service first. That is regardless whether you are using:

    1. PATCH which will update only changed fields
    2. or PUT which will send the full entity object

    Currently you are creating a new entity object via the builder: ContactOriginData.builder(). Instead, please use the corresponding getContactOriginDataByKey() method of your service to first retrieve the entity to update from the service. Actually many services will force you to do this to ensure you are always editing the latest version of your data. This often happens via ETags which the SDK will also handle for you automatically.

    You can find more information about the update strategies from the SDK on the documentaiton.


    Edit: As you pointed out in the comments the actual goal is to create an entity and the specific service in question only allows PUT and PATCH to create objects.

    In that case using replacingEntity() (which translates to PUT) should already work with your code. You can make PATCH work as well by replacing the builder approach with a constructor call + setter approach.