Skip to Content
Technical Articles

5 SIMPLE steps to wrap a REST service with a nice UI5.

Compositional UI

The whole vision of micro-service architecture is to allow applications to be built connecting different so called “back end” services.

Sometimes, applications needs to be used directly by humans,  and then the goal of compositional application development is to enable different “back ends” to be “wrapped” by a nice UI.

Here is described a simple 5 step procedure to develop and deploy a UI5 for a POST service. Particularly useful for developers that so far had only been involved or focused on back-end services and need to rapidly demonstrate the capability avoiding POSTMAN or non user friendly interfaces.

1. yo easy-ui5 :

Create your first OpenUI5 App within a few seconds!

As soon as I deployed my first “recommendation engine” on CF (see … for some technical details) was clear that using POSTMAN or CURL

curl --request POST --data '{"myinput":"this is the input that I would like to analyze"}' 
https://mybackend.cfapps.sap.hana.ondemand.com/submit.cgi 

was not going to be easy to demonstrate the “intelligence” of the engine, and that a UI was needed. What a pain: I never implemented using UI5 ! Well, no pain – no gain : I accepted the challenge end embarked in learning UI5.

Luckily, there is a huge amount of materials available online to learn UI5;

unfortunately there is a huge amount of materials available online to learn UI5!

Quite desperate on how to climb the mountain of knowledge ahead of me, I trusted Marius (I)Obert statement “Create your first OpenUI5 App within a few seconds!”  and got my first UI5 in place indeed in few seconds !

npm install -g yo generator-easy-ui5
yo easy-ui5
..answer few questions..
cf login
npm run deploy:cf

And that’s it ! my cf first UI on CF is up and running ! Incredible the amount of work that the second commandline does: the UI5 node.js framework is downloaded and properly installed, a skeleton (but running) application is created and adapted to the environment you set, and is also automatically deployed using the DevOps friendly  SAP MultiApps framework. Amazing.

2. add the Form

At this point starts the real work: add your own “form”. In good old HTML days, this simply consisted in

<FORM 
  ACTION="submit.cgi" 
  METHOD="POST">
  <TEXTAREA ID="myinput">
this is the input that I would like to analyse
  </TEXTAREA>
  <ACTION TYPE="SUBMIT"/>
</FORM>

and typically resulted in an empty field with a button, and when clicking the button the content was then POSTed to the submit.cgi that would eventually do something with it and return something to the user.

All I wanted to achieve was the same, however with theUI5 framework that easy-ui5 provided! Indeed that is easily achieved by editing

webapp/view/MainView.view.xml

and inserting within the tags

<content></content>

the following lines:

<form:SimpleForm editable="true">
 <Label text="Input your text"/> 
 <TextArea id="inputValue" value="{/inputValue}" /> 
 <Label text="click on the button to get a result"/>
 <Button text="Tell Me" press="onPress" />
 <Label text="Result" /> 
 <Text id ="result" text=" " />
</form:SimpleForm>

Please also ensure that the namespace “form” is appropriately defined.

Quite easy ! At this point however, what is the equivalent of …  submit.cgi ?

3. modify mta.yaml

yo easy-ui5 generator creates a mta.yaml that requires a destination managed-service service.

modules:
 - name: mytest
   type: nodejs
   path: dist
   parameters:
      disk-quota: 512M
      memory: 512M
   requires:
    - name: dest_mytest

resources:
 - name: dest_mytest
   parameters:
      service-plan: lite
      service: destination
   type: org.cloudfoundry.managed-service

This must to modified according:

modules:
 - name: mytest
   type: nodejs
   path: dist
   parameters:
      disk-quota: 512M
      memory: 512M
   requires:
    - name: dest_mytest
      group: destinations
      properties:
         name: dest_mytest
         url: '~{url}'

resources:
 - name: dest_mytest
   properties:
      url: https://mybackend.cfapps.sap.hana.ondemand.com/

4. modify xs-app.json

yo easy-ui5 generator creates a xs-app.json that specifies how to handle the default route.

 "routes": [
    {
      "source": "^/(.*)$",
      "target": "$1",
      "localDir": "."
    }
  ]

 

In our application we want the UI to be delivered from the starting page, however the POST be done against mybackend. In order to achieve this, we will ensure that in the form the posting be done against  /destinations/submit.cgi and will be using the /destinations/ part of the path as “signal” for chosing a different route.

This is done by simply prepending the following content to the route in xs-app.json:

 

"routes": [
   {
    "source":"/destinations",
    "target": "/",
    "destination":"dest_mytest",
    "httpMethods": ["POST"]
    },
    {
      "source": "^/(.*)$",
      "target": "$1",
      "localDir": "."
    }
  ]

