Skip to Content

This tutorial will show how to create a SAPUI5 frontend based on the services of the earlier blog posts. In particular, it will show how to:

  • Create a new SAPUI5 project using the template
  • Use SAPUI5 controls to create the view
  • Consume the REST service
  • Deploy the application to Cloud Foundry
    • Using a monolithic approach
    • Using a micro service approach

The resulting application will show a list of cost center from the ERP that is connected to the backend.

Note: This post is part of a series. For a complete overview visit the SAP S/4HANA Cloud SDK Overview.

Create a new SAPUI5 Project Using the Template

The easiest way to start developing a SAPUI5 application is to utilize the project templates of the WebIDE (https://www.sap.com/developer/topics/sap-webide.html). To access it, you need to create an account on SAP Cloud Platform as described in Step 2 of the SAP S/4HANA Cloud SDK Overview. After creating an account, you can activate and go to the WebIDE from the services tab. To create a new template-based project, select File > New > Project from Template and select SAPUI5 Application and create a new project using the wizard. For the purposes of the tutorial, all the default settings are fine. In the following code snippets, we will assume that the project was named blog-tutorial. If you copy the code and have used a different project name, make sure to replace blog-tutorial with the project name you have chosen during the wizard

The project will automatically have the following structure:

The webapp folder contains the actual application which follows the Model View Controller pattern and therefore is split into the View1.view.xml, models.js, and View1.controller.js. Also, there is a separate style.css file, which can be used to customize the look of your app (by default all controls will be Fiori compliant). Finally, there is the i18n.properties file. I18n stands for internationalization and the file itself will serve as a base for translation of your app. For the sake of simplicity, we will not use i18n to define the UI texts in this tutorial. You can read more about it in the SAPUI5 documentation.

The other files contain configuration or are responsible for loading and initializing SAPUI5. Before touching the actual app, it is recommended to update the index.html to fetch the SAPUI5 sources from the official CDN. To do that, you need to change it in the script tag in line 11 as follows:

<script id="sap-ui-bootstrap"
	src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
	data-sap-ui-libs="sap.m"
	data-sap-ui-theme="sap_belize"
	data-sap-ui-compatVersion="edge"
	data-sap-ui-resourceroots='{"blog-tutorial": ""}'>
</script>

You can use this link to the latest stable version of SAPUI5 for the tutorial or for testing purposes, but avoid it for productive use. In an actual app, you always should specify an SAPUI5 version explicitly.

How to use SAPUI5 Controls to Create the View

When opening the view, the WebIDE gives 2 options, the layout editor, and the code editor. The code editor is the more powerful tool which gives you the ability to change your code directly, while the layout editor shows you a visual editor, providing an approximated preview of your changes, and uses drag and drop of a control catalog to edit your view. You can use either editor to follow this tutorial, but we will show the actual code as you would see in the code editor since it is easier to compare and avoid mistakes this way.

To get an overview of what controls SAPUI5 provides, you can use the SAPUI5 Explored website to see a searchable list with interactive examples.

For our app, we want to display a list of cost centers, so a quick search in Explored suggests that we should use sap.m.List control. Controls are organized in libraries and in the beginning, you will mostly use controls from sap.m and sap.ui.core. These controls are by default responsive and will adjust to fit the device that displays the website.

When you open the View1.view.xml, it will already contain the basic structure needed for a SAPUI5 application. In the following code, you only need to copy the List tag and the StandardListItem and put it between the content tag in your own View1.view.xml.

This will already create the list we want to display, but of course, there is no data loaded yet. This will be explained in the next part.

<mvc:View xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="blog-tutorial.controller.View1" displayBlock="true">
	<App>
		<pages>
			<Page title="Cost Center Explorer">
				<content>
 
					<!-- Add this between the content tags -->
			        <List headerText="Cost Centers"
						items="{costCenter>/}" >
						<StandardListItem
							title="{costCenter>costCenterDescription}"
							description="{costCenter>costCenterID}" />
					</List>
 
				</content>
			</Page>
		</pages>
	</App>
</mvc:View>

Consuming the REST Service

In the previous steps of this tutorial series, we already created a REST Service that requests and returns a list of cost centers from SAP S/4HANA. To call this service and connect its data to our list, we use jQuery and SAPUI5’s JSONModel.

This business logic will be implemented as part of the controller. As with the view, the template already provides some basic structure.

To add the functionality, we need to use jQuery.get() to retrieve the data. Because of the asynchronous nature of the call, we need to use the done callback to put the data in a JSONModel and connect it with the view. Additionally, we need to include the JSONModel by adding it as the first parameter of the sap.ui.define() function. You can also add jQuery there, but SAPUI5 already guarantees that jQuery is included everywhere.

sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/ui/model/json/JSONModel"
], function(Controller, JSONModel) {
	"use strict";
	return Controller.extend("blog-tutorial.controller.View1", {
		onInit: function () {
			var view = this.getView();
			
			jQuery.get("/costcenters")
				.done(function (data) {
					var model = new JSONModel(data);
					view.setModel(model, "costCenter");
				});
		}
	});
});​

