Skip to Content

  OData CRUD from XSJS-Outbound API  

     SAP HANA Extended Application Services (SAP HANA XS) includes a server-side JavaScript API that enables outbound access to a defined HTTP destination. The HTTP destination provides services which an application can use. In the following steps , we will configure the connectivity with netweaver gateway system which provides us a Employee Odata service where we can C,R,U & D Employee details.

Step 1 : Create a XS Project in the project perspective.


     Create a XS project in the project explorer, maintaine .xsaccess file and .xsapp files and create four individual xsjs files for CRUD operations. After this step , our project hierarchy will look like below.

project1.JPG

Step 2 : Create a XS HTTP Connection parameters.


     Maintain a folder under the main project level named service, inside which we can maintain our connectivity parameters to the net weaver gateway.

Create a file named gateway.httpdest with the connection parameters as below.


host = “Target IP Address”;

port = Target Host;

description = “ABAP Gateway test”;

pathPrefix = “/sap/opu/odata/sap/ZEMPLOYEE_SRV”;

authType = none;

useProxy = false;

proxyHost = “”;

proxyPort = 0;

timeout = 0;

Step 3 : Implement GetEntity.xsjs.

          Here in this file, we will implement the Read operation on the Odata URL.


var destination;
var client;
var request;
var employeeID;
//Read the input employee number which is to be read
employeeID = $.request.parameters.get("EMPID");
try{
    //Reading the destination properties
    destination = $.net.http.readDestination("CRUD.service","gateway");
    //Creating HTTP Client
    client = new $.net.http.Client();
    //Creating Request
    request = new $.web.WebRequest($.net.http.GET,"Employee('"+employeeID+"')?$format=json");
    client.request(request,destination);
    //Getting the response body and setting as output data
    $.response.setBody(client.getResponse().body.asString());
}
catch(errorObj){
  $.response.setBody(JSON.stringify({
  ERROR : errorObj.message
  }));
}

Output :

GetEntity.JPG

Step 3 : Implement CreateEntity.xsjs.


     When an OData POST (Create) call is made, it is very much important to manage the Cross site request forgery by handling CSRF tokens(en.wikipedia.org/wiki/Cross-site_request_forgery ).

In order to make a POST call, we can trigger a GET(Read) request to the gateway system with the header “X-CSRF-Token” , and can use the returned CSRF Token.

getCSRF() function would return the CSRF Token to make the POST call. We can implement this method in the file CreateEntity.xsjs


var destination;
var client;
destination = $.net.http.readDestination("CRUD.service","gateway");
client = new $.net.http.Client();
function getCSRF()
{
  var request;
  var response;
  try{
    //GET Operation on the base odata URL
    request = new $.web.WebRequest($.net.http.GET,"/");
    //X-CSRF-Token header will be set with value Fetch
    request.headers.set("X-CSRF-Token", "Fetch");
    client.request(request,destination);
    response = client.getResponse();
    //reading the token from response header
    return response.headers.get("X-CSRF-Token").toString();
  }
  catch(errorObj){
  $.response.setBody(JSON.stringify({
  ERROR : errorObj.message
  }));
  return "CSRF TOKEN FETCH FAILED : " + errorObj.message;
  }
}

Implementing the POST Method call :


function makePOSTCall(CSRF){
  //Specifying the entity name for the POST operation
  var request = new $.web.WebRequest($.net.http.POST,"/Employee");
  try{
  //Setting the token header
  request.headers.set("x-csrf-token",CSRF);
  //Application content type
  request.headers.set("Content-Type","application/json");
  request.headers.set("X-Requested-With","XMLHttpRequest");
  //setting the data to be created
  request.setBody(JSON.stringify(
  {
  d: {
  Empid:"0000006000",
  Ename:"RAHUL GANDHI",
  Phone:"00000999999999"
  }
  }));
  client.request(request, destination);
  //Checking the status ( 201 for success )
return client.getResponse().status;// === '201' ? "Successfully Created" : "Not created:";
  }
  catch(eee){
  return "Error:"+eee.message;
  }
}
$.response.setBody(makePOSTCall(getCSRF()));

Output :

created.JPG

