Skip to Content
Author's profile photo Thomas Jung

SAP HANA SPS 09: New Developer Features; XSDS (XS Data Services)

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

Additional blogs on this topic:

In SPS 09, SAP introduces a major extension to the programming model in the form of a reusable XSJS Library called XSDS or XS Data Services. There are several goals for this new library and the impact that it has on the overall programming model.

General HANA artifact consumption

  • Native JavaScript embedding of HANA database artifacts
  • Structured API calls instead of low-level SQL Interface
  • Less boilerplate coding (for example result set conversions)

Native CDS Consumption

  • Import CDS entities as native JavaScript objects
  • Understand CDS metadata for working with JavaScript objects

The origin of this extension to the programming model is that there were originally three separate projects/libraries built within SAP.  They focused on different aspects of data consumption within XSJS. They were an ORM (Object Relationship Mapper) library, a Query Builder, and a Relationship library.

HANABlog59.png

While these three individual libraries all had value on their own; ultimately SAP decided to integrate them together into one single library and also build them onto the CDS/HDBDD foundation for even better reuse of information that already exists within the database layer.

CDS (Core Data Services)

Core Data Services are a cross-platform set of concepts and tools to define semantically rich data models.  Within SAP HANA we already have the development artifact HDBDD for using the CDS syntax to define tables (entities), their relationships and views that utilize those relationships. A central part of the CDS specification is the object-relationship mapping that links semantically meaningful entities to their technical representation as records in the HANA database.

The short description of XSDS then can be consider as the native CDS embedding for JavaScript in the XS application services layer of the SAP HANA Programming Model.

HANABlog60.png

At its core, XSDS allows you to import and extend CDS entity definitions.  You simply supply the package path and file name of the HDBDD and the entity name during the import. The XSDS library reads the available metadata on types, keys and associations.  It also supports extensions, projections, and renaming of entity definitions.  It also supports CDS conceptions (like backlink and via entity associations) which aren’t yet supported by HDBDD definitions.

In this simple example we import the Employees entity from the EPM hdbdd artifact and the MasterData Context.


$.import("sap.hana.xs.libs.dbutils", "xsds");
var XSDS = $.sap.hana.xs.libs.dbutils.xsds;
var oEmployee = XSDS.$importEntity("sap.hana.democontent.epmNext.data", "EPM.MasterData.Employees");



oEmployee is a now a JavaScript which contains all this metadata which was already defined in the underlying CDS model. It also supports full CRUD transactionality via this JavaScript object.

Import Pre-Generation

However, this import of the metadata from the underlying model can be a relatively costly operation. Because the XSJS programming model is stateless this often creates the situation where you must re-import the CDS metadata for every single request.

For this reason the XSDS library also support pregeneration of imports in order to improve performance.  The library serializes the result of the import into a single reusable XSJSLIB file. Therefore instead of importing the entity from the HDBDD artifact you can use standard $.import feature of XSJS to utilize this prebuilt library definition.

Managed/Unmanaged

However XSDS isn’t limited to only using CDS Entities. The goal for XSDS was to provide a single solution for all XSJS applications.  This means being able to use the same access library even if your base tables are directly created in the catalog and not via CDS. This way you can decide between Managed or Unmanaged modes in the library.

Managed mode allows you to import entity definitions from catalog objects and from CDS definitions (as described above). It is best used when you need consistency in access. It functions as a lightweight ORM building JavaScript objects from catalog or CDS definitions. It supports navigation via associations, data consistency and a limited query ability.

Unmanaged mode, on the other hand, functions as a Query Builder to provide you with maximum flexibility and access to nearly the full HANA SQL Syntax but via a simplified query interface. Data consistency between entities, however, remains the responsibility of the application developer.

Now for more details, lets look at some syntax examples of both Managed and Unmanaged Mode.

Managed Mode

Earlier we saw how to import a CDS entity definition.  You can also import catalog object definitions as well:


var Demo= XSDS.$defineEntity("Demo", '"DEMOSP9"."DEMO_TABLE"');



