Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
*** This blog is OBSOLETE! ***

If you are still subscribed to Neo please refer to this blog post https://blogs.sap.com/2020/01/24/cross-mta-dependencies.-custom-ui5-library-reference-example./

Multiple Apps with a Shared Reuse Library on BAS and CF, follow this blog post for more details https://blogs.sap.com/2022/02/08/designing-ui5-apps-for-sap-launchpad-service-part-2/

 

****************************************************************************************************************

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
4 Comments