Skip to Content
Author's profile photo Arun Chembra

Batch Request in Netweaver Gateway(Multiple Operations into a Single Request)

This blog contains information regarding batch concept in SAP NetWeaver Gateway Consumers . The OData Batch requests allow the grouping of multiple operations into a single HTTP request payload. I have seen lot of discussion regarding the  batch concept.

This is a brief blog to explain how to implement batch in SAP system and how to make batch gateway service calls for READ,CREATE and UPDATE.

In SAP we don’t have to write any additional logic to implement batch, just have to redefine/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_BEGIN and/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_END methods as shown below.

/wp-content/uploads/2013/08/2_266612.jpg

/wp-content/uploads/2013/08/1_266613.png

READ :

Example of executing a batch request containing multiple Read operations.

URL:

http://**************/sap/opu/odata/sap/<Main_Service_Name>/$batch

HEADER:

Authorization: SAP ID & PASSWORD

x-csrf-token:   Enter Token

Content-Type: multipart/mixed; boundary=batch

BODY:

–batch

Content-Type: application/http

Content-Transfer-Encoding: binary

Accept: application/xml

GET ABCCollection/?$filter= EMP_ID eq ‘10000030’ HTTP/1.1

–batch

Content-Type: application/http

Content-Transfer-Encoding: binary

Accept: application/jsonxml

GET ABCCollection/?$filter=EMP_ID eq ‘10000031’ HTTP/1.1

  –batch–

CREATE:

Example of executing a batch request containing multiple Create operations.

URL:


http://**************/sap/opu/odata/sap/<Main_Service_Name>/$batch

HEADER :

Authorization: SAP ID & PASSWORD

x-csrf-token:   Enter Token

Content-Type: multipart/mixed; boundary=batch

    

BODY:

–batch

Content-Type: multipart/mixed; boundary=changeset

–changeset

Content-Type: application/http

Content-Transfer-Encoding: binary

POST ABCCollection HTTP/1.1

Content-Type: application/atom+xml

Content-Length: 588

<?xml version=”1.0″ encoding=”utf-8″ standalone=”yes”?>

<atom:entry xmlns:atom=”http://www.w3.org/2005/Atom

xmlns:d=”http://schemas.microsoft.com/ado/2007/08/dataservices

xmlns:m=”http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“>

<atom:content type=”application/xml”>

<m:properties>

<d:EMP_ID>10000033</d:EMP_ID>

<d:FIRST_NAME>MIKE</d:FIRST_NAME>

<d:LAST_NAME>JOHNSON</d:LAST_NAME>

</m:properties>

</atom:content>

</atom:entry>

–changeset

Content-Type: application/http

Content-Transfer-Encoding: binary

POST ABCCollection HTTP/1.1

Content-Type: application/atom+xml

Content-Length: 588

<?xml version=”1.0″ encoding=”utf-8″ standalone=”yes”?>

<atom:entry xmlns:atom=”http://www.w3.org/2005/Atom

xmlns:d=”http://schemas.microsoft.com/ado/2007/08/dataservices

xmlns:m=”http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“>

<atom:content type=”application/xml”>

<m:properties>

<d:EMP_ID>10000034</d:EMP_ID>

<d:FIRST_NAME>ALLAN</d:FIRST_NAME>

<d:LAST_NAME>XAVIER</d:LAST_NAME>

</m:properties>

</atom:content>

</atom:entry>

–changeset–

–batch–

UPDATE:

Example of executing a batch request containing multiple Update operations(Change names).

URL:


http://**************/sap/opu/odata/sap/<Main_Service_Name>/$batch

HEADER :

Authorization: SAP ID & PASSWORD

x-csrf-token:   Enter Token

Content-Type: multipart/mixed; boundary=batch

    

BODY:

–batch

Content-Type: multipart/mixed; boundary=changeset

–changeset

Content-Type: application/http

Content-Transfer-Encoding: binary

PUT ABCCollection(‘10000033’) HTTP/1.1

Content-Type: application/atom+xml

Content-Length: 588

<?xml version=”1.0″ encoding=”utf-8″ standalone=”yes”?>

<atom:entry xmlns:atom=”http://www.w3.org/2005/Atom

