This is an automated email from the ASF dual-hosted git repository. ramyav pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/olingo-odata2.git
The following commit(s) were added to refs/heads/master by this push: new 9631139 [OLINGO-1388]Allow Content-id referencing across changesets 9631139 is described below commit 9631139c22564ce0a549a727ca673eab40f4c9e6 Author: ramya vasanth <ramya.vasa...@sap.com> AuthorDate: Wed Aug 28 09:17:06 2019 +0530 [OLINGO-1388]Allow Content-id referencing across changesets --- .../olingo/odata2/core/batch/BatchHandlerImpl.java | 21 +++-- .../olingo/odata2/core/batch/BatchHandlerTest.java | 19 ++++ .../batchContentIdReferencingForGet.batch | 35 +++++++ .../olingo/odata2/fit/client/ClientBatchTest.java | 102 +++++++++++++++++++++ .../basicBatchWithContentIdReferencing.batch | 58 ++++++++++++ .../basicBatchWithContentIdReferencingFail.batch | 65 +++++++++++++ .../resources/basicBatchWithContentIdWithNav.batch | 37 ++++++++ .../basicBatchWithContentIdWithNavFail.batch | 52 +++++++++++ 8 files changed, 383 insertions(+), 6 deletions(-) diff --git a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java index cfc5df6..2c0d31a 100644 --- a/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java +++ b/odata2-lib/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java @@ -53,25 +53,31 @@ public class BatchHandlerImpl implements BatchHandler { public BatchHandlerImpl(final ODataServiceFactory factory, final ODataService service) { this.factory = factory; this.service = service; + contentIdMap = new HashMap<String, String>(); } @Override public BatchResponsePart handleBatchPart(final BatchRequestPart batchPart) throws ODataException { if (batchPart.isChangeSet()) { List<ODataRequest> changeSetRequests = batchPart.getRequests(); - contentIdMap = new HashMap<String, String>(); return service.getBatchProcessor().executeChangeSet(this, changeSetRequests); } else { if (batchPart.getRequests().size() != 1) { throw new ODataException("Query Operation should contain one request"); } ODataRequest request = batchPart.getRequests().get(0); - ODataRequestHandler handler = createHandler(request); String mimeHeaderContentId = request.getRequestHeaderValue(BatchHelper.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH)); String requestHeaderContentId = request.getRequestHeaderValue(BatchHelper.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH)); - ODataResponse response = setContentIdHeader(handler.handle(request), mimeHeaderContentId, requestHeaderContentId); + + List<PathSegment> odataSegments = request.getPathInfo().getODataSegments(); + if (!odataSegments.isEmpty() && odataSegments.get(0).getPath().matches("\\$.*")) { + request = modifyRequest(request, odataSegments); + } + ODataRequestHandler handler = createHandler(request); + ODataResponse response = setContentIdHeader(request, handler.handle(request), + mimeHeaderContentId, requestHeaderContentId); List<ODataResponse> responses = new ArrayList<ODataResponse>(1); responses.add(response); return BatchResponsePart.responses(responses).changeSet(false).build(); @@ -95,7 +101,7 @@ public class BatchHandlerImpl implements BatchHandler { ODataRequestHandler handler = createHandler(request); ODataResponse response = handler.handle(request); if (response.getStatus().getStatusCode() < BAD_REQUEST) { - response = setContentIdHeader(response, mimeHeaderContentId, requestHeaderContentId); + response = setContentIdHeader(request, response, mimeHeaderContentId, requestHeaderContentId); } if (request.getMethod().equals(ODataHttpMethod.POST)) { String baseUri = getBaseUri(request); @@ -151,10 +157,13 @@ public class BatchHandlerImpl implements BatchHandler { return modifiedRequest; } - private ODataResponse setContentIdHeader(final ODataResponse response, final String mimeHeaderContentId, - final String requestHeaderContentId) { + private ODataResponse setContentIdHeader(ODataRequest request, final ODataResponse response, + final String mimeHeaderContentId, final String requestHeaderContentId) { ODataResponse modifiedResponse; if (requestHeaderContentId != null && mimeHeaderContentId != null) { + String baseUri = getBaseUri(request); + fillContentIdMap(response, requestHeaderContentId, baseUri); + fillContentIdMap(response, mimeHeaderContentId, baseUri); modifiedResponse = ODataResponse.fromResponse(response).header(BatchHelper.REQUEST_HEADER_CONTENT_ID, requestHeaderContentId) .header(BatchHelper.MIME_HEADER_CONTENT_ID, mimeHeaderContentId).build(); diff --git a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchHandlerTest.java b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchHandlerTest.java index d520c10..bafc003 100644 --- a/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchHandlerTest.java +++ b/odata2-lib/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchHandlerTest.java @@ -108,6 +108,25 @@ public class BatchHandlerTest { } @Test + public void contentIdReferencingForGet() throws Exception { + SERVICE_ROOT = SERVICE_BASE; + PathInfoImpl pathInfo = new PathInfoImpl(); + pathInfo.setServiceRoot(new URI(SERVICE_ROOT)); + pathInfo.setODataPathSegment(Collections.<PathSegment> singletonList( + new ODataPathSegmentImpl("$batch", null))); + EntityProviderBatchProperties properties = EntityProviderBatchProperties.init().pathInfo(pathInfo).build(); + InputStream content = readFile("/batchContentIdReferencingForGet.batch"); + List<BatchRequestPart> parsedRequest = EntityProvider.parseBatchRequest(CONTENT_TYPE, content, properties); + + PathInfo firstPathInfo = parsedRequest.get(0).getRequests().get(0).getPathInfo(); + assertFirst(firstPathInfo); + + handler.handleBatchPart(parsedRequest.get(0)); + handler.handleBatchPart(parsedRequest.get(1)); + } + + + @Test public void contentIdReferencingWithAdditionalSegments() throws Exception { SERVICE_ROOT = SERVICE_BASE + "seg1/seg2/"; PathInfoImpl pathInfo = new PathInfoImpl(); diff --git a/odata2-lib/odata-core/src/test/resources/batchContentIdReferencingForGet.batch b/odata2-lib/odata-core/src/test/resources/batchContentIdReferencingForGet.batch new file mode 100644 index 0000000..bb8cf44 --- /dev/null +++ b/odata2-lib/odata-core/src/test/resources/batchContentIdReferencingForGet.batch @@ -0,0 +1,35 @@ +--batch_123 +Content-Type: multipart/mixed; boundary=changeset_b4d2651f-4c8e-4707-8ac3-5bdde1e25760 + +--changeset_b4d2651f-4c8e-4707-8ac3-5bdde1e25760 +Content-Type: application/http +Content-Transfer-Encoding: binary +Content-Id: 1 + +POST Employees HTTP/1.1 +Content-Length: 23 +Accept: application/json +content-type: application/json + +gAAAAgABwESAAMAAAABAAEA +--changeset_b4d2651f-4c8e-4707-8ac3-5bdde1e25760 +Content-Type: application/http +Content-Transfer-Encoding: binary +Content-Id: 2 + +PUT $1/EmployeeName HTTP/1.1 +Content-Length: 41 +Accept: application/json +content-type: application/json + +{"EmployeeName":"Frederic Fall MODIFIED"} +--changeset_b4d2651f-4c8e-4707-8ac3-5bdde1e25760-- + +--batch_123 +Content-Type: application/http +Content-Transfer-Encoding: binary + +GET $1 HTTP/1.1 + + +--batch_123-- \ No newline at end of file diff --git a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/client/ClientBatchTest.java b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/client/ClientBatchTest.java index 66be286..da5a302 100644 --- a/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/client/ClientBatchTest.java +++ b/odata2-lib/odata-fit/src/test/java/org/apache/olingo/odata2/fit/client/ClientBatchTest.java @@ -351,4 +351,106 @@ public class ClientBatchTest extends AbstractRefTest { + "\"Could not find an entity set or function import for 'nonsense'.\"}}}", response.getBody()); } } + + @Test + public void testContentIDReferencing() throws Exception { + final HttpPost post = new HttpPost(URI.create(getEndpoint().toString() + "$batch")); + post.setHeader("Content-Type", "multipart/mixed;boundary=" + BOUNDARY); + + String body = StringHelper.inputStreamToStringCRLFLineBreaks( + this.getClass().getResourceAsStream("/basicBatchWithContentIdReferencing.batch")); + HttpEntity entity = new StringEntity(body); + post.setEntity(entity); + HttpResponse batchResponse = getHttpClient().execute(post); + + assertNotNull(batchResponse); + assertEquals(202, batchResponse.getStatusLine().getStatusCode()); + + InputStream responseBody = batchResponse.getEntity().getContent(); + String contentType = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue(); + List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(responseBody, contentType); + assertEquals("201", responses.get(0).getStatusCode()); + assertEquals("Created", responses.get(0).getStatusInfo()); + assertEquals("201", responses.get(1).getStatusCode()); + assertEquals("Created", responses.get(1).getStatusInfo()); + assertEquals("200", responses.get(2).getStatusCode()); + assertEquals("OK", responses.get(2).getStatusInfo()); + } + + @Test + public void testContentIDReferencingfail() throws Exception { + final HttpPost post = new HttpPost(URI.create(getEndpoint().toString() + "$batch")); + post.setHeader("Content-Type", "multipart/mixed;boundary=" + BOUNDARY); + + String body = StringHelper.inputStreamToStringCRLFLineBreaks( + this.getClass().getResourceAsStream("/basicBatchWithContentIdReferencingFail.batch")); + HttpEntity entity = new StringEntity(body); + post.setEntity(entity); + HttpResponse batchResponse = getHttpClient().execute(post); + + assertNotNull(batchResponse); + assertEquals(202, batchResponse.getStatusLine().getStatusCode()); + + InputStream responseBody = batchResponse.getEntity().getContent(); + String contentType = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue(); + List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(responseBody, contentType); + assertEquals("400", responses.get(0).getStatusCode()); + assertEquals("Bad Request", responses.get(0).getStatusInfo()); + assertEquals("201", responses.get(1).getStatusCode()); + assertEquals("Created", responses.get(1).getStatusInfo()); + assertEquals("404", responses.get(2).getStatusCode()); + assertEquals("Not Found", responses.get(2).getStatusInfo()); + assertEquals("200", responses.get(3).getStatusCode()); + assertEquals("OK", responses.get(3).getStatusInfo()); + } + + @Test + public void testContentIDReferencingWithNav() throws Exception { + final HttpPost post = new HttpPost(URI.create(getEndpoint().toString() + "$batch")); + post.setHeader("Content-Type", "multipart/mixed;boundary=" + BOUNDARY); + + String body = StringHelper.inputStreamToStringCRLFLineBreaks( + this.getClass().getResourceAsStream("/basicBatchWithContentIdWithNav.batch")); + HttpEntity entity = new StringEntity(body); + post.setEntity(entity); + HttpResponse batchResponse = getHttpClient().execute(post); + + assertNotNull(batchResponse); + assertEquals(202, batchResponse.getStatusLine().getStatusCode()); + + InputStream responseBody = batchResponse.getEntity().getContent(); + String contentType = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue(); + List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(responseBody, contentType); + assertEquals("201", responses.get(0).getStatusCode()); + assertEquals("Created", responses.get(0).getStatusInfo()); + assertEquals("200", responses.get(1).getStatusCode()); + assertEquals("OK", responses.get(1).getStatusInfo()); + assertTrue(responses.get(1).getBody().contains("Building 100")); + } + + @Test + public void testContentIDReferencingWithNavFail() throws Exception { + final HttpPost post = new HttpPost(URI.create(getEndpoint().toString() + "$batch")); + post.setHeader("Content-Type", "multipart/mixed;boundary=" + BOUNDARY); + + String body = StringHelper.inputStreamToStringCRLFLineBreaks( + this.getClass().getResourceAsStream("/basicBatchWithContentIdWithNavFail.batch")); + HttpEntity entity = new StringEntity(body); + post.setEntity(entity); + HttpResponse batchResponse = getHttpClient().execute(post); + + assertNotNull(batchResponse); + assertEquals(202, batchResponse.getStatusLine().getStatusCode()); + + InputStream responseBody = batchResponse.getEntity().getContent(); + String contentType = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue(); + List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(responseBody, contentType); + assertEquals("400", responses.get(0).getStatusCode()); + assertEquals("Bad Request", responses.get(0).getStatusInfo()); + assertTrue(responses.get(0).getBody().contains("The request body is malformed.")); + assertEquals("404", responses.get(1).getStatusCode()); + assertEquals("Not Found", responses.get(1).getStatusInfo()); + assertTrue(responses.get(1).getBody().contains( + "Could not find an entity set or function import for '$2'.")); + } } diff --git a/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdReferencing.batch b/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdReferencing.batch new file mode 100644 index 0000000..a3d5ac0 --- /dev/null +++ b/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdReferencing.batch @@ -0,0 +1,58 @@ +--batch_123 +Content-Type: multipart/mixed; boundary=changeset_005056A5-09B1-1ED1-BF82-409B26A80301 + + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80301 +Content-Type: application/http +Content-Transfer-Encoding: binary + +POST Rooms HTTP/1.1 +Content-Type: application/atom+xml +Content-ID: 2 + +<entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"> +<content type="application/xml"> +<m:properties> +<d:Id>100</d:Id> +<d:Name>Room 1</d:Name> +<d:Seats>1</d:Seats> +<d:Version>1</d:Version> +</m:properties> +</content> +</entry> + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80301-- + + +--batch_123 +Content-Type: multipart/mixed; boundary=changeset_005056A5-09B1-1ED1-BF82-409B26A80302 + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80302 +Content-Type: application/http +Content-Transfer-Encoding: binary + +POST Rooms HTTP/1.1 +Content-Type: application/atom+xml +Content-ID: 3 + +<entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"> +<content type="application/xml"> +<m:properties> +<d:Id>300</d:Id> +<d:Name>Room 1</d:Name> +<d:Seats>1</d:Seats> +<d:Version>1</d:Version> +</m:properties> +</content> +</entry> + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80302-- + +--batch_123 +Content-Type: application/http +Content-Transfer-Encoding: binary + +GET $2 HTTP/1.1 + + +--batch_123-- \ No newline at end of file diff --git a/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdReferencingFail.batch b/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdReferencingFail.batch new file mode 100644 index 0000000..8f2c890 --- /dev/null +++ b/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdReferencingFail.batch @@ -0,0 +1,65 @@ +--batch_123 +Content-Type: multipart/mixed; boundary=changeset_005056A5-09B1-1ED1-BF82-409B26A80301 + + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80301 +Content-Type: application/http +Content-Transfer-Encoding: binary + +POST Rooms HTTP/1.1 +Content-Type: application/atom+xml +Content-ID: 2 + +<entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"> +<content type="application/xml"> +<m:properties> +<d:Id>100</d:Id> +<d:Name>Room 1</d:Name> +<d:Seats>10-12-2019</d:Seats> +<d:Version>1</d:Version> +</m:properties> +</content> +</entry> + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80301-- + + +--batch_123 +Content-Type: multipart/mixed; boundary=changeset_005056A5-09B1-1ED1-BF82-409B26A80302 + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80302 +Content-Type: application/http +Content-Transfer-Encoding: binary + +POST Rooms HTTP/1.1 +Content-Type: application/atom+xml +Content-ID: 3 + +<entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"> +<content type="application/xml"> +<m:properties> +<d:Id>300</d:Id> +<d:Name>Room 1</d:Name> +<d:Seats>1</d:Seats> +<d:Version>1</d:Version> +</m:properties> +</content> +</entry> + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80302-- + +--batch_123 +Content-Type: application/http +Content-Transfer-Encoding: binary + +GET $2 HTTP/1.1 + + +--batch_123 +Content-Type: application/http +Content-Transfer-Encoding: binary + +GET $3 HTTP/1.1 + + +--batch_123-- \ No newline at end of file diff --git a/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdWithNav.batch b/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdWithNav.batch new file mode 100644 index 0000000..28f5237 --- /dev/null +++ b/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdWithNav.batch @@ -0,0 +1,37 @@ +--batch_123 +Content-Type: multipart/mixed; boundary=changeset_005056A5-09B1-1ED1-BF82-409B26A80301 + + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80301 +Content-Type: application/http +Content-Transfer-Encoding: binary + +POST Rooms HTTP/1.1 +Content-Type: application/json +Content-ID: 2 + +{ + "d": { + "Id": "100", + "Name": "Room 100", + "Seats": 1, + "Version": 1, + "nr_Building": { + "Id": "100", + "Name": "Building 100", + "Image": null + } + } +} + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80301-- + +--batch_123 +Content-Type: application/http +Accept: application/json +Content-Transfer-Encoding: binary + +GET $2/nr_Building HTTP/1.1 + + +--batch_123-- \ No newline at end of file diff --git a/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdWithNavFail.batch b/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdWithNavFail.batch new file mode 100644 index 0000000..cf38574 --- /dev/null +++ b/odata2-lib/odata-fit/src/test/resources/basicBatchWithContentIdWithNavFail.batch @@ -0,0 +1,52 @@ +--batch_123 +Content-Type: multipart/mixed; boundary=changeset_005056A5-09B1-1ED1-BF82-409B26A80301 + + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80301 +Content-Type: application/http +Content-Transfer-Encoding: binary + +POST Rooms HTTP/1.1 +Content-Type: application/json +Content-ID: 2 + +{ + "d": {, + "Id": "100", + "Name": "Room 100", + "Seats": 1, + "Version": 1, + "nr_Building": { + "Id": "100", + "Name": "Building 100", + "Image": null, + } + } +} + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80301 +Content-Type: application/http +Content-Transfer-Encoding: binary + +PUT $2/nr_Building HTTP/1.1 +Content-Type: application/json +Content-ID: 3 + +{ + "d": { + "Name": Building, + "Image": null + } +} + +--changeset_005056A5-09B1-1ED1-BF82-409B26A80301-- + +--batch_123 +Content-Type: application/http +Accept: application/json +Content-Transfer-Encoding: binary + +GET $2/nr_Building HTTP/1.1 + + +--batch_123-- \ No newline at end of file