How to process an OData Batch Request

Implement the method executeBatch of the class ODataSingleProcessor.

Sample Code

public ODataResponse executeBatch(final BatchHandler handler, final String contentType, final InputStream content)
    throws ODataException {

  List<BatchResponsePart> batchResponseParts = new ArrayList<BatchResponsePart>();
  PathInfo pathInfo = getContext().getPathInfo();
  EntityProviderBatchProperties batchProperties = EntityProviderBatchProperties.init().pathInfo(pathInfo).build();
  List<BatchRequestPart> batchParts = EntityProvider.parseBatchRequest(contentType, content, batchProperties);
  for (BatchRequestPart batchPart : batchParts) {
  return EntityProvider.writeBatchResponse(batchResponseParts);

NOTE: The parameter batchProperties of the method parseBatchRequest contains OData URI informations as PathInfo-object. These informations are necessary for the parsing, that's why the PathInfo-object should not be null.

Implement the method executeChangeSet of the class ODataSingleProcessor.

In order to process a request invoke handler.handleRequest(request), that delegates a handling of the request to the request handler and provides ODataResponse. Define a rollback semantics that may be applied when a request within a ChangeSet fails. The following example shows a possible implementation:

 public BatchResponsePart executeChangeSet(final BatchHandler handler, final List<ODataRequest> requests) throws ODataException {
    List<ODataResponse> responses = new ArrayList<ODataResponse>();
    for (ODataRequest request : requests) {
      ODataResponse response = handler.handleRequest(request);
      if (response.getStatus().getStatusCode() >= HttpStatusCodes.BAD_REQUEST.getStatusCode()) {
        // Rollback
        List<ODataResponse> errorResponses = new ArrayList<ODataResponse>(1);
        return BatchResponsePart.responses(errorResponses).changeSet(false).build();
    return BatchResponsePart.responses(responses).changeSet(true).build();

NOTE: If a request within a ChangeSet fails, a Batch Response Part contains only the error response and the flag changeSet is set to false.

Batch Request Body Example
Content-Type: multipart/mixed; boundary=changeset_321

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

PUT Employees('2')/EmployeeName HTTP/1.1
Content-Length: 100
DataServiceVersion: 1.0
Content-Type: application/json;odata=verbose
MaxDataServiceVersion: 2.0

{"EmployeeName":"Frederic Fall MODIFIED"}


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

GET Employees('2')/EmployeeName?$format=json HTTP/1.1
Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1
MaxDataServiceVersion: 2.0



Request Line of a single request

The following request lines of a single request (e.g. a retrieve request) will be accepted:

Note: An absolute-path reference like // will not be accepted


The new entity may be referenced by subsequent requests within the same ChangeSet by referring to the Content-Id value. $ acts as an alias for the Resource Path of the new entity. In order to refer the new entity the Request URI must begin with $:

POST Customers HTTP/1.1
Content-ID: newCustomer
PUT $newCustomer/Name HTTP/1.1

Note: Requests in different ChangeSets cannot reference one another, even if they are in the same Batch

Note: Client are expected to take care of the percent encoding of the special characters from their end, if there are any. Also, for batch requests the encoding of the parameters in the URLs in the payload are expected to be taken care by the client.


Copyright © 2013-2015, The Apache Software Foundation
Apache Olingo, Olingo, Apache, the Apache feather, and the Apache Olingo project logo are trademarks of the Apache Software Foundation.