Skip to Content
Personal Insights

Integrate an UI5 component into another in the Cloud Foundry using MTA archive and SAP Web IDE

Hello every body,

In this blog post, i will try to demonstrate the component reuse in the cloud foundry environment using the MTA archive and deploying it into the SAP Cloud Platform (SCP) . This will be done in three different ways :

  1. Deploying a childUIApp and parentUIApp each one as a module in a different MTA archive and using destination service.
  2. Deploying 2 UI module for both childUIApp and parentUIApp in the same MTA archive without using destination service.
  3. Deploying a childUIApp and parentUIApp in two different MTA archive without using destination service.

If you work in the neo envirement you can check this great blog Demystifying the art of component reuse in SAPUI5


I) Deploying a childUIApp and parentUIApp each one as a module in a different MTA archive and using destination service.

 

1 – We will create a Multi-Target application in the SAP Web IDE.

ctrl+alt+shift+o (Project from template) -> choose cloudFoundry Envirement -> Multi-Target application -> projectName ‘FirstMTA’ -> Finish

2 – We will create our first module named MyChildApp

Right-click on our MTA project -> New -> HTML5 module -> choose SAPUI5 Application -> Enter moduleName and Namespace like in the image bellow -> rename the view ‘ChildView’.

3 – We will remove the requirements and resources from the mta.yaml, then we will disable authentification check in the xs-app.json (replace route by none).

4 – We will do the same by creating a MTA project FirstParentMTA, then creating a HTML5 module named : MyParentApp and the nameSpace : sap.cf.parentComponent and rename the view ParentView. We will change the authentification check in the xs-app.json to none like with the child.

5 – Build both MTA and deploy each module to CloudFoundry in your preferred Space (you can deploy each module into different space) to test that for this state all work fine.

 

6 – We will add our ComponentContainer in the parentView to display our child app.

<mvc:View controllerName="sap.cf.parentComponent.MyParentApp.controller.ParentView" xmlns:mvc="sap.ui.core.mvc" displayBlock="true"
	xmlns="sap.m" xmlns:core="sap.ui.core">
	<Shell id="shell">
		<App id="app">
			<pages>
				<Page id="page" title="{i18n>title}">
					<content>
						
						<core:ComponentContainer width="100%" id="myChildContainer"/>
						
					</content>
				</Page>
			</pages>
		</App>
	</Shell>
</mvc:View>

7 – We have to add the resourceroots for our child application in the index.html of our MyParentApp by giving the namespace.name : path to my child app.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>MyParentApp</title>
		<script id="sap-ui-bootstrap"
			src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
			data-sap-ui-theme="sap_belize"
			data-sap-ui-resourceroots='{"sap.cf.parentComponent.MyParentApp": "./",
			"sap.cf.childComponent.MyChildApp": "../MyChildApp/MyChildApp/"
			}'
			data-sap-ui-compatVersion="edge"
			data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
			data-sap-ui-async="true"
			data-sap-ui-frameOptions="trusted">
		</script>
	</head>
	<body class="sapUiBody">
		<div data-sap-ui-component data-name="sap.cf.parentComponent.MyParentApp" data-id="container" data-settings='{"id" : "MyParentApp"}'></div>
	</body>
</html>

8 – we will load our childComponent in the ParentView.Controller.js of our MyParentApp.

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

	return Controller.extend("sap.cf.parentComponent.MyParentApp.controller.ParentView", {
		onInit: function () {

			// get the child container
			var oChildContainer = this.byId("myChildContainer");
			this.getOwnerComponent().runAsOwner(function () {
				sap.ui.component({
					name: "sap.cf.childComponent.MyChildApp", //Our child component
					id: "MyChildComponent",
					manifestFirst: true,
					async: true
				}).then(function (component) {
					// set the component when it is successfully loaded
					oChildContainer.setComponent(component);
				}.bind(this));
			}.bind(this));

		}
	});
});

9 – in the manifest.json (within dependencies) of our MyParentApp we will add the lazy load of the childComponent.

"sap.ui5": {
  ...

   "dependencies": {
...
          "components": {
				"sap.cf.childComponent.MyChildApp": {
					"lazy": true
				}
			} //End components
       }//End dependencies

}// End sap.ui5"

10 – Now, in the xs-app.json, we have to tell the parentApp when and where to find the childApp. For that we will use the destination service added in the mta.yaml of our parentApp.

{
  "welcomeFile": "/MyParentApp/index.html",
  "authenticationMethod": "none",
  "logout": {
    "logoutEndpoint": "/do/logout"
  },
  "routes": [
    {
      "source": "^/MyParentApp/(.*)$",
      "target": "$1",
      "localDir": "webapp"
    }, {
		"source": "^/MyChildApp/(.*)",
		"target": "$1",
		"destination": "dest_FirstParentMTA"
	}
  ]
}

