Skip to Content
Author's profile photo Thomas Jung

SAP HANA SPS 09: New Developer Features; New XSODATA Features

This blog is part of the larger series on all new developer features in SAP HANA SPS 09:http://scn.sap.com/community/developer-center/hana/blog/2014/12/02/sap-hana-sps-09-new-developer-features

In this blog we will look at new features in the XSODATA service framework in SAP HANA SPS 09.

Configurable Cache-settings for the $metadata request

When calling OData services, the $metadata document is often requested over and over again.  Yet changes to the underlying entity definitions is relatively rare. Therefore in SPS 09 we enable the option to configure caching of these $metadata documents in order to avoid the many redundant queries to the process the metadata.


service {
...
}
settings {
  content cache-control "no-store";
  metadata cache-control "max-age=3600,must-revalidate";
}

ETag Support

The OData specification uses ETags for optimistic concurrency control.  You can read more about the specification here: http://www.odata.org/documentation/odata-version-2-0/operations/#ConcurrencycontrolandETags

If the developer wants to support this feature in XSODATA, they have to enable it per entity in the .xsodata file. Example:


service
{ entity "sap.test.odata.db.views::Etag" as "EtagAll"
    key ("KEY_00") concurrencytoken;
  entity "sap.test.odata.db.views::Etag" as "EtagNvarchar"
   key ("KEY_00") concurrencytoken ("NVARCHAR_01","INTEGER_03");
}



If only “concurrencytoken” is specified, all properties, except the key properties, are used to calculate the etag value. If only specific properties are given, only those are used for the calculation. concurrencytoken” cannot be used on aggregated properties with aggregation method AVG (average).


Nullable Properties

All entity properties are automatically generated by the XSODATA layer during create and since they are not nullable, the consumer is now forced to pass dummy values into these property.

However OData supports $filter and $orderby conditions on the “null” value. This means, that it is now possible to treat “null” as a value, if the developer enables it. This behavior can only be enabled for the whole service, not per entity. Example:



service {
 …
 }
settings {
 support null;
 }



Only if this support is enabled, $filter requests like $filter=NVARCHAR_01 eq null are possible. Otherwise “null” is rejected with an exception.

If the support is not enabled, the default behavior applies and all null values are neglected in comparisons and the respective rows are removed from the result (i.e. common database behavior).


Odata Execution Tracking Utility

In order to ease the supportability and analysis of performance for OData request in HANA, we’ve added functionality to request to profile the performance of request processing (executed queries and the time spend in different OData components) in read and write requests. The requested profiling info is then accessible only if the XS engine is in debug mode.


Main usage is – tracking performance by:
1. Add query parameter named ‘profile’ to OData request that notifies the server to produce the report
2. If the parameter is present and engine is in debug mode – OData profiling is done
3. OData response is skipped and the server returns:
     HTML page with the collected information in case profile=html (default)
     JSON response with the collected info in case profile=
json

HANABlog5.png


OData Explorer

The SAP River Application Explorer has been rebuilt as a general SAP OData Explorer in SPS 09. It allows for the general testing and data generation of XSODATA based services. You can view all records in a service or create/delete/edit individual records. It also supports mass generation of multiple records at once with random value generation. It can be launched from the Web-based Development Workbench (via context menu option on XSODATA service) or directly via the url=

/sap/hana/ide/editor/plugin/testtools/odataexplorer/index.html?appName=<xsodata service path>


HANABlog6.png