Now, this simple app is already completed. To try it out, we can use the WebIDE’s deployment or follow the rest of the tutorial to deploy the app on Cloud Foundry. To use the WebIDE deployment, just right-click the project folder on the left and select Run > Run As > Web Application. If we use this method, it will not be connected to our REST Service as they are in different environments that can’t communicate. Instead of looking at an empty list, we can replace the .done() callback with the code below which uses dummy data so you can verify the functionality of the app without a backend. Just make sure to revert this change once you deploy on Cloud Foundry.

 

sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/ui/model/json/JSONModel"
], function(Controller, JSONModel) {
	"use strict";
	return Controller.extend("blog-tutorial.controller.View1", {
		onInit: function () {
			var view = this.getView();
			
			jQuery.get("/costcenters")
                .always(function () {
                    var data = [{
                        "id": "0010101101",
                        "description": "Financials (DE)"
                    }, {
                        "id": "0010101201",
                        "description": "Purch & Stores 1 (DE)"
                    }, {
                        "id": "0010101202",
                        "description": "Purch & Stores 2 (DE)"
                    }, {
                        "id": "0010101301",
                        "description": "Manufacturing 1 (DE)"
                    }, {
                        "id": "0010101302",
                        "description": "Manufacturing 2 (DE)"
                    }, {
                        "id": "0010101401",
                        "description": "QM (DE)"
                    }, {
                        "id": "0010101501",
                        "description": "R&D (DE)"
                    }, {
                        "id": "0010101601",
                        "description": "Marketing (DE)"
                    }, {
                        "id": "0010101602",
                        "description": "Sales (DE)"
                    }, {
                        "id": "0010101701",
                        "description": "Plant & Maintenance (DE)"
                    }, {
                        "id": "0010101750",
                        "description": "Build. & Maintenance (DE)"
                    }, {
                        "id": "0010101751",
                        "description": "HR Services-(DE)"
                    }];
                    var model = new JSONModel(data);
                    view.setModel(model, "costCenter");
                });
		}
	});
});

After you implemented these steps, the application should look like this:

Make sure to replace the .always() callback with .done()  from the previous snippet once you deploy on Cloud Foundry. Afterwards, download the project files by right-clicking the project and selecting Export. It will download a .zip archive, that can be easily extracted.

Deploy the Application to Cloud Foundry

Using the SAP Cloud Platform Cloud Foundry for your deployment gives several benefits. One of these benefits is the flexibility to structure the project as a monolith or split it into several micro services. In previous blog posts, we already showed how to develop and deploy an API service to Cloud Foundry as well as Neo. If you have not setup the backend yet, you can follow the other tutorials in this series which are linked in the SAP S/4HANA Cloud SDK Overview.

In the following, we want to explore how to deploy a full web application that uses data provided by our service. We will show both the monolithic approach as well as a more micro service oriented architecture.

Deploy the Application to Cloud Foundry Using a Simple Monolith Approach

Prerequisites

Deploying the whole application including backend and frontend in a monolithic approach can be very easy. In order to have a better understanding of our final goal look at the picture:

We utilize the same server to serve both the service URL’s as well as the frontend files. To do this we extract the downloaded archive and copy theses files to the webapps folder of the backend.