11 – Not yet. We have to define the destination by adding the URL to our childApp.

Go to the SubAccount -> Connectivity -> Destinations. Add a new Destination.

12 – Now we can build our FirstParentMTA and deploy the MTA archive.

II) Deploying 2 UI module for both childUIApp and parentUIApp in the same MTA archive without using destination service.

For this second demonstration we will use the FirstMTA where we have already our child Module (MyChildApp) and we will create a second Module (MyParentApp2).

1 – After that we will copy the same code from MyParentApp without the destination declaration in the mta.yaml.

2 – In the mta.yaml we will add a provider in which we will add a property that store theURL of our child module (No need to add it manually or hard-coded). In the parent we will consume this URL and create a destination (myChildDestination).

ID: FirstMTA
_schema-version: '2.1'
version: 0.0.1

modules:
 - name: MyChildApp
   type: html5
   path: MyChildApp
   provides:
      - name: provideChildUI
        properties:
          service_url: '${default-url}'
   parameters:
      disk-quota: 256M
      memory: 256M
   build-parameters:
      builder: grunt

 - name: MyParentApp2
   type: html5
   path: MyParentApp2
   parameters:
      disk-quota: 200M
      memory: 200M
   build-parameters:
      builder: grunt
   requires:
      - name: provideChildUI
        group: destinations
        properties:
          name: myChildDestination
          url: '~{service_url}'
          forwardAuthToken: false

3 – Now we have to tell our appRouter in the xs-app.json of the MyParentApp2 to take the destination into consideration.

{
  "welcomeFile": "/MyParentApp2/index.html",
  "authenticationMethod": "none",
  "logout": {
    "logoutEndpoint": "/do/logout"
  },
  "routes": [
    {
      "source": "^/MyParentApp2/(.*)$",
      "target": "$1",
      "localDir": "webapp"
    }, {
		"source": "^/MyChildApp/(.*)",
		"target": "$1",
		"destination": "myChildDestination"
	}
  ]
}

4 – Now we build our FirstMTA and we deploy to cloudFoundry.

III) Deploying a childUIApp and parentUIApp in two different MTA archive without using destination service.

Now we will change mta.yaml of the FirstParentMTA (used in the first part) by replacing the destination by a MTA dependency.

1 – in the mta.yml remove the destination (dest_FirstParentMTA) and add the MTA dependency

ID: FirstParentMTA
_schema-version: '2.1'
version: 0.0.1

modules:
 - name: MyParentApp
   type: html5
   path: MyParentApp
   parameters:
      disk-quota: 200M
      memory: 200M
   build-parameters:
      builder: grunt
      
   requires:
      - name: provideChildUI
        group: destinations
        properties:
          name: myChildDestination
          url: '~{service_url}'
          forwardAuthToken: false
resources: 
  - name: provideChildUI 
    type: mta-provided 
    parameters:
      mta-id: FirstMTA
      mta-provides-dependency: provideChildUI
      mta-version: ">=0.0.1" 
      
      
      
#   requires:
#    - name: uaa_FirstParentMTA
#   - name: dest_FirstParentMTA

#resources:
# - name: uaa_FirstParentMTA
#   parameters:
#      path: ./xs-security.json
#      service-plan: application
#      service: xsuaa
#   type: org.cloudfoundry.managed-service

# - name: dest_FirstParentMTA
#   parameters:
#      service-plan: lite
#      service: destination
#   type: org.cloudfoundry.managed-service

As you can see, the requires are similar as when we use a single MTA project to contain our 2 application. But now, the parent need to know from where he will consume the provided URL.

This is why we will give a resources with some parameters which are :

the mta-id : FirstMTA (which is also the name of the MTA that contain our childModule)

mta-provides-dependency : provideChildUI (The name used in the provides of our MyChildApp)

2 – Something that we mustn’t forget, is to let our provided URL public in the childModule. Because the parent will search first the child MTA and when he find it, he will search the provideChildUI resource.

3 – in the xs-app.json change the destination from dest_FirstParentMTA to myChildDestination

{
  "welcomeFile": "/MyParentApp/index.html",
  "authenticationMethod": "none",
  "logout": {
    "logoutEndpoint": "/do/logout"
  },
  "routes": [
    {
      "source": "^/MyParentApp/(.*)$",
      "target": "$1",
      "localDir": "webapp"
    }, {
		"source": "^/MyChildApp/(.*)",
		"target": "$1",
		"destination": "myChildDestination"
	}
  ]
}

4 – Now like every time Build, Deploy and Test.

We saw how it is possible to integrate and reuse an ui5 Application into another on the cloud foundry environment.

The Child and the Parent application can exchange data using EventBus.

Regards,

Ilyes Mansour

Be the first to leave a comment
You must be Logged on to comment or reply to a post.