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


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.