Search code examples
sap-cloud-sdk

Unable to create contact with additional id


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

ODataRequestUpdate contactRequest = 
  contactService
    .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();

var additionalId = 
  AdditionalID.builder()
    .externalContactID(pii.getId().toString())
    .originOfContact(origin)
    .originOfContact_2("EMAIL") //ContactAdditionalOrigin
    .externalContactID_2(pii.getEmail()) //ContactAdditionalID
    .build();

var additionalIdRequest = contactService
  .updateAdditionalIDs(additionalId)
  .replacingEntity()
  .withHeader("Sap-Cuan-RequestTimestamp", getFormattedTime(System.currentTimeMillis()))
  .withHeader("Sap-Cuan-SourceSystemType", "EXT")
  .withHeader("Sap-Cuan-SourceSystemId", "sdk-test")
  .toRequest();

// use low level API as a work around for https://github.com/SAP/cloud-sdk/issues/156
ODataRequestBatch requestBatch =  new ODataRequestBatch(ContactService.DEFAULT_SERVICE_PATH, ODataProtocol.V2);
requestBatch
  .beginChangeset()
  .addUpdate(contactRequest)
  .addUpdate(additionalIdRequest)
  .endChangeset();

HttpClient httpClient = HttpClientAccessor.getHttpClient(contactsDestination);
ODataRequestResultMultipartGeneric batchResult = requestBatch.execute(httpClient);
batchResult.getResult(additionalIdRequest);

This results in the following error:

{
  "error": {
    "code": "SY/530",
    "message": {
      "lang": "en",
      "value": "Inline component is not defined or not allowed (HTTP PUT)"
    },
    "innererror": {
      "application": {
        "component_id": "CEC-MKT-DM-IC",
        "service_namespace": "/SAP/",
        "service_id": "API_MKT_CONTACT_SRV",
        "service_version": "0004"
      },
      "transactionid": "3B63A2A6CC9205E0E00604E1D31F1CDF",
      "timestamp": "20210315142401.8432680",
      "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": []
    }
  }
}

I am using this documentation as a guide for building my requests (under the section "Create Contacts with Additional IDs"). When I run the example code in Postman it works as expected. Note that the payload for the AdditionalIDs is an empty JSON object.

So I enabled HTTP wire logs and noticed that the SDK seems to be including the following payload:

PUT AdditionalIDs(ContactAdditionalOrigin='EMAIL',ContactAdditionalID='[email protected]',ContactID='ae46e174-52a3-4de6-8caa-57213151b295',ContactOrigin='<CONTACT_ORIGIN>') HTTP/1.1
Sap-Cuan-SourceSystemId: sdk-test
Accept: application/json
Sap-Cuan-SourceSystemType: EXT
Content-Type: application/json
Sap-Cuan-RequestTimestamp: '2021-03-15T14:24:00.828'

{"ContactOrigin":"<CONTACT_ORIGIN>","ContactID":"ae46e174-52a3-4de6-8caa-57213151b295","ContactAdditionalOrigin":"EMAIL","ContactAdditionalID":"[email protected]","ContactAdditionalIdUUID":null,"ContactUUID":null,"ContactAddlIDIsInvalid":null,"MarketingAreas":[]}

Unfortunately, I can't seem to find a way to omit the payload/inline component while using the SDK so that it matches the example code. Is this an issue with the SDK or am I doing something wrong? Any help would be much appreciated!

Cheers!

UPDATE

Applying the suggested workaround from @matkuhr I changed my additionalIdRequest above to this and it worked:

ODataEntityKey key = new ODataEntityKey(ODataProtocol.V2)
        .addKeyProperty(AdditionalID.EXTERNAL_CONTACT_ID.getFieldName(), mcContact.getContactId())
        .addKeyProperty(AdditionalID.ORIGIN_OF_CONTACT.getFieldName(), origin)
        .addKeyProperty(AdditionalID.ORIGIN_OF_CONTACT_2.getFieldName(), "EMAIL")
        .addKeyProperty(AdditionalID.EXTERNAL_CONTACT_I_D_2.getFieldName(), mcContact.getEmailAddress());
    var request = new ODataRequestUpdate(
        ContactService.DEFAULT_SERVICE_PATH,
        "AdditionalIDs",
        key,
        "{}",
        UpdateStrategy.REPLACE_WITH_PUT,
        null,
        ODataProtocol.V2);
    request.addHeader("Sap-Cuan-RequestTimestamp", getFormattedTime(System.currentTimeMillis()));
    request.addHeader("Sap-Cuan-SourceSystemType", "EXT");
    request.addHeader("Sap-Cuan-SourceSystemId", "sdk-test);

Solution

  • It's not you doing something wrong, it's also not the SDK, it's the service. The service seems to substantially deviate from the OData V2 conventions as well as basic HTTP conventions.

    You can work around this by leveraging the low-level APIs of the SDK even more. Create the update request fully manually with the payload the service requires, e.g.:

    ODataEntityKey key = new ODataEntityKey(ODataProtocol.V2)
                    .addKeyProperty(Contact.XYZ.getFieldName(), contact.getXyz())
    request = new ODataRequestUpdate(
                    contactService.getServicePath(),
                    contact.getEntityCollection(),
                    key,
                    "{ }",  // this will be the payload
                    UpdateStrategy.REPLACE_WITH_PUT,
                    null,
                    ODataProtocol.V2);
    request.addHeader("key", "val");
    // add more headers & parameters if needed and execute