Enterprise Resource Planning Blogs by SAP
Get insights and updates about cloud ERP and RISE with SAP, SAP S/4HANA and SAP S/4HANA Cloud, and more enterprise management capabilities with SAP blog posts.
cancel
Showing results for 
Search instead for 
Did you mean: 
andy_bai
Advisor
Advisor

In this blog, I would like to share how to do business object update operation via Service Layer API.


As Service Layer follows OData protocol, it uses HTTP verb PATCH or PUT to update entities. The semantic difference is:




  • A PUT request indicates a replacement update. All property values with those specified in the request body will be replaced. Missing properties are set to their default values. Be aware of the potential for data-loss in round-tripping properties that the client may not know about in advance.

  • A PATCH indicates a differential update. Those property values that are specified in the request body will be exactly replaced. Missing properties are not altered. PATCH provides more resiliency between clients and services by directly modifying only those values specified by the client.


Generally, PATCH is strongly recommended while PUT is deprecated.
1. Update a Primitive Property

CardName is a primitive property of the entity BusinessPartners. To update the name of the customer "c1", send a PATCH request as below:


PATCH /BusinessPartners('c1')

 

 

{ "CardName": "Updated customer name" }

 

On success, HTTP code 204 is returned without content.



HTTP/1.1 204 No Content

2. Update a Complex Property

Only those properties of the complex type specified in the payload of the PATCH request will be modified. For example, AddressExtension is a complex property of the order entity. The original value of this property is as below:


{

 

"AddressExtension": {


 

"ShipToStreet": null,


 

"ShipToStreetNo": null,


 

"ShipToBlock": null,


 

"ShipToBuilding": null,


 

"ShipToCity": null,


 

"ShipToZipCode": null,


 

"ShipToCounty": null,


 

"ShipToState": null,


 

"ShipToCountry": null,


 

"ShipToAddressType": null,


 

"BillToStreet": null,


 

"BillToStreetNo": null,


 

"BillToBlock": null,


 

"BillToBuilding": "",


 

"BillToCity": null,


 

"BillToZipCode": null,


 

"BillToCounty": null,


 

"BillToState": null,


 

"BillToCountry": "US",


 

"BillToAddressType": null,


 

"ShipToGlobalLocationNumber": null,


 

"BillToGlobalLocationNumber": null,


 

"ShipToAddress2": null,


 

"ShipToAddress3": null,


 

"BillToAddress2": null,


 

"BillToAddress3": null


 

}


 

}

 

Send a PATCH request with the following payload to update the AddressExtension:


PATCH /b1s/v1/Orders(9)

 

 

{

 

"AddressExtension": {


 

"ShipToStreet": "Chenhui",


 

"ShipToStreetNo": "1001",


 

"ShipToBuilding": "pvg02",


 

"ShipToCity": "Shanghai",


 

"ShipToCounty": "China"


 

}


 

}

 

On success, HTTP code 204 is returned without content.



HTTP/1.1 204 No Content

Then send a HTTP GET request to retrieve the changed AddressExtension, Service Layer will return:


{ ...

 

"AddressExtension": {


 

"ShipToStreet": "Chenhui",


 

"ShipToStreetNo": "1001",


 

"ShipToBlock": null,


 

"ShipToBuilding": "pvg02",


 

"ShipToCity": "Shanghai",


 

"ShipToZipCode": null,


 

"ShipToCounty": "China",


 

"ShipToState": null,


 

"ShipToCountry": null,


 

"ShipToAddressType": null,


 

"BillToStreet": null,


 

"BillToStreetNo": null,


 

"BillToBlock": null,


 

"BillToBuilding": "",


 

"BillToCity": null,


 

"BillToZipCode": null,


 

"BillToCounty": null,


 

"BillToState": null,


 

"BillToCountry": "US",


 

"BillToAddressType": null,


 

"ShipToGlobalLocationNumber": null,


 

"BillToGlobalLocationNumber": null,


 

"ShipToAddress2": null,


 

"ShipToAddress3": null,


 

"BillToAddress2": null,


 

"BillToAddress3": null


 

}


 

}

 
3. Update a Collection Property

According to the OData standard, since collection members have no individual identity, PATCH is not supported for collection properties.


However, this rule does not suit the B1 data model well, as the collection members of B1 business objects have individual identity. Considering this fact, Service Layer extends the PATCH to support collection properties.


[Add and Update elements in Collection]


Before 9.1H PL12, Service Layer allows to add and update the elements in a collection property. Although removing element in collection is also possible, it is supported using PUTmethod, which is not user-friendly and not recommended.


Assume there is an order with DocEntry = 9 and having one document line as below:


{

 

...


 

"DocEntry": 9,


 

"DocNum": 4,


 

"CardCode": "bp004",


 

"DocDate": "2016-04-23",


 

"DocDueDate": "2016-04-23",


 

"DocumentLines": [


 

{


 

"LineNum": 0,


 

"ItemCode": "i001",


 

"UnitPrice": 10,


 

"Quantitiy": 1


 

}


 

]


 

...


 

}

 

To add a new document line and update the UnitPrice from an existing document line in one round trip, send a request as below:


PATCH /b1s/v1/Orders(9)

 

 

{

 

"DocumentLines": [

 

{

 

"LineNum": 0,

 

"ItemCode": "i001",

 

"UnitPrice": 20,

 

"Quantitiy": 1

 

},

 

{

 

"ItemCode": "i002",

 

"UnitPrice": 10,

 

"Quantitiy": 2

 

}

 

]

 

}

 

On success, HTTP code 204 is returned without content.



HTTP/1.1 204 No Content

Then send a HTTP GET request to check the changed line, Service Layer will return:


{

 

...

 

"DocumentLines": [

 

{

 

"LineNum": 0,

 

"ItemCode": "i001",

 

"UnitPrice": 20,

 

"Quantitiy": 1

 

},

 

{

 

"LineNum": 1,

 

"ItemCode": "i002",

 

"UnitPrice": 10,

 

"Quantitiy": 2

 

}

 

]

 

...

 

}

 

To delete a document line (e.g. the first line), two steps are needed.


1. Retrieve this order by sending below request:
GET /b1s/v1/Orders(9)

2. Get a copy of the response from step 1 and remove the first document line. Then send the rest content to Service Layer by:

PUT /b1s/v1/Orders(9)

 

 

{

 

...


 

"DocumentLines": [


 

{


 

"LineNum": 1,


 

"ItemCode": "i002",


 

"UnitPrice": 10,


 

"Quantitiy": 2


 

}


 

],


 

...


 

}

 

On success, HTTP code 204 is returned without content:



HTTP/1.1 204 No Content

Then send a HTTP GET request to check the changed lines, Service Layer will return:


{

 

...


 

"DocumentLines": [


 

{


 

"LineNum": 1,


 

"ItemCode": "i002",


 

"UnitPrice": 10,


 

"Quantitiy": 2


 

}


 

],


 

...


 

}

 

[Add, Update and Delete elements in collection]


Since 9.1H PL12, Service Layer provides a new way to support removing an element in the collection property by adding a special header in the request:


B1S-ReplaceCollectionsOnPatch=true


Assume there is one business partner with CardCode = 'bp004' and having two addresses (e.g. "addr1" and "addr2") as below:


{

 

...

 

"BPAddresses": [

 

{

 

"AddressName": "addr1",

 

"Country": "US",

 

"AddressType": "bo_BillTo",

 

"BPCode": "bp004",

 

"RowNum": 0,

 

....

 

},

 

{

 

"AddressName": "addr2",

 

"Country": "US",

 

"AddressType": "bo_BillTo",

 

"BPCode": "bp004",

 

"RowNum": 1,

 

...

 

}

 

],

 

...

 

}

 

To add a new address (e.g. "addr3"), update the existing address from "addr2" to "ddr2_new", and remove address "addr1" in one round trip, send a request as below:


PATCH /b1s/v1/BusinessPartners('bp004')

 

B1S-ReplaceCollectionsOnPatch=true

 

 

{

 

"BPAddresses": [

 

{

 

"AddressName": "addr2_new",

 

"AddressType": "bo_BillTo",

 

"BPCode": "bp004",

 

"RowNum": 1

 

},

 

{

 

"AddressName": "addr3",

 

"AddressType": "bo_BillTo",

 

"BPCode": "bp004"

 

}

 

]

 

}

 

On success, HTTP code 204 is returned without content.



HTTP/1.1 204 No Content

Then send a HTTP GET request to check the addresses, Service Layer will return


{

 

...

 

"BPAddresses": [

 

{

 

"AddressName": "addr2_new",

 

"Country": "US",

 

"AddressType": "bo_BillTo",

 

"BPCode": "bp004",

 

"RowNum": 1,

 

...

 

},

 

{

 

"AddressName": "addr3",

 

"Country": "US",

 

"AddressType": "bo_BillTo",

 

"BPCode": "bp004",

 

"RowNum": 2,

 

...

 

}

 

],

 

...

 

}

 

[Note]




  • Read only properties (e.g. CardCode) are not possible to be updated. They are ignored silently if assigned in the request.

  • (Version Note: since 9.1 patch 02) The HTTP verb MERGE is also supported and behavior like PATCH. It's not recommended to use as it's not a standard HTTP verb. It's just for compatibility like supporting Microsoft WCF framework.


In sum, Service Layer mainly uses the OData PATCH verb to update the B1 business objects . Actually, Service Layer also supports PUT. As PUT does not conform to the update semantics defined in B1 data model, it is not suggested to use.

17 Comments