Assigned Tags

      39 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo ROCCO MARINO
      ROCCO MARINO

      Hi,
      useful post.

      But i have a problem.
      I'm trying to create a sample application like this:

      /wp-content/uploads/2014/12/odataprj_613612.png

      The Odata service (appone.xsodata) works fine but when add 'Etags' in the Service (like your code) i have this error into HANA STUDIO:

      /wp-content/uploads/2014/12/etags_error_613686.png

      Can you help me?

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Try activating anyway. It should still activate just fine.  This is just the client side check in the Studio not getting updated for the new syntax.

      Author's profile photo ROCCO MARINO
      ROCCO MARINO

      I Activated Anyway it and I had following error:

      Keys cannot be specified for source "XXXX_test_appone.data::otable2" as it is a table object.


      What does it mean? Can I use etag with table object or only for view object?

      Author's profile photo Sreehari V Pillai
      Sreehari V Pillai

      Tables will have its own primary key(or composite key) , and it can not be specified again in xsodata.

      Author's profile photo Iulia Petrea-Papadima
      Iulia Petrea-Papadima

      Hi Thomas,

      I have the following issue. I created some ODATA services in HANA(SPS09) and I want to consume them in C#.

      For the simple operations (insert, update, delete) it's ok. But for batch-requests it's a problem.

      In HANA a change-set from a batch request should look like:

      --changeset_f290a406-5cdf-40a9-abd1-cfa4e741af3a
      Content-Type: application/http
      Content-Transfer-Encoding: binary

      POST http://***/OdataTestsProject/OdataTestService1.xsodata/t_ztable1 HTTP/1.1
      Content-ID: 1
      Content-Type: application/json;odata=verbose;charset=utf-8
      Accept: application/json;odata=verbose
      Content-Length: XXX

      {ID":38,"VERS_ID":14,"COL11":"Col 123","COL12":"Col 12345"}
      --changeset_f290a406-5cdf-40a9-abd1-cfa4e741af3a--

      The header "Content-Lenght" for an operation is needed.

      If I don't use it, then an error is raised.

      The C# libraries do not includ this "Content-Lenght" header for an operation. It seams that this is an optional header. I checked Microsoft OData service examples for protocols V1-3 and they all accept changesets without content length.

      Please tell me if it's possible to create batch requests without using this header (content-length) for operations.

      Thank you for your support!

      KInd Regards,

      Iulia

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Its not clear from the OData documentation if content-length is required or not:

      http://www.odata.org/documentation/odata-version-2-0/batch-processing/

      It doesn't explicitly state that it is required but is shown in all examples. I think there might be a case to be made that the underlying Multipart MIME v1.0 used in Batch operations is what specifies that the content-length must be used.

      If you feel that SAP is incorrect in requiring this header, then you should consider entering a support ticket.

      Author's profile photo Rene Kschamer
      Rene Kschamer

      Hi Thomas,

      I'm a colleague of Iuila and we really appreciate your your answer!

      You're right the documentation is not clear about if the Content-Length is mandatory or optional. However, if you look into the specification(s) it become quite clear:

      "The only exception is that the Content-Length request header is not mandatory in  requests that include request payloads."
      (Open Data Protocol (OData) Specification 2.0 - Page 233 - http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/[MS-ODATA].pdf)

      "As specified in [RFC7230], a request or response SHOULD include a Content-Length header when the message's length can be determined prior to being transferred. OData does not add any additional requirements over HTTP for writing Content-Length."

      (OData Version 4.0 Part 1: Protocol Plus Errata 02 - OData Version 4.0 Part 1: Protocol Plus Errata 02)

      As Iulia pointed out, our client is not setting the Content-Length header and adapting it is not that easy unfortunately. In any case, we don't think the service should raise an error if an optional field is missing in the (batch) request. We'll create a support ticket for this.

      Thanks again for your answer!

      Best,
      René

      Author's profile photo Former Member
      Former Member

      Hi Thomas,

      in the first section you say it is possible to enable caching for the $metadata requests. Can you pls explain how to obtain that. Similar to static content via .xsaccess file?

      Thanks and best regards,

      Timo.

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      I need to check with the developer of this new feature. I just tried the syntax which was documented for this feature and it didn't work in my system. It produces an activation error. Let me get the correct syntax and get back to you.

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Actually my bad.  The syntax does work, its just that the editor doesn't understand it and still produces an error.  The error can be ignored as the server side activation works just fine.  You need to add the settings syntax after all your entity definitions.  Here is an example:

      service {

      "SYS"."M_SYSTEM_OVERVIEW" keys("SECTION","NAME");

      }

      settings {

        metadata cache-control "no-store";

        content cache-control "max-age=3600,must-revalidate";

      }

      You use normal browser cache control headers. Whatever headers you add in the settings section will be added to the responses.

      Author's profile photo Former Member
      Former Member

      Hi Thomas,

      great, thanks much for your quick response. I'll test this asap.

      One additional question: We usually have several exposed objects in our .xsodata service. Is it possible to set caching for each of these individually?

      Thanks again,

      Timo.

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      No.  You can separate the settings between content and metadata, but not at the entity level.  To have different settings per entity you would have to separate them into different XSODATA files.

      Author's profile photo Former Member
      Former Member

      Ok, we'll consider that. Thanks again!

      Author's profile photo Michael Vogel
      Michael Vogel

      Hi Thomas,

      why do you set the cache-control for metadata to "no-store" and the content cache-control to "max-age=3600,must-revalidate"? I would expect to set it vice versa, as the metadata definition changes relatively rare and the content changes very often.

      Regards,

      Michael

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      That was just an example I cut and pasted out of a real service. For this particular service I guess we wanted to cache the result set but not the metadata. I can see that being reasonable. The metadata might not change often; but when it doesn't its critical to pick up that change for this particular application. On the other hand, the content might change but for this application its fine to cache the results. The point being that the settings give you the ability to control either independently depending upon your applications' requirements.

      Author's profile photo Michael Vogel
      Michael Vogel

      Hi Thomas,

      is it also possible to send an ETAG with the metadata response, which is send back to the server during metadata request, so that the server could send a 304 message, if the metadata was not changed?

      Regards,

      Michael

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      We do support eTags for concurrency control on the entities themselves; but not on metadata.  I do know that one of the improvements we are looking for the future is to reduce the number of metadata requests. This could end up being one of the ways we do that.

      Author's profile photo Former Member
      Former Member

      Hi Thomas,

      Thank you for your great post!

      I'm working on prototyping project with Fiori on HANA via XS-OData.
      I faced a performance issue. HANA itself is fast but performance becomes slow
      when XS-OData is used. I'd like to identify the reason from XS-OData specification.

      I think "Odata Execution Tracking Utility" may provide us with some hints.
      Could you tell me how to activate debug mode in XS engine and sample of OData request?
      Also, I appreciate it if you share how to analyze "OData Execution Profiler result".

      Kind regards,
      Masatoshi

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      >Could you tell me how to activate debug mode in XS engine and sample of OData request?

      xsengine.ini -> httpserver -> developer_mode = true

      >Also, I appreciate it if you share how to analyze "OData Execution Profiler result".

      Add profile=html as a URL parameter on your OData request exactly as shown in the screen shot in the above blog.

      Author's profile photo Former Member
      Former Member

      Hi Thomas,

      Thank you for quick reply!

      I checked the pass you described but I couldn't found the parameter "developer_mode"...

      Are there any prerequisite to enable the parameter to be shown?

      screen shot.PNG

      Masatoshi

      Author's profile photo Former Member
      Former Member

      Hi Thomas,

      Could you please tell me what would be the overhead in putting XS engine in debug mode ?
      Thank you
      Welly

      Author's profile photo Former Member
      Former Member

      Hi Masatoshi,

      we face performance issues with XS OData as well. When using $expand (check this by adding &profile to your url, as Thomas Jung just wrote), the odata implementation creates a local temporary table in hana. The subsequent insert statement on this temporary table seems to be very slow.

      We haven't dived deeper into this, yet.

      If you use $expand as well, this might be the reason for the bad performance.

      Cheers,

      Timo.

      Author's profile photo Former Member
      Former Member

      Hi Timo,

      Thank you for your sharing the information!

      We don't use $expand but use $format, $orderby and $filter.

      Masatoshi

      Author's profile photo Srinivas Maddineni
      Srinivas Maddineni

      Hi Friends,

      Has any body tried $metadata cache in xsodata. We are building an application in iOS, we are running a CRUD operation on a custom z table from xsjs.

      when I enable metadata caching in xsodata file like

      settings { 

      metadata cache-control "no-store"; 

      content cache-control "max-age=3600,must-revalidate";  }


      An INSERT is happening into Z table but the control is not getting the latest inserted record from SAP HANA. We are using business suite on HANA SPS09.


      When I remove cache and try, it works perfectly file. Is there any other tweaking required like setting max-age or so?


      Thanks in Advance.

      Best Regards,

      Srini.

      Author's profile photo Former Member
      Former Member

      Hi Srini,

      with the seetings you just posted, the content will be cached, but not the metadata. I think you might want it vice versa.

      For us metadata caching worked perfectly.

      Kind regards,
      Timo.

      Author's profile photo Srinivas Maddineni
      Srinivas Maddineni

      Thank you Timo,

      Good catch.

      I refereed above blog post and it was the way I pasted. It seems it got updated.

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Yes I changed the blog after your comment. I can see where it was bit confusing. I was describing the more common scenario of caching the metadata but then I had cut and pasted a source code example from a real service where I was actually doing the opposite and caching the service results instead. I reversed the code sample to be more clear.  Point however is that you can control the cache setting of either.

      Author's profile photo Srinivas Maddineni
      Srinivas Maddineni

      Thank you Thomas. But the help document http://help.sap.com/hana/SAP_HANA_Developer_Guide_for_SAP_HANA_Web_Workbench_en.pdf page 295 has the same misleading information. I hope team will correct it.

      Best Regards,

      Srini Maddineni

      Author's profile photo Srinivas Maddineni
      Srinivas Maddineni

      Hi Timo,

      I corrected the settings as follows.

      settings {

      support null;

      metadata cache-control "max-age=904800,must-revalidate";

      content cache-control "no-store"; }

      As per my understanding the SAPUI5 control shouldn't fire metadata call, even if it fires there should be a faster response. But I couldn't notice any difference in response time with metadata cache and without settings lines in my xsodata file. Please see screenshot of response with metadata.

      I appreciate your help on this.

      Screenshot_1.pngcache enabled.

      Author's profile photo Former Member
      Former Member

      Hi Srini,

      you have to unflag "Disable cache" in debugging mode of chrome (second line of your screenshot) and reload. Then chrome gives you information on cached content (by saying "(from cache)" in the size/content column.

      Best regards,

      Timo.

      Author's profile photo Srinivas Maddineni
      Srinivas Maddineni

      Hi Timo,

      Thank you so much for your time & efforts in analyzing this issue.

      I tried with removing disable cache in chrome developer tools general settings. It takes the same time with and without cache settings. I'm I doing something wrong here.

      metadata caching is important for me as we have around 40 to 60 services in one xsodata file. Please see screenshot.

      Screenshot_3.png

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Be careful.  Google Chrome ignores the Cache-Control or Expires header if you make a request immediately after another request to the same URI in the same tab (by clicking the refresh button or pressing the F5 key).

      Does Chrome reloadButton ignores the cache? - Super User

      I got tricked by the same when testing just now. As soon as I moved the URL to a new tab and loaded from there it got the $metadata from the Cache.
      /wp-content/uploads/2015/08/metadata_cache_777527.png

      Author's profile photo Srinivas Maddineni
      Srinivas Maddineni

      Thank you Thomas for the reply. Here is my observations. We are using AJAX calls from UI application.

      1. Tested a service without $metadata cache (chrome normal and incognito mode)

      Chrome is firing $metadata call for every refresh

      2. Tested a service with [metadata cache-control "max-age=900000,must-revalidate";]

      Chrome is not firing calls for every refresh, I fired 5 times but I see 1 call in the network tab.

      Your observation on new window is right and the service metadata is being loaded from Cache.

      Screenshot_4.png

      Author's profile photo Former Member
      Former Member

      Hi,

      Great blog!

      Is there any advice/guidance from SAP on when to use OData services over any of the other options available (ODBC, JDBC, XMLA...)?

      Sonni

      Author's profile photo Jon Humphrey
      Jon Humphrey

      Hi Thomas,

      I seem to be unable to use the OData explorer in my SPS9 system.  Whether I use the preloaded services or one of my own I get:ssodataerr1.JPG

      and yet the direct call to the service works:

      ssodataerr2.JPG

      Thanks,

      Jon

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Are you opening the OData Explorer from the Web Based Development Workbench (right mouse click on the service and choose Open OData Explorer)?  If so the correct service URL should be added to the OData Explorer URL for you.  From your screen shot it seems like the leading forward slash is missing from the service URL.  Have a look at this screen shot from my system for the correct URL format.  Try that and see if it helps.

      odataExplorer.png

      Author's profile photo Jon Humphrey
      Jon Humphrey

      Special prize to me for asking the dumbest question and to you for speed of response to it.

      Many thanks, Thomas

      Author's profile photo Former Member
      Former Member

      Hi Friends,

      Can anyone help me with this question:  https://answers.sap.com/questions/223959/how-to-set-nullable-true-in-xsodata-metadata-for-a.html# I want to know a way in which I can force xsodata metadata to display Nullable property even if it is true.

      Author's profile photo Tanveer Shaikh
      Tanveer Shaikh

      Hi Thomas,

      I successfully created xsodata service and able to test the service in browser with various parameters. And all works fine.

      Need of my application is to GET data using the generated local id for example –

      My result set is –

      {"__metadata": {"type":"odata.CV_ProjectDetailType"
      
          ,"uri":"/odata/odata.xsodata/CV_ProjectDetail('543859892167869371')"}
      
          ,"C_NAME":"SAP","CR_NUMBER":7},
      }

      And I want to access the same result set using –

      GET /odata/odata.xsodata/CV_ProjectDetail(‘543859892167869371’)

      Is there there a way to achieve this ? I got “RESOURCE NOT FOUND” error when I use generated IDs

      Thanks,

      Tanveer