Split MTA into backend & frontend – Managed AppRouter
When building applications for the SAP Business Technology Platform (BTP) containing a database layer, API layer and UI layer we have two options. The first option would be to create each part separated and deploy it independent from each other to BTP. The other option would be to keep different modules that share the same lifecycle together by using the concept of MTA. MTA is designed to develop all different modules as one big application and deploy it together to BTP. MTA projects will automatically instantiate required services and bind it to the modules that consume them.
Here you have the official definition of MTA:
A Multitarget application (MTA) is logically a single application comprised of multiple parts created with different technologies, which share the same lifecycle.
The developers of the MTA describe the desired result using the MTA model, which contains MTA modules, MTA resources, and interdependencies between them. Afterward, the validates, orchestrates, and automates the deployment of the MTA, which results in Cloud Foundry applications, services and SAP specific contents. For more information about the Multitarget Application model, see the official The Multitarget Application Model specification.
It states “share the same lifecycle”, the database and API layer often have similar lifecycle but this is not always the case. It can be perfectly possible that the API part and UI have a complete different lifecycle. In that case you maybe want to split up the MTA. Another reason could that you have different teams working on different parts of the app, a team working on the backend and one on the frontend. You maybe don’t want that a backend developer starts changing the frontend or the other way around. There might be even more reasons to split your MTA.
The question remains, how to connect the frontend to the backend when they are part of different MTA projects? Just like you have different reasons for splitting your MTA, there are different solutions to connect both MTA projects. In this blog I’m going to show how you can split your backend from the frontend using the managed AppRouter in BTP by only using MTA configuration.
Let’s start by creating the backend MTA:
(I’m going to use the Business Application Studio because it comes with a generator that has some valuable AppRouter configuration for the managed AppRouter)
Create Backend service
With “Backend service” I mean the database and api layer together. This goes hand in hand most of the time so it doesn’t harm to keep this together.
For creating the backend, I used the SAP Cloud Application Programming model, also known as CAP. Starting by using the “CAP Project” generator in BAS:
In the generator I provide a name for my project, select my favorite runtime and enable deployment for the database part to HANA with MTA configuration for deploying to CloudFoundry.
On top of that, I also enable the option to include the basic sample files just for testing purpose.
For demo purpose I simply keep everything as generated from the sample files. I do enable authentication on my service for security reasons by following the steps in the CAP documentation: https://cap.cloud.sap/docs/node.js/authentication#jwt
Some parts of the documentation are done by the mta configuration. For example, the xsuaa configuration comes from the generator already.
Next, I make authentication required by adding the following in the “cat-service.cds”
That’s actually it for the backend service!
For making the backend service available to other applications, I need some additional configuration. This configuration can be easily generated by adding a Fiori app to the CAP project. It also gives the possibility to test if everything works fine. For this I still used the deprecated generator “SAP Fiori Freestyle Module”:
Reason, why I use the deprecated generator: https://answers.sap.com/questions/13303942/bas-fiori-generator-not-working-with-cap-service-i.html
Give it a name:
Select the basic template:
Immediately add the approuter config, I want to use the “Managed Approuter” and provide a unique name my project: (It’s important to not use an existing one, it will overwrite the existing one.)
Enable authentication an provide a namespace:
Provide a name for the main view and add a data service
This is the benefit when running the generator for a UI module in the same mta. You can simply connect the UI module to the service in the generator by selecting “workspace”:
And here you can select the service from your CAP project:
I also added a list to the main view to see the result of the CAP service.
In the end, this generator will add configuration to the mta.yaml file which will create a destination for the CAP service:
This destination is needed to access the CAP service from other applications outside this MTA project.
You can find the full code in this repo: https://github.com/lemaiwo/SplitAppService
Create separated Frontend app
Off course, by frontend I mean a Fiori UI5 application :). Instead of generating a new UI5 app in the same MTA, I’m going to create a completely new MTA project with only my UI5 app. This time I used the newly released “SAP Fiori application” generator:
I selected the same template as in the deprecated generator:
As Data source I selected “None”. Currently I did not found a way to connect to my CAP service by using the generator:
I filled in all the project attributes and enabled deployment and flp configuration:
For some reason I got stuck in the generator at the time writing this blog post. Luckily, I was able to finish the wizard before taking screenshots and notes. If the problem in the generator still occurs for you, I raised this as a question for follow up:
For now, I continued using the deprecated generator. This generator includes the steps for the configuration of the approuter. If you use the new generator, you have to run a second generator for adding the approuter config: (You can also do this manually but it’s not that easy)
I’m going to use the “Managed Approuter” again. Be aware that the id for the managed approuter needs to be unique. Otherwise it will overwrite other html5 repositories.
This generator will add the following configuration to your project. This is the key to connect the UI of this MTA project to the service in the other MTA project:
This configuration will create a destination for the app-host and xsuaa instance that’s being used for the Fiori app in combination with the sap cloud service id. These generated destinations are needed for the Launchpad service to find your app in the HTML5 content provider. You can find detail explanation in the sap help documentation: https://help.sap.com/viewer/8c8e1958338140699bd4811b37b82ece/Cloud/en-US/1b80373be4fc4cbb8a7529495c9c9d62.html
I changed this generated config for two reasons:
- Reusing service instances, some services are already instantiated by the config of the first project (CAP project with Fiori app included).
- The destination service from the Fiori app in the CAP project can be used in this Fiori app as well. It’s not needed to create a new instance of the Destination service
- This is not the case for all of them, the app-host service needs to be a new instance. Otherwise it will overwrite your other app.
- I’m going to reuse the xsuaa service which I’m going to explain in the next point. In case you have completely separated apps, it is better to create a new xsuaa instance. This will allow you to maintain the scopes dedicated for this app in the app-security file.
- Using my CAP service from the first project
- I want to consume my CAP service from my first project in my second separated fiori app. For this, the service and the UI app need to be connected to the same XSUAA instance. Downside, both share the same xs-security.json file. Best is to keep them in sync because each deploy will overwrite the previously deployed xs-security.json.
Let’s start the magic 🙂
- Change the destination service, go to “resources” in the mta.yaml and change the “service-name” of the destination service to the same as the one in the first project:
2. Change the service instance name of the xsuaa service to the same as in the first project:
3. Change the “xsappname” in xs-security.json to the same as the other project. Otherwise the deploy will fail because it’s not possible to update the name in an existing xsuaa instance.
4. Add the route to the destination of the CAP service in the xs-app.json (this destination was generated from the mta config in the CAP project)
5. Add tile config (might be done already by the generator)
6. Add the datasource config to the CAP service:
7. Add the ODataModel config:
8. Show the books entity as a list in the main view:
9. The app is ready for building and deploying to BTP CloudFoundry
The full project is available on GitHub: https://github.com/lemaiwo/SplitAppUI
Result in BTP Launchpad Service
As soon as the applications are deployed, you have to refresh the “HTML5 Apps” content provider in the Launchpad service and you will find them in the Content Exporer:
First refresh the HTML5 Apps provider:
Now, you will see your app in the “Content Explorer”:
Add the app to a catalog, group and role to see it on the launchpad:
When you click on the tile, the app from one MTA project will open and show data from the other MTA project:
A more detailed tutorial on how to integration your app in the launchpad service:
The complete group of tutorials: https://developers.sap.com/group.launchpad-cf-add-custom-app.html
I created a CAP project with a database, api and ui layer. The API was made accessible only for authenticated users. On top of that, I created a UI only app that consumes the API from the CAP project. All of this described in different MTA’s. The key is to bind both MTA projects to the same xsuaa service instance.
This setup can be used in case you want to separate the MTA project into a backend and frontend part for whatever reason.
I shared my example projects on GitHub:
I had this requirement for splitting up the MTA into backend and frontend already a few times for different reasons. Sometimes because of different types of developers, sometimes because one API is consumed by several apps and all have a different lifecycle or just to improve the build and deploy time of the MTA. Hope this can be valuable for you as well!