Introduction : Many times consultants can be in a situation where the preferred UI Technology is SAPUI5 but services are exposed as WebServices rather than an OData model. The below blog will help you understand how you can consume a WebService from SAPUI5 via an XML model and show it in SAPUI5 user interface. Although some code samples are scattered here an there, one has to spend quite some time to make a scenario work. By the end of this blog you will have a fair understanding of the scenario and code to make it work.

Target Audience : Beginners to Experts alike.

Environment : Eclipse (Mars) with SAPUI5 plugins, Google Chrome browser.

Date Created: 4 Jan 16


I used the following publicly exposed WebServices to create a scenario :

http://www.w3schools.com/xml/tempconvert.asmx

http://www.w3schools.com/xml/tempconvert.asmx?WSDL

A convenient online WebService client :

http://wsdlbrowser.com/

You need to have the WSDL and then you can easily generate XML request and response. This is one of many options but it is interesting that with this site you can work without a Web Service client installation.

When dealing with XML in string format you might have issues using double quotes ” as XML also has them and diving your XML into multiple line. The problem can be resolved by using single quotes to represent strings and using string concatenation :

http://www.w3schools.com/js/js_strings.asp

Capture.PNG

Key code that does the job :

http://scn.sap.com/community/developer-center/front-end/blog/2014/07/23/consuming-web-service-in-sapui5

Sample Code (Thanks to Navya Krishna):

var request = “<Your input xml to the webservice>”; // more info in the appendix section

var response = “”;

$.ajax({

     url : “Your webservice wsdl url”,

     type : “POST”,

     data : request,

     dataType : “text”,

     contentType : “text/xml; charset=\”utf-8\””,

     success : function(data, textStatus, jqXHR) {

          response = data;

          console.log(“SUCCESS”);

     },

     error: function(xhr, status)

     {

          console.log(“ERROR”);

     },

     complete: function(xhr,status) {

         console.log(“COMPLETE”); 

     }

});

NOTE:

1). Since the WebService is not on the same machine as the SAPUI5 application it causes a “No ‘Access-Control-Allow-Origin’ header is present on the requested resource.” error

Capture.PNG

It can be resolved by using the inbuilt proxy. For e.g. url : “proxy/http/www.w3schools.com/xml/tempconvert.asmx?WSDL”,  in the above code.


2). For using the mentioned WebService I had to get rid of  </SOAP-ENV:Envelope> and </SOAP-ENV:Body> tags in my response to make the scenario work.

response = response.replace(‘<soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema“>’, ”);

response = response.replace(“<soap:Body>”, “”);                   

response = response.replace(“</soap:Body>”, “”);                  

response = response.replace(“</soap:Envelope>”, “”);


3). Do not forget to add the libraries required for running the scenario in the Bootstrap

data-sap-ui-libs=”sap.m, sap.ui.commons,sap.ui.table”

Sample code that can consumes a WebService Response, converts it into an XML model and displays the data in a Table :

NOTE: The code here does not run in a sequence if written right after Ajax call. Please use the success or complete functions to ensure code runs in a sequence.

var oModel = new sap.ui.model.xml.XMLModel(); 

function uicontrols(){

     oModel.setXML(response);

}

var oTable = new sap.ui.table.Table({

     id: “table1”

});

oTable.addColumn(

     new sap.ui.table.Column({

          label: new sap.ui.commons.Label({text: “Label1”}),       

          template: new sap.ui.commons.TextField().bindProperty(“value”, “Tag1/text()”) 

     })

);

oTable.addColumn(

     new sap.ui.table.Column({

          label: new sap.ui.commons.Label({text: “Label2”}),

          template: new sap.ui.commons.TextField().bindProperty(“value”, “Tag2/text()”)

  })

);

oTable.setModel(oModel);

oTable.bindRows({path: “/the main XML tag under which Tag1 and Tag2 are present/”});

Appendix :

Sample Request XML based on above mentioned public WebService

var request = ‘<?xml version=”1.0″ encoding=”UTF-8″?>’ +

  ‘<SOAP-ENV:Envelope xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:ns1=”http://www.w3schools.com/xml/“>’ +

  ‘<SOAP-ENV:Body>’ +

  ‘<ns1:CelsiusToFahrenheit>’ +

  ‘<ns1:Celsius>10</ns1:Celsius>’ +

  ‘</ns1:CelsiusToFahrenheit>’ +

  ‘</SOAP-ENV:Body>’ +

  ‘</SOAP-ENV:Envelope>’;


Another sample code that simulates consuming a WebService Response, converting it into an XML model and displaying the data in a Table.

(Thanks to Konstantin Anikeev)

https://scn.sap.com/thread/3307300

// start of code

var oModel = new sap.ui.model.xml.XMLModel();

  oModel.setXML(“<?xml version=\”1.0\” encoding=\”UTF-8\”?>”+

  “<config>”+

  “<item date=\”January 2009\”>”+

  “<mode>1</mode>”+

  “<unit>900</unit>”+

  “<current>1</current>”+

  “<interactive>1</interactive>”+

  “</item>”+

  “<item date=\”February 2009\”>”+

  “<mode>2</mode>”+

  “<unit>400</unit>”+

  “<current>2</current>”+

  “<interactive>5</interactive>”+

  “</item>”+

  “<item date=\”December 2009\”>”+

  “<mode>9</mode>”+

  “<unit>5</unit>”+

  “<current>100</current>”+

  “<interactive>3</interactive>”+

  “</item>”+

  “</config>”);

  try{

  alert(“GETXML>>>>:”+oModel.getXML());

  }catch(e){

  alert(e.message);

  }

  oTable.addColumn(

  new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: “Date”}),

  template: new sap.ui.commons.TextField().bindProperty(“value”, “@date”)  }

  )

  );

  oTable.addColumn(

  new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: “Mode”}),

  template: new sap.ui.commons.TextField().bindProperty(“value”, “mode/text()”)  }

  )

  );

  oTable.addColumn(

  new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: “Unit”}),

  template: new sap.ui.commons.TextField().bindProperty(“value”, “unit/text()”)  }

  )

  );

  oTable.addColumn(

  new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: “Current”}),

  template: new sap.ui.commons.TextField().bindProperty(“value”, “current/text()”)  }

  )

  );

  oTable.addColumn(

  new sap.ui.table.Column({

  label: new sap.ui.commons.Label({text: “Interactive”}),

  template: new sap.ui.commons.TextField().bindProperty(“value”, “interactive/text()”)  }

  )

  );

  oTable.setModel(oModel);

  oTable.bindRows({path: “/item/”});