Be very careful: if you invert the order (e.g. if you leave the original as it is and append to it the source …httpMethods lines) then your endpoint is never going to be reached and you will get a 405 error.

5. controller/MainView.controller.js

If at this point we would deploy the application, it will look nice but would be doing nothing cine we need to instruct it what to do when a user clicks the button. This “wiring” is done in the controller.

As you well know, UI5 allows to use the Model View Controller object oriented pattern, and in our application so far we mainly used the View (the form) but not yet the Controller for the actions. This is what needs to be done now.

yo easy-ui5 generator creates a controller/MainView.controller.js however it needs to be filled with content.

sap.ui.define([
  "sap/ui/core/mvc/Controller"
], function(Controller) {
  "use strict";

  return Controller.extend("com.myorg.mytest.controller.MainView", {});
});

and here is what you need to have  …

sap.ui.define([
	"sap/ui/core/mvc/Controller",
	'sap/ui/model/json/JSONModel
], function(Controller, JSONModel) {
	"use strict";
	return Controller.extend("com.myorg.mytest.controller.MainView", {
		onInit: function() {
			var oModel = new JSONModel({
				data: {}
			});
			this.getView().setModel(oModel);
		},
		onPress: function(event) {
			var sValue = this.byId("inputValue").getValue();
			var aData = $.ajax({
				url: '/destinations/submit.cgi',
				dataType: 'json',
				type: 'post',
				async: false,
				data: sValue
				}),
				processData: false,
				success: function(data, textStatus, jQxhr) {
					var oModel = new JSONModel({
						data: {}
					});
					oModel.setData(data);
				}
			});
			this.byId("result").setText(aData.responseText);
		}
	});
});

As you can notice, now when the user enters some text in the text area and then pushes the button, then the content is sent to /destination/submit.cgi that is interpreted by the router as to be forwarded to the dest_mytest, the result is then going to be returned to the user by setting the element with id “result” accordingly.

Conclusions

npm run deploy:cf

That’s it ! if you simply now repeat the above command, the whole pipeline will be executed, and your UI5 will be up and running and serving the customers with a human understandable endpoint.

If for some reasons you get strange error message such as “Unsupported resource type “” for platform type “CLOUD-FOUNDRY” then you might want to

java -jar mta_archive_builder-1.1.19.jar --build=CF build
cf deploy my.mtar

I really hope this material will save you a lot of time, specially the first time you will have to create a simple UI for any REST service.

 

Source code
https://github.com/lucatoldo/5-simple-steps-to-wrap-a-rest-service-with-a-nice-ui5.git

 

 

10 Comments
You must be Logged on to comment or reply to a post.
  • Doesn’t that also show the downsides of SCP? From a pure logical point of view, neither step 3 (mta.yaml), step 4 (xs-app.json) nor command line for deployment is needed. The only things that are required are uploading the view, html and controller files to your account’s webspace.

    If I use any other cloud development solution I upload these files to their webserver and all works.

    Run simple!

    • Dear Werner,

      thank you for the time you spent in reading my documentation and thinking about it.

      I should have added that the above approach is required in those cases where the “back end” is restricting the usage by same-origin security policy.

      In other words, Cross Origin Resource-Sharing (https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) is what would be involved if one would follow the approach you suggested.

       

      • Agree, but your response reads like “and therefore these additional steps are needed and they are the only solution”.

        On the contrary, it does help accessing other SCP urls only. But often your restful services is outside, in another domain. Doesn’t it?

        Anyway. Thinking about it, I lacked the information why these extra steps are needed and that triggered my response. Might have been the wrong place, sorry for that.

        • Thankyou Werner for your valuable comments.

          Yes, you are perfectly right the approach I reported targets accessing other microservices from the SCP.

          For accessing microservices outside SCP I have not investigated how to proceed, however it sounds an interesting extension of that work.

          Thankyou for providing that use case.

  • Hi Luca,

    This is a nice introduction.  I use RESTful services where I can with SAPUI5, but I find that there’s a strong baked-in dependency on OData constructs in UI5 controls.  For example, Filtering, Sorting, and Search capabilities in UI5 Tables all basically map back directly to equivalent OData URI constructs.

    This puts real limits on the practicality of swapping-in REST for OData — at least for the sorts of applications I’ve been exposed to.

    Your thoughts?

    Riley

    • Hi Riley,

      thank you for your comments.

      I was not suggesting of swapping-in REST for OData.

      A comparison between OData and REST can be seen for example at this address.

      In my case I had a plain REST service as backend, that I could not modify to handle OData.

      Thankyou