Open lasterra opened 8 years ago
For supporting batch this is not enough, however I am not sure that can even help. For me batch is working as soon as we have only one changeset
. As soon as we want to send multiple changes sets in one batch like this:
--batch_ffec-4d8c-af56
Content-Type: multipart/mixed; boundary=changeset_aec6-3a75-e9ea
--changeset_aec6-3a75-e9ea
Content-Type: application/http
Content-Transfer-Encoding: binary
MERGE QuestionSet(6) HTTP/1.1
sap-contextid-accept: header
Accept: application/json
Accept-Language: en-US
DataServiceVersion: 2.0
MaxDataServiceVersion: 2.0
Content-Type: application/json
Content-Length: 141
{"Deleted":false,"FormId":2,"Id":6,"Mandatory":true,"QtypeId":"QT2","Question":"Do you like your manager?","RandomWeight":"1.0","Sequence":1}
--changeset_aec6-3a75-e9ea--
--batch_ffec-4d8c-af56
Content-Type: multipart/mixed; boundary=changeset_4289-845e-d51d
--changeset_4289-845e-d51d
Content-Type: application/http
Content-Transfer-Encoding: binary
MERGE QuestionSet(5) HTTP/1.1
sap-contextid-accept: header
Accept: application/json
Accept-Language: en-US
DataServiceVersion: 2.0
MaxDataServiceVersion: 2.0
Content-Type: application/json
Content-Length: 157
{"Deleted":false,"FormId":2,"Id":5,"Mandatory":false,"QtypeId":"QT1","Question":"How do you like working with him or her?","RandomWeight":"1.0","Sequence":1}
--changeset_4289-845e-d51d--
--batch_ffec-4d8c-af56
Content-Type: multipart/mixed; boundary=changeset_714c-f47d-1abd
--changeset_714c-f47d-1abd
Content-Type: application/http
Content-Transfer-Encoding: binary
MERGE QuestionSet(20) HTTP/1.1
sap-contextid-accept: header
Accept: application/json
Accept-Language: en-US
DataServiceVersion: 2.0
MaxDataServiceVersion: 2.0
Content-Type: application/json
Content-Length: 187
{"Deleted":false,"FormId":2,"Id":20,"Mandatory":false,"QtypeId":"QT6","Question":"What are the things you like about your manager’s leadership style?","RandomWeight":"1.0","Sequence":3}
--changeset_714c-f47d-1abd--
--batch_ffec-4d8c-af56--
then it will show the following error:
<?xml version='1.0' encoding='UTF-8'?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<code/>
<message xml:lang="en">Error on processing request content:Cannot begin Transaction on closed Session/EntityManager</message>
</error>
The solution is overriding the executeChangeSet
of ODataJPADefaultProcessor
class. The problem comes from a commiting
function that will close the session:
@Override
public ODataResponse executeBatch(final BatchHandler handler, final String contentType, final InputStream content)
throws ODataException {
try {
ODataResponse batchResponse;
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) {
batchResponseParts.add(handler.handleBatchPart(batchPart));
}
batchResponse = EntityProvider.writeBatchResponse(batchResponseParts);
return batchResponse;
} finally {
close(true);
}
}
@Override
public BatchResponsePart executeChangeSet(final BatchHandler handler, final List<ODataRequest> requests)
throws ODataException {
List<ODataResponse> responses = new ArrayList<ODataResponse>();
try {
//oDataJPAContext.getODataJPATransaction().begin();
for (ODataRequest request : requests) {
//oDataJPAContext.setODataContext(getContext());
ODataResponse response = handler.handleRequest(request);
if (response.getStatus().getStatusCode() >= HttpStatusCodes.BAD_REQUEST.getStatusCode()) {
// Roll Back
oDataJPAContext.getODataJPATransaction().rollback();
List<ODataResponse> errorResponses = new ArrayList<ODataResponse>(1);
errorResponses.add(response);
return BatchResponsePart.responses(errorResponses).changeSet(false).build();
}
responses.add(response);
}
//oDataJPAContext.getODataJPATransaction().commit();
return BatchResponsePart.responses(responses).changeSet(true).build();
} catch (Exception e) {
throw new ODataException("Error on processing request content:" + e.getMessage(), e);
} finally {
close(true);
}
}
I have commented the two problematic lines!
Hey you have mentioned that you have commented 2 lines but in the above code 3 lines seem to be committed. Can you confirm is it required to comment oDataJPAContext.setODataContext(getContext()); also. For me its working fine without commenting this line and commenting the other 2 lines. Thanks in advance.
In the SevletRegister you need to configure multipart to support batch operations.
Just include this line
odataServletRegistrationBean.setMultipartConfig(new MultipartConfigElement(""));
Thanks for your example, it was very helpful.