Step 4 : Implement DeleteEntity.xsjs.

    

     To DELETE an entity , we need to specify the Entity Key which is to be deleted and the OData operation DEL. For deletion, we do not need to pass any body as the body is irrelevant for the operation.


function deleteEmployee(CSRF){
  try{
  destination = $.net.http.readDestination("CRUD.service","gateway");
  client = new $.net.http.Client();
  //Specifying the entity name for the DELETE operation
  var request = new $.web.WebRequest($.net.http.DEL,"/Employee('"+employeeID+"')");
  //Setting the token header
  request.headers.set("x-csrf-token",CSRF);
  //Application content type
  request.headers.set("Content-Type","application/json");
  request.headers.set("X-Requested-With","XMLHttpRequest");
  client.request(request, destination);
  //Checking the status ( 204 for successful deletion )

  return client.getResponse().status;
  }
  catch(eee){
  return "Error:"+eee.message;
  }
}
$.response.setBody(deleteEmployee(getCSRF()));

We can use the same getCSRF() function used in CreateEntity.xsjs, her also.

Output :

deleted.JPG

Step 5 : Implement UpdateEntity.xsjs.


     While updating an entity , specify the key value of the entity to be updated and the new entity data in the http body.


function makePOSTCall(CSRF){
  //Specifying the entity name for the PUT operation
  var request = new $.web.WebRequest($.net.http.PUT,"/Employee('0000001000')");
  try{
  //Setting the token header
  request.headers.set("x-csrf-token",CSRF);
  //Application content type
  request.headers.set("Content-Type","application/json");
  request.headers.set("X-Requested-With","XMLHttpRequest");
  //setting the data to be created
  request.setBody(JSON.stringify(
  {
  d: {
  Empid:"0000001000",
  Ename:"Name Changed",
  Phone:"00000999999000"
  }
  }));
  client.request(request, destination);
  //Checking the status ( 204 for success )
  return client.getResponse().status;// === '204' ? "Successfully Created" : "Not created:";
  }
  catch(eee){
  return "Error:"+eee.message;
  }
}
$.response.setBody(makePOSTCall(getCSRF()));

Output :

updates.JPG

References :

odata.org,SAP HANA Developer guide

Regards

Sreehari V Pillai

“Save Nature For the Future”

To report this post you need to login first.

16 Comments

