Skip to Content
Author's profile photo Jhodel Cailan

How to implement Function Import in HANA XS

Hello Everyone!

This is my first blog post and it is all about a feature that I found missing in HANA XSODATA — support for OData Function Imports.  While this feature can be implemented in a custom way through XSJS, I would like to have this custom implementation compliant with OData V2 specification in order for the consumer application (which is SAPUI5) to be able to leverage the existing ODataModel V2 library.  This is my journey for achieving this requirement — by creating a custom function import utility through XSJS.

 

 

Overview

I need to develop an OData service on top of SAP HANA XS engine through the XSODATA framework, however, according to this SAP Q&A, Function Imports are not supported by the XSODATA framework and can only be implemented using the XSJS framework.

When implementing an XSJS service, by default, it would need to be called by using an AJAX call.  But when you are using SAPUI5 framework, as a UI5 developer, you don’t normally have to use AJAX in your UI5 application, you would normally use ODataModel V2 instead.  A lot of service handling capabilities is already provided by the standard ODataModel V2 library, so we want to make use of those capabilities as much as possible when consuming the custom XSJS service.

In order to achieve the above requirement, the XSJS service needs to be compliant with the OData V2 specifications.  Therefore, I have created this custom Function Import Utility through XSJS that is compliant with OData V2 spefications.

 

Prerequisites

  • Understanding of OData V2 specifications – especially Function Import operation
  • Understanding of SAP HANA XSJS Development in XSA (the concept should be the same if implemented in XSC)

 

Function Import Utility

Refer to this repository in GitHub for the sample implementation of the Function Import Utility.

Basically there are a total of 4 XSJS Library files in this utility:

Notes and limitations:

  • This utility/framework may be incomplete, it was created to be able to cater the requirements we need
  • No support for OData $batch functionality

 

How to use

  • In the SAP WebIDE for SAP HANA tool, create a new MTA Project
  • In the new MTA Project, create a Nodejs Module with XSJS support
  • In the Nodejs Module under the “lib” folder, create a folder called “custom”
  • In the new “custom” folder, import the Function Import Utility files
  • In the “lib” folder, create a new XSJS file — SampleFunction.xsjs
  • Here is a sample code for SampleFunction.xsjs:
"use strict";

$.import("custom", "type");
$.import("custom", "FunctionImportUtility");  

// Function Import Utility expects an importing parameter of type 
// Object (data model definition object) which contains the data  
// model definition for the function import and its return type
$.custom.FunctionImportUtility.execute({
	ComplexType: {
		Name: "TotalAmountType",
		Property: {
			Name: "TotalAmount",
			Type: $.custom.type.DECIMAL,
			Precision: "15",
			Scale: "0"
		}
	},
	
	FunctionImport: [{
		Name: "GetTotalAmount",
		// the return type is based on the complex type TotalAmountType
		ReturnType: "TotalAmountType",  
		HttpMethod: "GET",
		// the exit function implementation that is similar to the 
		// exit function in XSODATA framework
		ExitFunction: "xsjs:GetTotalAmount.xsjslib::onExecuteAction", 
		Parameter: [{
			Name: "SalesOrderId",
			Type: $.custom.type.STRING,
			MaxLength: "10"
		}]
	}]
});
  • Under the “lib” folder, create a new folder called “xsjs”
  • Under the “xsjs” folder, create a new file called GetTotalAmount.xsjslib.  Take note that this is the exit function implementation that is being referenced by the XSJS service created above.
  • Here is a sample code for GetTotalAmount.xsjslib:
"use strict";

function _getTotalAmount(sSalesOrderId) {
	// implement your logic here ...
	
	// for simplicity of the demo just return a hardcoded value
	return (sSalesOrderId === "0100000000") ? 100 : 0;
}

function onExecuteAction(oParameter) {
	// oParameter will contain the parameters defined in Function Import
	// definition in SampleFunction.xsjs
	var sSalesOrderId = oParameter.SalesOrderId;

	// Implement your logic to get the TotalAmount based on sSalesOrderId
	var iTotalAmount = _getTotalAmount(sSalesOrderId);
   
	// Return an object that has properties matching the data definition
	// of the Function Import's return type
	return {
		TotalAmount: iTotalAmount
	};
}

