0
votes

We are trying to create an entity that has date attributes via an odata service. Backend is an sap system. This entity has only 3 key attributes plus a bunch of other attributes. We have identified that dates in the keys are the root cause of the problem.

Keys:

  • Pernr type string,
  • begda type datetime
  • endda type datetime.

The code below, (which does not work), has been severely simplified when trying to troubleshoot the issue. At the moment, it reads an entity from an entity set and immediately tries to create one with exactly the same data.

Code:

var oODataModel = new sap.ui.model.odata.ODataModel("/sap/opu/odata/sap/Z_PERSONAL_DATA_SRV/");

//Test entity to be saved
var entity = null;

//Handler for read error
var handleReadE = function (oEvent){ 
    alert("error");
};

//Handler for read success
var handleRead = function (oEvent){
    //Get the data read from backend
    entity = oEvent.results[0];

    //Try to create a new entity with same data
    oODataModel.create('/PersDataSet', entity, null, function(){
        alert("Create successful");
    },function(oError){
        alert("Create failed", oError);
    });
};

oODataModel.read("/PersDataSet", null, [], true, handleRead, handleReadE);

In the gateway error log, an xml parsing error appears. In this log, we can see the request data and it can be seen that the dates are transported with String types. These dates are defined in the service as DateTimes so the request is rejected. Example:

<m:properties>
<d:Pernr m:type="Edm.String">00000001</d:Pernr>
    <d:Endda m:type="Edm.String">9999-12-31T00:00:00</d:Endda>
    <d:Begda m:type="Edm.String">1979-05-23T00:00:00</d:Begda>

When the entity is read, the backend does not send any type information. It sends like the following example:

<m:properties>
   <d:Pernr>72010459</d:Pernr>
   <d:Endda>9999-12-31T00:00:00</d:Endda>
   <d:Begda>1876-07-21T00:00:00</d:Begda>

And, indeed, if we try to save the same info without the type=".." it works. So the problem are the incorrect types ODataModel.create adds to the xml.

My question is: Can I tell ODataModel.create to not add this type info? It is not doing a good job inferring the types.

Can anyone share an example reading and writing dates through odata?

Thank you very much in advance.

2
have you tried to get the data after the read has finished? so, what i mean is let the model load and query the model by oODataModel.create('/PersDataSet', oODataModel.getProperty('/'), ...)Manuel Richarz
or let ODataModel use two-way binding and just create a new entity inside this model. hopefully the model will do the rest ;-)Manuel Richarz
I think this is already letting the read finish and then trying to create (or I do not understand what you mean :) ). The two-way binding updates automatically in the server?? Did not read this anywhere in the documentation. Many thanksTiago A.
whats in your service $metadata, should look something like <Property Name="Endda" Type="Edm.DateTime"/> not Edm.StringJasper_07
Hi, Yes. DateTime :) <EntityType Name="PersData" sap:content-version="1"> <Key> <PropertyRef Name="Begda" /> <PropertyRef Name="Endda" /> <PropertyRef Name="Pernr" /> </Key> <Property Name="Begda" Type="Edm.DateTime" Nullable="false" Precision="0" sap:label="Date" /> <Property Name="Endda" Type="Edm.DateTime" Nullable="false" Precision="0" sap:label="Date" /> ...Tiago A.

2 Answers

2
votes

the data returned from oODataModel.read is raw, before you post you need to parse it

 var handleRead = function (oEvent){
   //Get the data read from backend
   entity = oEvent.results[0];

   var newEntity = jQuery.extend({},entity);
   delete newEntity.__metadata;
   newEntity.Begda = new Date(entity.Begda);
   newEntity.Endda = new Date(entity.Endda);

   //Try to create a new entity with same data
   oODataModel.create('/PersDataSet', newEntity, null, function(){

why not use json instead of xml?

0
votes

Thanks all for the help. We got this working accounting for the following:

The problem of the wrong types appended to the attributes comes from the read itself. The object returned by read has a __metadata attribute which describes the values. In this object the dates are set with type=edm.string, even when the service says they are DateTime. To me this is a bug of the .read function.

When trying to use the same object to save, create sees the __metatada on the entry and uses those values, producing type edm.string type for the dates. This caused the request to be rejected. Manually changing these __metadata.properties...type to Edm.DateTime makes it work.

In the end, we did the following:

  • Dates are parsed manually from the Odata response, creating a js Date object from the strings in format "yyyy-mm-ddT00:00:00", to make it work with control bindings. When we want to save, the reverse is done.
  • The object to be created is a new object with only the attributes we care (no __metadata)