xmlns:d=”http://schemas.microsoft.com/ado/2007/08/dataservices

xmlns:m=”http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“>

<atom:content type=”application/xml”>

<m:properties>

<d:EMP_ID>10000033</d:EMP_ID>

<d:FIRST_NAME>MIKE_CHANGE</d:FIRST_NAME>

<d:LAST_NAME>JOHNSON_CHANGE</d:LAST_NAME>

</m:properties>

</atom:content>

</atom:entry>

–changeset

Content-Type: application/http

Content-Transfer-Encoding: binary

PUT ABCCollection(‘10000034’) HTTP/1.1

Content-Type: application/atom+xml

Content-Length: 588

<?xml version=”1.0″ encoding=”utf-8″ standalone=”yes”?>

<atom:entry xmlns:atom=”http://www.w3.org/2005/Atom

xmlns:d=”http://schemas.microsoft.com/ado/2007/08/dataservices

xmlns:m=”http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“>

<atom:content type=”application/xml”>

<m:properties>

<d:EMP_ID>10000034</d:EMP_ID>

<d:FIRST_NAME>ALLAN_CHANGE</d:FIRST_NAME>

<d:LAST_NAME>XAVIER_CHANGE</d:LAST_NAME>

</m:properties>

</atom:content>

</atom:entry>

–changeset–

–batch–

Reference Links:

http://help.sap.com/saphelp_gateway20sp06/helpdata/en/90/dc8363306c47d3b2fca1398f5de94b/content.htm

http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/40546820-3ea7-2f10-dfab-be373c0da357?QuickLink=index&overridelayout=true&55959128903935