// End of code

To report this post you need to login first.

8 Comments

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

  1. Fabio Pagoti

    SAPUI5 provides very good integration with OData but not so easily with WebServices.

    Yes it does and they are known as JSONModel and XMLModel, which you have in your code snippets. It’s easier when your services are REST based.

    (0) 
    1. Amol Gupta Post author

      Hi Fabio,

      Thanks for the proactive feedback, corrected it. But dont you think consuming OData services is much easier compared to Web Services ? For example you dont have to build Request XML or make an AJAX call. For a simple scenario with a couple of fields it is manageable but with a bigger real world application with numerous structures and fields, it is an extra overhead that needs extra coding effort which increases the chances of issues/bugs and  associated troubleshooting which in turn significantly  increases development turn around time.

      Regards,

      Amol Gupta

      (0) 
      1. Fabio Pagoti

        Hi Amol Gupta,

        Actually I don’t think so. Comparing the effort of consumption between an oData service and a XML or JSON based service, the only thing that changes in your UI5 code is the name of the model class being used. Instead of ODataModel, you would use a XMLModel or JSONModel class. Such classes already make AJAX calls for you in order to get data. Your data binding should be the same assuming the services responses have all the same structure.

        Of course, if you consider not just data retrieval scenarios, when the consumer has to push some data to the server (POST, PUT, MERGE, etc), them of course you would have to do some extra AJAX calls yourself. Using jQuery this is almost effortless.

        However this is not a limitation from JSONModel or XMLModel classes. The point is that oData is a server based model class where XML and JSON are client based model classes. The oData protocol has more (known by the client) features comparing to random customized services. As a consequence, ODataModel class has more methods and more functionality.

        It would be extremely hard for UI5 developers to build JSON and XMLModel classes with “create”, “update” or “delete” methods because the service might only work according to bizarre rules defined by the back end developer. Should the request contain a specific header? What are the HTTP methods supported by the server? Does it support other unicode? What is the content type? jQuery has already solved this issue.

        Concluding, IMO it does not change much for reading data. In order to solve CUD scenarios you will need more than client based models because well… they are just client based.

        Fábio Pagoti

        (0) 
  2. anubha pandey

    Hi Amol, thanks for the blog. Even though I followed Kavya’s blog, but was able to execute the ajax query and get response only after going through yours.

    Now, I am stuck at the stage – parsing the XML and get me output from response.

    Since I have only one field in output, it is easier for me to user DOM Parser.

    Could you please let me know, if I need to add below libraries to my controller.js file.

    (0) 
  3. Prabh Simran Kaur

    Hi Amol,

    After following the above steps , i get stuck data binding in Table. I am not sure where I am going wrong in setting the data

    Here is ajax call

    var oModel = new sap.ui.model.xml.XMLModel();

    $.ajax({

       url:”webservice url”,

      type: “POST”,

      data: request,

      dataType: “text”,

      async: false,

         contentType: “text/xml; charset=\”utf-8\””,

      success: function(data, textStatus, jqXHR) {

      response = data;

    response = response.replace(‘<soap-env:Envelope xmlns:soap-env=”http://schemas.xmlsoap.org/soap/envelope/“>’,”<documents>”);

      response = response.replace(‘<tag>’,””);

      response = response.replace(“<soap-env:Header/>”, “”);                

      response = response.replace(“<soap-env:Body>”, “”);     

      response = response.replace(“</soap-env:Body>”, “”);  

      response = response.replace(“<tag>”,””);

      response = response.replace(“</soap-env:Envelope>”, “</documents>”);

      console.log(“SUCCESS” + response);

      },

      error: function(xhr, status) {

      console.log(“ERROR”);

      },

      complete: function(xhr, status) {

      console.log(“COMPLETE”);

      oModel.setXML(response);

      }

      });

    <documents> root tag is added to overcome xml parsing error.

    I am directly setting this model in sap.m.Table control via .

    this.byId(“tableId”).setModel(oModel);

    Console shows oModel.getData as #document instead of object.

    /wp-content/uploads/2016/09/screenshot_1045727.jpg

    View.xml

    <Table id=”resultTable” items=”{path:’#document/documents/item/subitem’}”>

      <columns>

      <Column>

      <Text text=”SalesNo” id=”sales”/>

      </Column>

      <Column>

      <Text text=”Account” id=”account”/>

      </Column>

      </columns>

      <items>

      <ColumnListItem type=”Navigation” press=”onPress”>

      <cells>

      <Text text=”{@SALESNO}”/>

      <Text text=”{@ACCOUNT}”/>

      </cells>

      </ColumnListItem>

      </items>

      </Table>

    What path should be given in xml view to fetch the data returned by webservice in xml.format.

    (0) 

Leave a Reply