You must be Logged on to comment or reply to a post.

  1. Former Member

    Hi Sreehari,

    I have created xshttpdest and xsjs file. My requirement is to read the odata service from the xsjs file.

    While running the xsjs file one extra “/” is added in the service url after hostname from where i want to get the data and the xsjs file is giving below error

    {“ERROR”:”HttpClient.request: request failed: response from xxxxxxx/:80/sap/opu/odata/iwpgw/TASKPROCESSING;v=2/TaskCollection(’83’)/Description is pending…please retrieve it first with getResponse()”}

    I want to create this url

    xxxxxxx:80/sap/opu/odata/iwpgw/TASKPROCESSING;v=2/TaskCollection(’83’)/Description

    “hostname:port/pathprefix”

    Please let me know how to remove “/” after hostname.

    Destination code:

    host =”xxxxxxx”;
    port =80;
    description =”ABAP Gateway test”;
    pathPrefix =”sap/opu/odata/iwpgw/TASKPROCESSING;v=2/TaskCollection(’83’)/Description”;
    authType =basic;
    timeout =0;

     

    xsjs code

    try{
        //Reading the destination properties
        destination = $.net.http.readDestination(“test12.Services”,”dest00″);
        //Creating HTTP Client
        client = new $.net.http.Client();
        //Creating Request
       
        request = new $.web.WebRequest($.net.http.GET,”?$format=json”);
        
        client.request(request,destination);
        $.response.setBody(client.getResponse().body.asString());
    }
    catch(errorObj){
     $.response.setBody(JSON.stringify({
      ERROR : errorObj.message
      }));
    }

     

    (0) 
  2. Former Member

    Hi,

     

    I am new to sap technology. Basically i am from UNITY3D .NET background. I got a requirement to consume a xsodata service which uses client certificate to authenticate. In regular .net project i am able to get the data but the same is not working when used in UNITY. Getting 403 forbidden error.

    So i was thinking of using an xsjs service which will load the client certificate and gets me the data. Is there a way to do it? Kindly reply asap.

     

    thanks

     

    (0) 
  3. Former Member

    Hi Sree,

    thanks for sharing this post! I am also new to the sap technology. I have created the “gateway.httpdest” file, but where can i find the “pathPrefix”? In my case i want to send a webrequest from a xsjs file to a xsodata file which are both located in the same tree. if i use: pathPrefix=”/Package/Package/TSA.xsodata” i get this error: “The requested URL /TSAPI/xsodata/TSA.xsodataId(‘2’ was not found on this server.”

    I really hope you can help me out with this.

    thanks in advance

    (0) 
    1. Sreehari V Pillai Post author

       

      So, you want to send a request from XSJS to XSODATA . Well, are they the same system ? If yes – It doesn’t require to consume xsodata from xsjs , instead, you can consume the model behind the xsodata directly from XSJS .

      Sticking to your question – Run the xsodata file in browser . it would be something like https://<ip&gt;:port/package/abc/test/MYService.xsodata

       

      then /package/abc/test/MYService.xsodata is the pathPrefix.

      Sreehari

       

      (0) 
  4. Amit Kumar Barik

     

    Hi Sree,

    Facing issue while executing .xsjs file. Please refer to the attached doc and help me.

     

    GetAgentLists.xsjs

    var destination;
    var client;
    var request;
    //var employeeID;
    //Read the input employee number which is to be read
    //employeeID = $.request.parameters.get(“EMPID”);
    try{
    //Reading the destination properties
    destination = $.net.http.readDestination(“ChatBot.services”, “DEST_BOT_ODATA”);
    //Creating HTTP Client
    client = new $.net.http.Client();
    //Creating Request
    request = new $.web.WebRequest($.net.http.GET, “/PurchaseOrderSet(‘4500000405’)”);
    //request.headers.set(“x-csrf-token”,CSRF);
    client.request(request,destination);
    //Getting the response body and setting as output data
    $.response.setBody(client.getResponse().body.asString());
    }
    catch(errorObj){
    $.response.setBody(JSON.stringify({
    ERROR : errorObj.message
    }));
    }

     

    Xshttpdest file:

    description = “PO_Details”;
    //host = “aaesaws0521.aaes.XXXXXXX.com”;
    host = “madap8033.XXXXXXX.tsap”;
    port = 8001;
    pathPrefix = “/sap/opu/odata/SAP/ZAB_GET_PO_STATUS_SRV”;
    authType = none;
    useProxy = false;
    proxyHost = “”;
    proxyPort = 0;
    timeout = 0;
    //useSSL = false;
    //timeout = 0;
    //sslHostCheck = false;
    //sslAuth = anonymous;

     

    Getting this error while executing .xsjs file.

    {
    “ERROR”: “HttpClient.request: request failed: internal error occurred \”Failed to send request to socket…rc = -1\””
    }

    Regards,

    Amit

    (0) 
  5. Marco Harpenschläger

    Hey,

    I got the following error message:

    {“ERROR”:”read ECONNRESET”}

     

    I am using XSA and I defined the destination in the cockpit and connected the modules, it is working fine for other services, but not for mine.

    “protocol”: “https”,
    “port”: “51154”,
    “host”: “scotty-3.intern.zz”,
    “authType”: “none”,
    “pathPrefix”: “”,
    “timeout”: “0”

     

     

    This service is only available in the intranet, but this should not be an issue, should it?

    What does this error mean?

    Mayber because the connection is not save?

    BR

    Marcel

     

    (0) 
    1. Sreehari V Pillai Post author

      Hay, some possibilities to check

      1 . Does you server has access to the url ? ask the linux admin to curl the url .
      2. Do you have an http version of the url ? try any other intranet url having an http instead of https.
      3. May be you will need to set up some host file entry in the the linux ( if 1 fails )

      (0) 
      1. Marco Harpenschläger

        Thanks for the input, I will try it later.

        First I have a easier question.

        I need to user authType:”Basic”.

        I tried to set user: “XXX” and password : “YYY” but it says either wrong or not user crednetials.

        How can I pass user and password to a service with authentication?

        (0) 

Leave a Reply