Assigned Tags

      30 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      Nice Blog, thank you. It will be very helpful.

      Author's profile photo Arun Chembra
      Arun Chembra
      Blog Post Author

      Thanks Pinaki........ 🙂

      Author's profile photo Former Member
      Former Member

      Thanks Chembra

      Nice Blog..

      Author's profile photo Arun Chembra
      Arun Chembra
      Blog Post Author

      Thanks Suman........ 🙂

      Author's profile photo Former Member
      Former Member

      For batch read I have put the following content on the BODY part

      --batch

      Content-Type: application/http

      Content-Transfer-Encoding: binary


      GET ABCCollection(ID='123',DESC='ABC') HTTP/1.1


      --batch--

      You are passing filter parameters, I guess its batch query.

      Regards,

      Pinaki

      Author's profile photo Arun Chembra
      Arun Chembra
      Blog Post Author

      Thanks pinaki instead of Read i put Query in my document...

      Author's profile photo Ramesh T
      Ramesh T

      Hi Arun Chembra,

      Nice document, Thanks for sharing...

      Regards,

      Ramesh.T

      Author's profile photo Arun Chembra
      Arun Chembra
      Blog Post Author

      Thanks Ramesh

      Author's profile photo Former Member
      Former Member

      Good one Arun.

      Author's profile photo Former Member
      Former Member

      Hi Arun,

           Your Blog Helped me alot.

            I can Succesfully send the Data To backend from REST Client.

            Presently I am Doing Update Operation For Sales Order i.e change of quantity ,rejection ...

           my problem is we cannot send the data from Mobile Device the data to backend.

           please suggest me a way how to pass the Request Body from Mobile Side.

      Regards,

      Raju.

      Author's profile photo Wout de Jong
      Wout de Jong

      Arun, nice blog.

      Do you happen to have any advanced examples, like an implementation (use case) of the /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_BEGIN method in combination with its sibling /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_END?

      I see some hints in the docs what one can do with these, but not any actual example.

      Cheers, Wout

      Author's profile photo Arun Chembra
      Arun Chembra
      Blog Post Author

      Hi Wout,

      Thanks for your feedback...

      Even i was not sure about the real time scenarios where we can implement the /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_BEGIN method in combination with its sibling /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_END .

      While using batch you will not be able to use BAPI_TRANSACTION_COMMIT in this case you can implement the /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_BEGIN and /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_END to resolve this issue.

      Thanks,

      Arun

      Author's profile photo Wout de Jong
      Wout de Jong

      Hi Arun, yeah, indeed I haven't found any, except a ref in the help about preparing internal tables in BEGIN, then I assume filling internal tables in the individual CUD operations, and then committing the internal tables to the db in the END method.

      I'm not sure however, how to pass along those internal tables. I can only come up with via MEMORY, but usually I regard that as a bad choice. Plus the individual CUD operations then need to be aware whether they are called within a CHANGESET or not.

      Cheers, Wout

      Author's profile photo Arun Chembra
      Arun Chembra
      Blog Post Author

      Hi Wout,

      Yes, we have to achieve this via memory only, even though it was a bad choice 😎 .

      Thanks,

      Arun

      Author's profile photo Wout de Jong
      Wout de Jong

      Sorry Arun, I'm overcomplicating things with the MEMORY stuff. As all CHANGESET logic and CUD operations happen inside 1 instance of the Data Provider Class, you can just define attributes ("internal tables") to store the data and get that data in the CHANGESET_END method.

      Author's profile photo Former Member
      Former Member

      Hi Wout,

      How did you accomplish to do this with the member table in the data provider class?  Even when in the same changeset I noticed the runtime is reinstantiated for each change. So in my case I set the member variable "is_batch_request" in /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CHANGESET_BEGIN.  When I check for the variable in my entity's ENTITYSET_UPDATE_ENTITY, the variable is only initialized for the first entry of the batch request (within the same change set).. 
      When looking at the above code (see screenshot), it seems not possible to work with a member table? (Create + clear runtime)  Or am I missing something?

      Knipsel.PNG

      Thanks in advance!

      Author's profile photo Former Member
      Former Member

      Hi Bjorn,

      probably you already found out, I think you can use static member variables in the data provider class. These seem to be shared among the changes of a change set. This worked in a small test I did.

      Best regards,

      Matthias

      Author's profile photo Former Member
      Former Member

      Hi Matthias,

      Using a static member variable did the trick, thanks a lot!

      Kr,

      Bjorn

      Author's profile photo Wout de Jong
      Wout de Jong

      Bjorn, sorry for the very late reply. I did use instance attributes, and this still works, as I'm just revisiting the code. (This is an embedded Gateway deployment.)

      Not sure why the runtime is not reinstated in my case...

      Cheers, Wout

      Author's profile photo Former Member
      Former Member

      For what i can understand, if I prepare a service with the Batch option and send multiple create operations, it will treat each one as individual and not by a whole right?

      I have a table that needs to be analysed completely in a Create Operation but I'm not sure if the batch methods will work.

      Author's profile photo Former Member
      Former Member

      Hi Joel,

      By using the batch request all changes you add to that batch changeset will be processed via one http request, saving you the separate round trips to the server.

      For each create operation you added to the batch request however, the entityset_create_entity method will be called, acting on that single entry. I think my problem was similar to yours, and used a flag to have different behaviors in the create_entity method for normal and batch requests. In case of batch request, you can set a flag in the CHANGESET_BEGIN method of the DPC. When the batch flag is active, I do not update the entity in the database in the create_entity method, but instead append it to a member table of the DPC. After the last entry of the batch request, the CHANGESET_END method will be called, where you will have access to the entire table and can decide whether or not to write it to the database. Note that for this to work, both the flag and the table need to be static member attributes of the data provider class.
      Hope this clears things up for you!

      Kind regars,

      Bjorn

      Author's profile photo Wout de Jong
      Wout de Jong

      In addition to Bjorn's answer. 1 Batch can contain multiple Changesets. A Changeset behaves transactionally. Please checkout the documentation on help.sap.com; it's pretty clear.

      Author's profile photo Pavan Golesar
      Pavan Golesar

      nice Blog..... Was very informatic and helpful.. =)

      Regards,

      Pavan Golesar

      Author's profile photo Former Member
      Former Member

      Sorry but it doesn't feel like adding EXIT in the changeset_end and changeset_begin will  solve sending multiple entries for one entityset problem.

      Author's profile photo Former Member
      Former Member

      I have to admit, that your statement is right. I can't get my batch UPDATE to work.

      Author's profile photo Former Member
      Former Member

      Hello! Interesting blog, but how would creating these batch requests look like from the front-end using javascript/json?

      Author's profile photo Rohan Sriram
      Rohan Sriram

      Hi Arun ..! Thanks for the post.It helped me a lot.I have small doubt regarding header part.

      what value should we pass to this x-csrf-token in header section..



      Author's profile photo Former Member
      Former Member

      Hi Arun,

      I am getting status code 202  during my POST create operation , but not getting any other info in response area …even I put a external break point at create_entity …but still execution  was not stopped there ..

      Appreciate your help ..I paste below request

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

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

      POST SorditemSet HTTP/1.1
      Content-Type: application/atom+xml
      Content-Length: 588

      <?xml version=”1.0″ encoding=”utf-8″ standalone=”yes”?>
      <atom:entry xmlns:atom=”http://www.w3.org/2005/Atom“
      xmlns:d=”http://schemas.microsoft.com/ado/2007/08/dataservices“
      xmlns:m=”http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“>
      <atom:content type=”application/xml”>

      <m:properties>
      <d:Erdat>20161115</d:Erdat>
      <d:Netwr>    94.35</d:Netwr>
      <d:Waerk>GBP</d:Waerk>
      <d:Kunnr>0000001066</d:Kunnr>
      <d:Posnr>000010</d:Posnr>
      <d:Matnr>90251178</d:Matnr>
      <d:Kwmeng>    1.000</d:Kwmeng>
      <d:Status>UNAU</d:Status>
      <d:Vbeln>40000336</d:Vbeln>
      </m:properties>
      </atom:content>
      </atom:entry>

      –changeset–
      –batch–-

      Appreciate your help …if I am missing anything ..

      Kind Regards
      Sthiru

      Author's profile photo Ankur Gokhale
      Ankur Gokhale

      Where exactly we have to write business logic? Example reading and saving payload data into tables.

      Author's profile photo yan peng
      yan peng

      Hi, hello, I am having a problem now, when I call the request to create a purchase order, an error occurs as follows: <?xml version="1.0" encoding="utf-8"?>
      <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <code>005056A509B11EE3AEB5819C07C69E2F</code>
      <message xml:lang="en">The server is refusing to process the request because the entity has an unsupported format</message>
      <innererror xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <transactionid>457B9545FD6B0210E005BD3B9E76C48A</transactionid>
      <timestamp>20181106012253.0217930</timestamp>
      <Error_Resolution>
      <SAP_Transaction>For backend administrators: run transaction /IWFND/ERROR_LOG on SAP Gateway hub system and search for entries with the timestamp above for more details</SAP_Transaction>
      <SAP_Note>See SAP Note 1797736 for error analysis (https://service.sap.com/sap/support/notes/1797736)</SAP_Note>
      </Error_Resolution>
      </innererror>
      </error>
      My request address is: https://my300052-api.saps4hanacloud.cn/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/$batch
      The parameters are: {
      "PurchaseOrder": "4500000122",
      "CompanyCode": "A010",
      "PurchaseOrderType": "NB",
      "Supplier": "1000000040",
      "PurchasingOrganization": "A010",
      "PurchasingGroup": "001",
      "to_PurchaseOrderItem": {
      "results": [
      {
      "PurchaseOrder": "4500000122",
      "PurchaseOrderItem": "10",
      "Plant": "A010",
      "OrderQuantity": "10",
      "PurchaseOrderQuantityUnit": "KG",
      "PurchaseOrderItemCategory": "0",
      "Material": "T62-15160000-0",
      "to_AccountAssignment": {
      "results": [
      {
      "PurchaseOrder": "4500000122",
      "PurchaseOrderItem": "10",
      "AccountAssignmentNumber": "1"
      }
      ]
      },
      "to_PurchaseOrderPricingElement": {
      "results": [
      {
      "PurchaseOrder": "4500000122",
      "PurchaseOrderItem": "10",
      "PricingDocument": "1000000229",
      "PricingDocumentItem": "10",
      "PricingProcedureStep": "60",
      "PricingProcedureCounter": "1",
      "FactorForConditionBasisValue": 3.14
      }
      ]
      },
      "to_ScheduleLine": {
      "results": [
      {
      "PurchasingDocument": "7000000000",
      "PurchasingDocumentItem": "10",
      "ScheduleLine": "1"
      }
      ]
      }
      }
      ]
      }
      }