cd <PATH_TO_DOWNLOADED_ZIP>
unzip ui5-webapp.zip
cp -a ui5-webapp/webapp/* /path/to/java/application/application/src/main/webapp/

To deploy the application to CloudFoundry, a proper manifest.yml is neededIf you haven’t added one in the previous tutorials, you can use the following example. Just don’t forget to replace the ERP configuration placeholders.

---
applications:

- name: firstapp
  memory: 512M
  host: firstapp-d065331
  path: application/target/firstapp-application.war
  buildpack: sap_java_buildpack
  env:
    TARGET_RUNTIME: tomee

Finally, we build the application and deploy to CloudFoundry:

mvn clean install
cf push --no-start
cf set-env firstapp destinations: '[{name: "ErpQueryEndpoint", url: "https://***********.hana.ondemand.com", username: "******", password: "********"}]'
cd start firstapp

If your deployment was successful, the Cloud Foundry CLI will show you information about the deployment, that looks like the following snippet.

requested state: started
instances: 1/1
usage: 512M x 1 instances
urls: firstapp-USERNAME.cfapps.sap.hana.ondemand.com
last uploaded: Fri Jul 28 12:00:36 UTC 2017
stack: cflinuxfs2
buildpack: sap_java_buildpack

To verify that the deployment was successful, you can enter the URL in your browser and see the application showing the list of cost centers.

This approach allows for a quick initial deployment and a simple deployment process. For small applications like this cost center explorer, this approach will be preferable, but as the application grows and needs to scale it will get progressively harder and more expensive. Frontend and backend cannot be decoupled and scaled individually, also to make changes to either you need to deploy both which will result in more downtime unless you use blue green deployments.

Deploy the Application to Cloud Foundry Micro Service Approach

Prerequisites

We assume that you know what the Approuter is for and know the basics of how to configure it.

The micro service approach decouples the separate components and allows scaling them individually. To do this separation, we need to run the frontend in its own container.  We deploy the frontend application completely separate in its own container. For that, we use the staticfile_buildpack which is provided by default in Cloud Foundry. In the following, we will show how this can be done.

As in the monolithic approach, here is a picture of our final setup:

As the frontend will be its own service now, it should be in a separate folder from the backend (instead of being part of the backend as with the monolithic approach). Once you moved the code to a separate folder, you need to add a manifest.yml as it will need a different Cloud Foundry configuration than the backend now.

Like in the monolitic step we start with unpacking the downloaded zip.

cd <PATH_TO_DOWNLOADED_ZIP>
unzip ui5-webapp.zip
cd ~
mkdir cost-center-frontend

cd cost-center-frontend
cp -a <PATH_TO_DOWNLOADED_ZIP>ui5-webapp/webapp/* .

Now create here a new manifest.yml with the following content:

---
applications:
- name: cost-center-frontend
  memory: 64M
  host: cost-center-frontend-USERNAME
  buildpack: staticfile_buildpack

Push the frontend to CloudFoundry:

cf push

When you point your browser to cost-center-frontend-USERNAME.cfapps.sap.hana.ondemand.com you should see the application running but without data. To connect the frontend to our previous deployed backend we need a proper configured approuter.

Install the AppRouter like in step 7 or just reuse your existing installation.

As for all application that you want to deploy on CloudFoundry, we need a manifest file. You also need to add two routes to the AppRouter. The achieve this, adjust the manifest.yml and xs-app.json of the AppRouter. Make sure that the destination names and URLs match your own deployment. The name for the destinations is arbitrary. You can choose them on your own. We will use them in the next step to point our wished URL to the actual one.

---
applications:
- name: approuter
  host: approuter-p1942765239trial
  memory: 128M
  path: approuter
  buildpack: nodejs_buildpack
  env:
    destinations: '[
			{
				"name":"cost-center-api",
				"url" :"firstapp.cfapps.sap.hana.ondemand.com/"
			}, {
				"name": "cost-center-frontend",
				"url": "cost-center-frontend-USERNAME.cfapps.sap.hana.ondemand.com/"
			}]'
  services:
    - myuaa

Within the xs-app.json we configure which URL path shall be handled and resolves to what destination. For instance: url.to.router/costcenters resolves to  url.in.CF/costcenters. If you want to know more on that go back to step 7 and read there.

{ "welcomeFile": "index.html",
  "routes": [{
      "source": "^/costcenters",
      "destination": "cost-center-api"
    }, {
      "source": "/",
      "destination": "ui5-tutorial"
    }]
}

Finally, just run the Cloud Foundry CLI to deploy the AppRouter, the backend, and the frontend.

cd approuter/
cf push 
cd ../ui5-tutorial
cf push

After you deployed all 3 components, the application should be available just like before.

Since we didn’t touch the deployed backend from the monolithic step it should run right away. You can safely remove the frontend code from the webapps folder in the backend and redeploy.

To summarize, the micro service approach allows you to independently develop, deploy and scale the applications but also introduced operational complexity. A monolithic approach has lower operational complexity and is faster to setup initially but can run into scaling issues later. To choose the right way for you, you will have to evaluate the size and scope of your project and how the different approaches will help you achieve your goal.

To report this post you need to login first.

5 Comments

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

  1. Tri Le

    Hi Frank,

    I’m confused with the section Consuming the REST Service and not sure where you set destination to consume the service like we usually develop SAPUI5 apps.

    Could you please clarify that?

    Thanks

    Tri

    (0) 
      1. Henning Heitkoetter

        Hello Tri,

        you can do everything inside the app that you can do in SAPUI5, as it is a standard UI5 app. In this blog post, we focus on the integration with the service developed as part of the tutorial, which is a plain REST service.

        This could also be an OData service – there is also an OData provisioning framework for SAP Cloud Platform that you can integrate with the SAP S/4HANA Cloud SDK.

        Best regards,

        Henning

        (1) 
  2. Sankeerth Narsina

    Hi Frank,

    Thanks for posting such great blog. I am trying to get some hands-on experience with this concept. I implemented the steps as you mentioned in the blog when I run the application, It displays the blank rows as below screenshot. Can you please tell me what would be the reason for this?

     

     

    Thanks,

    Sankeerth

    (0) 

Leave a Reply