In this case we supply the Schema and Table name from the catalog instead of the path to the HDBDD artifact.

Regardless of the source of the entity, we perform the same core operations on the entity after its imported into a JavaScript object.

We can create, retieve, update, and delete instances of the entity.


var post = Post.$get({ pid: 101 });



The result is a plain JavaScript object that can be programming against like any other JavaScript object.


if (post.Author.Name === 'Alice') post.Rating++;



Optionally the objects support lazy retrieval of associated instances to avoid “n+1 problem”.  The library also optimizes Join strategy to minimize Database queries.

You can write changes into the database explicitly.


post.$save();



The transaction manager tracks local changes for minimal updates to the database.

As far as instance manipulation goes we can retrieve a single instance by key:


var post = Post.$get({ pid: 101 });



You can then update an instance like this:


post.Author.Name = "Alice";
post.$save();



Or you can create a new instance using this syntax:


var user = new User({ Name: "Alice", Created: new Date() });
user.$save();



Deletion works similarly:


post.$discard();



Instance Management

As the above examples show the entity instances are managed. This means that instances are singleton objects with “personality”. Associated instances are stored by reference.

The benefits of this approach are that the runtime guarantees consistency.  You have a single consistent view on every instance enforced by the $save operation. You also have automatic association management across all relationship cardinalities (1:1, 1:n, and m:n).

The downside, on the other hand, is that we need additional overhead for instance management.  We are also limited to a subset of database functionality for instance retrieval.

HANABlog61.png

Transaction Handling

The managed mode also has impacts on the transaction handling.  We receive the benefits of transparent database and transaction handling. With a minimal XSDS runtime, the library is still able to provide metadata processing, entity cache, and type conversion during the transaction. It still exposes and reuses as much underlying database functionality as possible (for example: Constraints checks).

XSDS uses a single Database connection and single transaction.  This makes it well suited for single-threaded, per-request execution model of the XS processing layer.  It supports auto commit, explicit commits, and rollbacks. It also supports connection configuration files (XSSQLCC).

Unmanaged Mode

We also have unmanaged mode for when you want a more convenient database interface but don’t want to give up the full database syntax.  For example here is the typical database join statement in XSJS code.


var rs = conn.prepareStatement(‘
SELECT a."Name", c."Text.Text"
  FROM "bboard.post" p
  JOIN "bboard.user" a ON p."Author.uid"=a."uid"
  JOIN "bboard.comment" c ON p."pid"=c."Post.pid"
  JOIN "bboard.user" ca ON c."Author.uid"=ca."uid"
WHERE a."uid"=ca."uid“').execute();
while (rs.next()) {
  rs.getInt(1); rs.getString(2);
}


There are several problems here which XSDS unmanaged mode addresses.

Leaking Abstraction:

  • Column name can only be derived from the underlying table definition

Convenience:

  • String based query interface
  • Manual result set processing

Redundant Code:

  • Joins could be derived from underlying metadata instead of hand written

For these reasons the XSDS library also supports a query library for Ad-hoc queries.  It allows you to construct general queries in a very JavaScript-like way:


var query = Post.$query().$where(Post.Author.Name.$eq("Alice"));
var results = query.$execute();


The result object still yields a plain JavaScript object as unmanaged values not an instance as of a managed object.

The Query Language used here has several features:

  • Incremental query building for better readability/maintainability
  • Operators like $project, $where, and $matching
  • Full support for CDS path navigation
  • Expression language based on CDS Query Language using fluent API
  • Alternative, more concise JSON-like selection notation for restricted subsets

Here are some additional code examples to help you learn some of these benefits.

$project

Projections with CDS navigation expressions:


var res = Post.$query().$project({ Author: {Name: true},          
                  Comments: {Author: {Name: true}},
                  Title: "TitleOfPost"}).$execute();


The results of this query would look something like this:


[{             Author: {
                                Name: "Alice"
                },
                Comments: {
                                Author: {
                                Name: "Bob"
                                }
                },
                TitleOfPost: "First Post!"
}, ...]


$where

The library supports complex where conditions like the following:


var selfCommentingPosts = Post.$query().$where(Post.Comments.Author.pid.$eq(Post.Author.pid))
.$execute();


There are predefined operators of the expression language:

  • $eq
  • $ne
  • $gt
  • $lt
  • $ge
  • $le
  • $like
  • $unlike

But you can still escape to any SQL operator:


var somePost = Post.$query() .$where(Post.Rating.$prefixOp('SQRT').$gt(2)).$execute();


$matching

$matching allows selection using a template for the result.


var interestingPosts = Post.$query().$matching({
    Rating: {
        $gt: 2
    },
    Tags: {
        Name: "+1"
    }
}).execute();


**Note the Unmanaged version of $find and $findAll uses the same template language.

Incremental Query Construction

Incremental construction with immutable query objects:


// build query without DB call
var qBadPosts = Post.$query().$where(Post.Author.pid)
  .$eq(Post.Comments.Author.pid)));
