At first, I will introduce the components of that long title. These components are also parts of the solution I will be describing here.
Lets take it from the end.
Cloud Foundry
Cloud Foundry is one of two available environments in SAP Cloud Platform. And I have to say, that it is newer and preferable one. New customers should be onboarded automatically to CF environment - even when NEO should still be supported - according to the
blog post. Most of new products and features are delivered on this environment, but on the other hand - not everything which is available on NEO are supported or available on CF.
It is important to know, that Cloud Foundry is based on multi container service architecture. I won`t dive deeper, but it just means, that whole application is built from different services tied together like lego. And the description how to put all the pieces together is part of MTAR application.
Multi Target Application (MTA)
Multi target application repository or in short MTAR is an way how to develop applications in decentralized, container based environment of Cloud Foundry. MTAR application consists of applications (or modules) and services (or resources) and (optionally) from other components like parameters etc.
The heart of every MTA is configuration stored in a file
mta.yaml. This configuration describes how the whole application is build and deployed to the CF. As previous sentence implied - there is two step procedure how to get application running.
- Build process - goes through the mta.yaml, and for the every application (module) runs (according to module type) its building procedure. The result is file (archive) with extension mtar, which contains all necessary information and sources which are needed to deploy our MTA. This step is performed by MTA build tool
- Deploy process - is how the application gets to the CF environment. It is performed by CF CLI tool.
Business Application Studio
Business Application Studio is the new standard for developing business applications on SAP Cloud Platform Cloud Foundry. It is successor and evolution of WebIDE Full Stack. As WebIDE Full Stack was based on a open source project
Eclipse CHE, the new Business App Studio is based on new
Eclipse Theia. The biggest difference is, that WebIDE is hosted only on NEO environment and therefore you have to prepare destinations and connection in order to develop on CF environment, new Business Application Studio is hosted as an individual isolated container hosted on CF environment. You can also create (on trial account) two development spaces, but only one can run at a time.
And why multiple spaces?
Because you can add different extension modules in development space when you create one. One dev space can be dedicated to work with CAPM and Fiori and the other one to workflows (and Fiori too). At least I got that kinds.
It is also important to notice, that Business App Studio has UI almost same as famous Visual Studio Code from Microsoft. And what I like most - you have access to the linux terminal there.
You can find more information in official
help pages and
here is also nice comparison of WebIDE vs Business App Studio.
Only negative I have found on Business App Studio is its name - it is too long and as far as I know, nobody came with nice shortcut or nickname. Business Application Studio is not that sexy as WebIDE. Or do you know some better way how to refer it?
Prerequisites
I assume, that you have at least that requirements:
This post will not teach you how to work with Business App Studio or why do we add the things to the project. There are really good tutorials on that topics already done - like this one on
SAPUI5 App with Business App Studio or
Creating MTA or
Start with workflow.
What I WILL show you, is how to use all that knowledge and build/deploy MTA application with workflow module and custom UI using Business App Studio.
Get our feet wet...
At first we need to create new workspace. As we are in Business App Studio, we will use terminal and CLI.
cd /home/user/projects
after that, create basic MTA scaffolding using yeoman.
yo basic-multitarget-application
Note: yeoman is web scaffolding tool. It is preinstalled (including basic UI5 and MTA generators) in App studio and it uses so called generators to create scaffolding of different projects. In this case we used generator named basic-multitarget-application to create - surprise... empty MTA application.
Fill the attributes of project. In this case it is only name of the project.
Name: WF-custom-ui
Open new project as a workspace - in a menu
File / Open Workspace and there choose your newly created project.
It is really just basic MTA application - just two files:
If you look into mta.yaml, you can see, that even there it is just bare minimum.
_schema-version: "3.2"
ID: WF-custom-ui
version: 0.0.1
Now it time to add other modules of our application. At first, add workflow module.
yo @workflow/workflow-module
and fill required attributes.
Name: workflow
Workflow name: workflow_service
Workflow description: Workflow tutorial for custom UI
Overwrite mta.yaml: y
Note: This generator can create whole MTA project, this is why it asks for overwrite mta.yaml. But I wanted to show you also how to create empty MTA project.
Now several things happened. Workflow editor has opened and you can see graphical representation of workflow process. And when you take a look at project folder, you can see, that a lot of files was added.
If you look into mta.yaml now, you can see, that one module named workflow was added and also resource for that module, named workflow_mta appeared.
_schema-version: "3.2"
ID: WF-custom-ui
version: 0.0.1
modules:
- name: workflow
type: com.sap.application.content
path: workflow
requires:
- name: workflow_mta
parameters:
content-target: true
resources:
- name: workflow_mta
parameters:
service-plan: lite
service: workflow
type: org.cloudfoundry.managed-service
Note: This will create new managed service for workflow. If you want to use your existing service, change the name of service to your name and type to org.cloudfoundry.existing.service. Also don`t forget to change service-plan to lite if you are on trial account.
Next step is to add html5 module, which will contain custom UI for user task. Also very easy done using yeoman.
yo fiori-module
and fill attributes
Module name: customUI
Template: SAPUI5 Application
Application: Standalone Approuter
Authentication: yes
Namespace: ui.tutorial
Karma tests: no
View name: Main
Data service: No
Note: you can explore other options like other templates, adding data service or managed application. These options are chosen to keep tutorial simple. If you want to know more about other options, don`t hesitate to ask in comments.
After that last option, a lot of things happened again. Generator started to download all necessary npm packages to create SAPUI5 application, a lot of rows was added to the mta.yaml and two new directories appeared in the project.
Let`s look to the mta.yaml again.
_schema-version: "3.2"
ID: WF-custom-ui
version: 0.0.1
modules:
- name: workflow
type: com.sap.application.content
path: workflow
requires:
- name: workflow_mta
parameters:
content-target: true
- name: wf-custom-ui-approuter
type: approuter.nodejs
path: wf-custom-ui-approuter
requires:
- name: WF-custom-ui_html_repo_runtime
- name: uaa_WF-custom-ui
parameters:
disk-quota: 256M
memory: 256M
- name: WF-custom-ui_ui_deployer
type: com.sap.application.content
path: .
requires:
- name: WF-custom-ui_html_repo_host
parameters:
content-target: true
build-parameters:
build-result: resources
requires:
- artifacts:
- customUI-content.zip
name: customUI
target-path: resources/
- name: customUI
type: html5
path: customUI
build-parameters:
builder: custom
commands:
- npm run build
supported-platforms: []
resources:
- name: workflow_mta
type: org.cloudfoundry.managed-service
parameters:
service: workflow
service-plan: standard
- name: WF-custom-ui_html_repo_runtime
type: org.cloudfoundry.managed-service
parameters:
service: html5-apps-repo
service-plan: app-runtime
- name: WF-custom-ui_html_repo_host
type: org.cloudfoundry.managed-service
parameters:
service: html5-apps-repo
service-plan: app-host
- name: uaa_WF-custom-ui
type: org.cloudfoundry.managed-service
parameters:
path: ./xs-security.json
service: xsuaa
service-name: WF-custom-ui-xsuaa-service
service-plan: application
build-parameters:
before-all:
- builder: custom
commands:
- npm install
Three new modules appeared. It is interesting, because it was just two folders added. If you look better, you will see, that that third module is module for UI deployer. This module is interesting by itself and I will return to it later. But now lets look to the HTML5 module.
- name: customUI
type: html5
path: customUI
build-parameters:
builder: custom
commands:
- npm run build
supported-platforms: []
Despite the fact, that we just created that module almost without any effort, that is nothing special here. path
customUI corresponds with newly created directory and custom builder will run command
npm run build on a build time.
Let`s take a look also on
./customUI/package.json file, which contains implementation of that build command.
{
"name": "customui",
"version": "0.0.1",
"devDependencies": {
"@sapui5/ts-types": "1.71.x",
"@ui5/cli": "2.2.6",
"@sap/ui5-builder-webide-extension": "1.0.x",
"bestzip": "2.1.4",
"rimraf": "3.0.2"
},
"scripts": {
"build": "npm run clean && ui5 build --include-task=generateManifestBundle generateCachebusterInfo && npm run zip",
"zip": "cd dist && npx bestzip ../customUI-content.zip *",
"clean": "npx rimraf customUI-content.zip dist"
},
"ui5": {
"dependencies": [
"@sap/ui5-builder-webide-extension"
]
}
}
As you can see in a
scripts object, that
build command is in fact composed of 3 commands joined by
&& operator.
At first it will clear file
customUI-content.zip from the directory
dist. This will ensure, that all build process will create new and fresh content.
After that, UI5 build command is performed, which will generate the content of UI5 application itself. By default it will create that content into
dist directory, will create component-preload.js file and uglify its content - in order to optimize the performance of application. You can find more about UI5 builder
here.
And the final step will create zip archive out of the application. This is necessary, because new way of deploying HTML5 apps to
runtime repository of SCP CF. More on that in deployer part.
One more thing is necessary here in UI5 module. You must add routing to the workflow services so application could access workflow API.
Open
./customUI/xs-app.json file and add new route
{
"source": "^/bpmworkflowruntime/(.*)$",
"target": "/$1",
"service": "com.sap.bpm.workflow",
"endpoint": "workflow_rest_url",
"authenticationType": "xsuaa"
},
The whole file will look like this
{
"welcomeFile": "/index.html",
"authenticationMethod": "route",
"logout": {
"logoutEndpoint": "/do/logout"
},
"routes": [
{
"source": "^/bpmworkflowruntime/(.*)$",
"target": "/$1",
"service": "com.sap.bpm.workflow",
"endpoint": "workflow_rest_url",
"authenticationType": "xsuaa"
},
{
"source": "^(.*)$",
"target": "$1",
"service": "html5-apps-repo-rt",
"authenticationType": "xsuaa"
}
]
}
Second new module is application router.
- name: wf-custom-ui-approuter
type: approuter.nodejs
path: wf-custom-ui-approuter
requires:
- name: WF-custom-ui_html_repo_runtime
- name: uaa_WF-custom-ui
parameters:
disk-quota: 256M
memory: 256M
Also created without any big effort by the generator. Just standard application router so we have access point to our MTA.
Third new module is deployer.
- name: WF-custom-ui_ui_deployer
type: com.sap.application.content
path: .
requires:
- name: WF-custom-ui_html_repo_host
parameters:
content-target: true
build-parameters:
build-result: resources
requires:
- artifacts:
- customUI-content.zip
name: customUI
target-path: resources/
Lets look closely at this module. UI Deployer is module, which ensures, that your new UI5 (or Vue, React or event plaint HTML) will be deployed to the application runtime service. But in fact this application in not part of functionality of MTA itself and is more or less useless during the life of application.
The old way was to deploy nodeJS application which run during the deployment process, deploys the HTML5 app and after that it stopped itself. But anyway, this app was visible among deployed
Applications and took from limit of applications on that subaccount.
This new way ensures that no additional application is created and UI module is deployed during the deployment process by CF builder.
In order to function properly, you have to configure that module.
Type have to be set to
com.sap.application.content. This ensures, that proper builder is run.
And also you have to set the dependencies, because this module can deploy UI module only after that UI module was built.
And here comes
build-parameters.
- build-result parameter sets the directory from where application should be deployed
- requires directive tells, that this module depends on other modules. In this case, it depends on customUI module.
- target-path tells where to put zip archive with that UI module
- artifacts directive contains the list of ZIP archives which should be deployed for this UI module.
If you look a little bit higher on a customUI module - on its build command, you can see, that the last part of that build command was command to prepare ZIP archive out of application itself. It was necessary to prepare that ZIP because new deployer requires already archived resources.
You can find more about that new deployer in this very interesting video by Marius Obert from UI5Con
https://www.youtube.com/watch?v=emnl-y9btdU
The last module we need is launchpad module - so we can access Workflow tiles and My Inbox application. You can add that also with yeoman.
yo @sapflp/launchpad-module
Fill attributes
Module name: flp
Create launchpad site: yes
Let`s look at new launchpad module
- name: flp
type: com.sap.portal.content
path: flp
requires:
- name: portal_resources_WF-custom-ui
- name: WF-custom-ui_html_repo_host
- name: WF-custom-ui_ui_deployer
- name: uaa_WF-custom-ui
parameters:
buildpack: https://github.com/cloudfoundry/nodejs-buildpack/releases/download/v1.6.51/nodejs-buildpack-cflinuxf...
memory: 128M
stack: cflinuxfs3
As you can see, the new module has name flp, its path in a project targets to the directory
./flp and has standard launchpad parameters. But it is missing information in the requires area.
You need to declare workflow service as a resource, so the workflow tiles will get access to the workflow api.
Workflow resource in that MTA has name
workflow_mta so new definition of the module will be
- name: flp
type: com.sap.portal.content
path: flp
requires:
- name: portal_resources_WF-custom-ui
- name: WF-custom-ui_html_repo_host
- name: WF-custom-ui_ui_deployer
- name: uaa_WF-custom-ui
- name: workflow_mta
parameters:
buildpack: https://github.com/cloudfoundry/nodejs-buildpack/releases/download/v1.6.51/nodejs-buildpack-cflinuxf...
memory: 128M
stack: cflinuxfs3
Add same resource also to the approuter module
- name: wf-custom-ui-approuter
type: approuter.nodejs
path: wf-custom-ui-approuter
requires:
- name: WF-custom-ui_html_repo_runtime
- name: uaa_WF-custom-ui
- name: portal_resources_WF-custom-ui
- name: workflow_mta
parameters:
disk-quota: 256M
memory: 256M
We also need to add launchpad content - 3 tiles - My Inbox, Workflow definitions and Workflow Instances.
Open
./flp/portal-site/CommonDataModel.json and add there following content
{
"_version": "3.0.0",
"identification": {
"id": "f23bee19-fdd3-4690-8c99-3b5df3409b5e-1569475133992",
"entityType": "bundle"
},
"payload": {
"catalogs": [{
"_version": "3.0.0",
"identification": {
"id": "defaultCatalogId",
"title": "{{title}}",
"entityType": "catalog",
"i18n": "i18n/defaultCatalogId.properties"
},
"payload": {
"viz": []
}
}],
"groups": [{
"_version": "3.0.0",
"identification": {
"id": "defaultGroupId",
"title": "{{title}}",
"entityType": "group",
"i18n": "i18n/defaultGroupId.properties"
},
"payload": {
"viz": [{
"id": "com.sap.bpm.monitorworkflow-0-1569475771450",
"appId": "com.sap.bpm.monitorworkflow",
"vizId": "bpmworkflowmonitor-DisplayInstances"
}, {
"id": "com.sap.bpm.monitorworkflow-1-1569475771450",
"appId": "com.sap.bpm.monitorworkflow",
"vizId": "bpmworkflowmonitor-DisplayDefinitions"
}, {
"id": "cross.fnd.fiori.inbox-2-1569475771450",
"appId": "cross.fnd.fiori.inbox",
"vizId": "WorkflowTask-DisplayMyInbox"
}]
}
}],
"sites": [{
"_version": "3.0.0",
"identification": {
"id": "3a2a1ec5-91b5-4bb6-83ed-7716fe8d895d-1569475133992",
"entityType": "site",
"title": "SAP Fiori launchpad site on Cloud Foundry",
"description": "SAP Fiori launchpad site on Cloud Foundry, deployed from SAP Web IDE"
},
"payload": {
"config": {
"ushellConfig": {
"renderers": {
"fiori2": {
"componentData": {
"config": {
"applications": {
"Shell-home": {}
}
}
}
}
}
}
},
"groupsOrder": ["defaultGroupId"],
"sap.cloud.portal": {
"config": {
"theme.id": "sap_fiori_3",
"theme.active": ["sap_fiori_3", "sap_belize_hcb", "sap_belize_hcw"]
}
}
}
}]
}
}
Note: if you want edit CommonDataModel.json in text mode, you have to right click on that file and choose Open With.../Code Editor
The last thing which is missing, is to add usert task to the workflow and assign our custom UI to that task.
Open
./workflow/workflows/workflow_service.workflow
and select User Task
and add it to the workflow
Select UserTask1 and on the Details tab put some Subject - eg. My Custom Task. On that same tab put your email to the Users text field. You should put there email which is connected to actually used account. If you will use some other email - you wont see workitem in your My Inbox.
On the third tab named
User interface select type as
SAPUI5 Component. Next fill HTML5 App Name. As you probably know (if you took those tutorials I recommended), you have to find app id from
./customUI/webapp/manifest.json and from there
sap.app.id but without all dots. In this case it will be
uitutorialcustomUI.
Value for the last mandatory field -
SAPUI5 Component can be found in
Component.js -
ui.tutorial.customUI in this case.
Right now, you should have everything you need to build and deploy the MTA.
So do it.
Build is done by command line tool called
MBT. Run this command in a terminal.
mbt build
When the build process finished correctly, you should see
INFO finished building the "WF-custom-ui_ui_deployer" module
among other messages. Build process created new directory called
MTA_ARCHIVES and in that folder you should find file called
WF-custom-ui_0.0.1.mtar
Now its time to deploy that project. This time you must use another command line tool - CF and specifically its plugin Multirepo.
cf deploy mta_archives/WF-custom-ui_0.0.1.mtar
After a while you should see terminal full of messages and among them should be
Process finished which indicates, that everything went fine.
So, application is now succesfully deployed on the cloud foundry space. Let`s take a look in a cockpit. Go to the space, into which you deployed app and look at the
Applications page. You should see two apps (if you hadn`t deployed other apps before).
App router si started and flp, which is stopped. FLP app is just deployer of content (CommonDataModel.json) and it finished its task during deploy process and stopped itself to save resources. As I described higher, UI deployer isn`t nodejs app so it isn`t here and UI app also isn`t nodejs app.
Now take a look at Service Instances page
Here you can see all services declared in resources part of mta.yaml. Service column identifies type of service (also seen in Service Marketplace tiles) and Plan column - is plan which you set at mta.yaml. Referencing Applications contains all the backwar references. Backward because we set that bindings in mta.yaml at modules level and here it is shown from resources level.
So everything seems ok, lets look into launchpad. On the
Applications page open app router. On
Overview page open link in section
Application routes.
This link should open new tab in browser and show launchpad on it.
Note: If you see error instead of number 0 on My Inbox tile - you are probably missing roles. Refer to the tutorial, how to create that roles.
Create new workflow instance in a
Monitor Workflows tile.
After that you should see 1 task in My Inbox tile
And as you can see - it is our customUI fiori application. It is just barebone application created from template right now, but you can develop it as you need and interact with Approver as you need. Information how to create basic functionality in your app, including adding Approve and Reject actions, can be found in this
SAP Help page.
Conclusion
This post is a little bit longer then I expected and for sure it could be much longer if I would dive deeper in the details of each individual steps. But I believe that amount of information contained here should help you with creation of bare bone MTA application with workflow, launchpad and custom UI for user task of workflow.
In case that I am wrong, and you will miss some information or I left out some piece and you will stuck in some step - write me in the comments and we can work it out.
I also created
github repository containg the project sources created during the writing of this blog. You can clone it and use it as a template for workflow MTA with custom UI.
Disclaimer: I posted this blog post also on my personal blog. You can find it on
https://vbalko.blogspot.com/2020/09/create-workflow-mtar-application-with.html
All pictures on this blog was created by myself.