That’s it!  You’re all set to test the function import implementation!

 

Testing the implementation

For this testing, I will just show how to consume the OData Service on a regular chrome browser, just like how a backend developer would normally test his/her OData service.

  • Execute the Nodejs module and wait until the service URL is generated by the WebIDE
  • Get the metadata of the OData Function Import implementation by using $metadata

  • Note that the EDMX file is generated based on the Data Model Definition maintained in SampleFunction.xsjs.  If you have been developing SAPUI5 apps, you probably already know that when you instantiate an object of sap.ui.model.odata.V2.ODataModel, this OData model will first call the $metadata to fetch the EDMX and the success of the instantiation depends on the successful fetch of EDMX file.
  • Now, let’s test the actual Function Import — GetTotalAmount.  We can test the function import the same way we test an OData service created from SAP Gateway — see below:

  • During the implementation, we have hardcoded the response to get the TotalAmount and we wrap the TotalAmount value inside a regular JavaScript Object.
	return {
		TotalAmount: iTotalAmount
	};
  • However, take note of the result of the Function Import call on the browser, you can see that the response is now wrapped with a fully qualified OData response that is returned by a Function Import.  Because of this behaviour, the object of sap.ui.model.odata.v2.ODataModel will be able to interpret the OData service response correctly.

That is all about it for testing the implementation of a fully qualified OData function import using XSJS service.

 

Closing

By using a framework concept like this, the consumption of the XSJS service to perform a Function Import operation is simplified since we can now use the SAPUI5 class library sap.ui.model.odata.v2.ODataModel, otherwise, the UI5 developers will need to use the conventional AJAX method call.

Notice how a simple framework can help on generating the EDMX file and making the function import response compliant with OData V2 specification.

Probably the next relevant thing to do is to try this out into a real SAPUI5 application using the ODataModel V2.  Let me know if it worked for you too. Cheers!

Assigned Tags

      5 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Jimmy Arnold Moreno Nuñez
      Jimmy Arnold Moreno Nuñez

      Hi Jhodel.

      Nice blog. I have a problem when I make this reference:

      // the exit function implementation that is similar to the 
      // exit function in XSODATA framework
      		ExitFunction: "xsjs:GetTotalAmount.xsjslib::onExecuteAction",

      I get this error:

      {"error":{"code":"500","message":{"lang":"en-US","value":"Internal Server Error"},"innererror":"Xsjs library with id \"xsjs.GetTotalAmount\" not found"}}

      This is the structure MTA project

      Thanks in advance.

      Author's profile photo Jhodel Cailan
      Jhodel Cailan
      Blog Post Author

      Hi Jimmy,

      The problem is with your reference:

      ExitFunction: "xsjs:GetTotalAmount.xsjslib::onExecuteAction",

      xsjs here translates into folder. lib folder is the root of your xsjs module. You can solve the issue by either removing the xsjs in the above config, or put your GetTotalAmount.xsjslib inside an xsjs folder.

      Author's profile photo Jimmy Arnold Moreno Nuñez
      Jimmy Arnold Moreno Nuñez

      Hi Jhodel.

      On another hand, I see that you import Library files. Why? I created an XSJSLIB to generate a correlative with a sequence in HANA but when I execute UPDATE setence I get this error:

      {"error":{"code":"500","message":{"lang":"en-US","value":"Internal Server Error"},"innererror":{"code":7,"message":"feature not supported: update statement for volatile table: line 1 col 8 (at pos 7)","sqlState":"HY000"}}}

      Maybe I lost a file import. 

      PS: I have HaaS HANA Image Version 5.0.1

      Thanks in advance.

      Author's profile photo Jhodel Cailan
      Jhodel Cailan
      Blog Post Author

      Hi Jimmy,

      It's very hard to determine the issue with the information you provided. Basically importing files is a modularization technique used everywhere in the programming world.

      Author's profile photo Kevin Dass
      Kevin Dass

      Jhodel,

      Appreciate if you could share inputs on other HttpRequest calls POST/PUT/DELETE?

      Regards,

      Kevin Dass