// refine query
var qStarBadPosts = qBadPosts.$where(Post.Rating.$gt(4));


Explicit trigger:


// trigger actual DB calls
var badTitles = qBadPosts.$project(
                { Title: true, Author: {Name : true}}).$execute();
var recentBadTitles = qStarBadPosts.$project({ Title: true })
  .$execute();


JSON Expressions

Simple expressions:


Post.$find({ mandt: "001", pid: 101 });


Complex expressions:


Post.$find({ Title: { $like: "First%" },
             Rating: { $gt: 1, $lt: 3 },
 Created: { $lt: Date.now() – 3600 } });


JSON Expression Language Operators:

  • $eq
  • $ne
  • $lt
  • $le
  • $gt
  • $ge
  • $like
  • $unlike
  • $null

Optimized Query Construction

The query construction allows for incremental query construction without database roundtrips.  Immutable query objects support sharing of subqueries. This results in just-in-time translation into plain SQL using needed joins.

Assigned Tags

      19 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Sreehari V Pillai
      Sreehari V Pillai

      Thanks for the blog Thomas . This resembles RDL .

      Author's profile photo Bert Deterd
      Bert Deterd

      Wow. Just tried it and it works very nice. This is going to be a great helpful library.

      Good work SAP!

      Author's profile photo hariz houssem
      hariz houssem

      Hi Bert,

      Can you share your code please.
      I tried several times and didn't get result

      Thanks in advance

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

      You tried what several times?  Might I suggest if you are having problems using the XSDS libraries that you post a question with details in the SAP HANA Developer Center forums.

      Author's profile photo hariz houssem
      hariz houssem

      Thank you Thomas,

      I had some problem with my instance and I fix it.

      Author's profile photo Madhuri Muthyalu
      Madhuri Muthyalu

      Hi Thomas,

      Great Blog!!! very informative.

      When you say " It also supports extensions" does it mean that it adds more properties to the actual Entity?

      Regards,

      Madhuri

      Author's profile photo Rakshetha J N
      Rakshetha J N

      Hi Thomas ,

      You mention that we can enhance an entity

      Please find below the code of my test.xsjs file

      var xsds=$.import("sap.hana.xs.libs.dbutils", "xsds");

      var Post =xsds.$importEntity("test.db",

        "bboard.post", {

      testname:String(10)

      });

      here I have added the field testname, the xsjs executes sucessfully but there is no change in my entity.

      I am using HANA rev 95.

      I also tired to extend the post entity with the comment association with backlink ,

      that also reflects no change in the post entity .

      Can you please help in this issue.

      thanks and regards

      Rakshetha

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

      Are you expecting that the underlying database tables would change in a permanent way? If so you misunderstand how this works.  These extensions are to the runtime object temporary and don't persist back into the entity definition (database table or view).

      Author's profile photo Jaideep Adhvaryu
      Jaideep Adhvaryu

      Hi,

      I keep on getting error 503 "service not available" for my simple xsjs code:

      // start

      var pRegion = $.request.parameters.get("region");

      var conn = $.hdb.getConnection();  

      var query = 'select "ZAPPS_UsageLog"."Enriched_ZAPP_UsgRecord"."ZAPPName", "ZAPPS_UsageLog"."Enriched_ZAPP_UsgRecord"."CompanyName", "ZAPPS_UsageLog"."Enriched_ZAPP_UsgRecord".LAT, "ZAPPS_UsageLog"."Enriched_ZAPP_UsgRecord".LON from "ZAPPS_UsageLog"."Enriched_ZAPP_UsgRecord","ZAPPS_UsageLog"."CountrySpatialPolygons";';

      var rs = conn.executeQuery(query);

      $.response.status = $.net.http.OK;

      $.response.contentType = "application/json";

      $.response.setBody(JSON.stringify(rs));

      // end

      It seems like it is timing out.

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

      Your question isn't related to the topic of this blog. Therefore it would be better suited to its own forum posting.  If you think you are timing out, then when happens when you run the same query from the SQL Console?  Or are you retrieving a very large result set? There doesn't seem to be any where condition on your query.

      Author's profile photo Naga Prakash
      Naga Prakash

      Hi Thomas Jung

      Can we import the CDS views created in ABAP perspective using XSDS ? or it is only HANA CDS Views.

      Thanks,

      Naga

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

      No you can not reuse CDS Metadata from ABAP CDS in XSDS. It only reads the HANA CDS metadata.  You could define the entities directly in XSDS like you would any other catalog object.

      Author's profile photo Dirk Raschke
      Dirk Raschke

      Hi Thomas,

      does XSDS will also work for XSA?

      Thanks!

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

      We do have a new implementation of XSDS directly in node.js. Its the module sap-cds. It is the successor of the XSDS library and contains most major features already present in the older library. This module can also be used within XSJS Compatibility Layer as a replacement for the XSDS xsjslib.

      var conn = $.db.getConnection();
      var cds = $.require("cds").xsjs(conn);

      There are additional XSJS Compatibility examples in the embedded documentation within with the module itself.

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

      I'm really glad you posted this question. I hadn't even considered the XSDS usage in the conversion process.  Its a very good point and I'll now add an example to my TechEd content for this. I've actually been trying to go through the common XSA questions here on SCN and use them as the basis of the content for TechEd. 

      If you want to have a look at what we are building for TechEd, its available in GitHub: GitHub - I809764/dev703: SAP TechEd 2016: Code Review; Migrating Applications to HDI/XSA  With any luck, I'll be able to commit an XSDS example by the end of my day.

      Author's profile photo Dirk Raschke
      Dirk Raschke

      Hi Thomas,

      that are fantastic news for us.

      I really really love your XSDS feature and was wondering while nobody was talking about it. (And I thought I saw all sap-moduls, but didn't see the cds-one before. )

      But now I really glad to hear that you didn't give up this feature.

      And of course we would really appreciate it, if you could show us only a small sample.


      Thanks a lot!!!

      Author's profile photo Dirk Raschke
      Dirk Raschke

      Hi Thomas,

      I saw this in the xsa developer documentation and it sounds to me, that the development for this modul is finished. Is there an other NoSQL sap-modul in work or how should I understand this note?

      “Note: The sap-cds library is now considered feature complete. It will remain fully supported but will not receive any further enhancements in future releases.”

      Thanks for your advice!

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

      I think the description that its finished is accurate.  It will remain supported but we aren't going to invest in it further.

      Author's profile photo Dirk Raschke
      Dirk Raschke

      Thanks, this helps me a lot by my decision for the future.

      In general I tried to use it once, but wasn’t able to get it to work.  In addition I found to less samples for sap-cds, so I decided to use “normal” sql-queries. But its sad, because I used to work with it in the past (mongodb) and I loved it, because the select was much more easier to understand. At least for me!

      Thanks!