Deploying Fiori Elements Apps to BTP: From Development to Production

Category
BTP
Published
Author
Johannes

Deploying a Fiori Elements App to SAP BTP involves several steps: From project creation in Business Application Studio through proper configuration to integration into the SAP Build Work Zone Launchpad. This article walks you through the complete process.

Overview: Deployment Process

┌─────────────────────────────────────────────────────────────────────┐
│ Fiori Elements App Deployment │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Create App 2. Configure 3. Build & Deploy │
│ ────────────── ───────────── ───────────────── │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ BAS │ │ manifest.json │ │ MTA Build │ │
│ │ Generator │ → │ xs-app.json │ → │ cf deploy │ │
│ │ │ │ mta.yaml │ │ │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │ │
│ ▼ │
│ 4. Launchpad Integration │
│ ────────────────────── │
│ ┌───────────────────────┐ │
│ │ SAP Build Work Zone │ │
│ │ • Create tile │ │
│ │ • Assign space │ │
│ │ • Configure roles │ │
│ └───────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘

Prerequisites

Before you start deployment:

PrerequisiteDescription
RAP ServiceWorking OData V4 service on BTP ABAP Environment
BAS Dev SpaceSAP Fiori Dev Space in Business Application Studio
Cloud FoundryAccess to BTP subaccount with CF space
Build Work ZoneSAP Build Work Zone (Standard or Advanced) subscription
DestinationConfigured destination to ABAP Environment

1. App Creation in Business Application Studio

Prepare Dev Space

If not already available, create a Fiori Dev Space:

1. Open BAS → "Create Dev Space"
2. Name: "FioriDevelopment"
3. Type: Select "SAP Fiori"
4. Activate extensions:
☑ HTML5 Application Template
☑ Fiori Tools
☑ MTA Build Tools
5. Click "Create Dev Space"

Generate Fiori Elements App

After dev space starts:

1. View → Command Palette (F1)
2. Enter "Fiori: Open Application Generator"
3. Select template: "List Report Page"
4. Click next

Configure Data Source

Data Source: "Connect to SAP System"
Service Selection:
├── System: BTP ABAP Environment
├── ABAP Environment: [Your service key]
├── System URL: (automatically from service key)
└── Service: ZUI_FLIGHTBOOK_O4 (your OData service)
Main Entity: FlightBook
Navigation Entity: None (or child entity if available)

Set Project Attributes

Project Name: flightbooking
Application Title: Manage Flight Bookings
Application Namespace: com.mycompany
Description: Fiori Elements App for Flight Bookings
Minimum SAPUI5 Version: 1.127.0 (or newer)
Project Folder: /home/user/projects
Add deployment configuration: Yes
Add FLP configuration: Yes

Deployment and FLP Configuration

Provide during generation:

Deployment Configuration:
├── Target: Cloud Foundry
├── Destination Name: BTP_ABAP_ENV (your destination)
└── Add Application to managed App Router: Yes
FLP Configuration:
├── Semantic Object: FlightBooking
├── Action: manage
├── Title: Manage Flight Bookings
└── Subtitle: Create and edit bookings

2. Understanding Deployment Configuration

After generation, your project contains several configuration files.

Project Structure

flightbooking/
├── webapp/
│ ├── manifest.json # App configuration
│ ├── Component.js # UI5 Component
│ ├── i18n/
│ │ └── i18n.properties # Translations
│ ├── localService/ # Mock data for local testing
│ └── test/ # OPA5 tests
├── xs-app.json # App Router routing
├── mta.yaml # Multi-Target Application Descriptor
├── package.json # Node.js dependencies
├── ui5.yaml # UI5 build configuration
└── ui5-deploy.yaml # Deployment-specific UI5 config

manifest.json

The manifest.json is the heart of app configuration:

{
"_version": "1.65.0",
"sap.app": {
"id": "com.mycompany.flightbooking",
"type": "application",
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"applicationVersion": {
"version": "1.0.0"
},
"dataSources": {
"mainService": {
"uri": "/sap/opu/odata4/sap/zui_flightbook_o4/srvd/sap/zui_flightbook/0001/",
"type": "OData",
"settings": {
"odataVersion": "4.0"
}
}
},
"crossNavigation": {
"inbounds": {
"FlightBooking-manage": {
"semanticObject": "FlightBooking",
"action": "manage",
"title": "{{flpTitle}}",
"subTitle": "{{flpSubtitle}}",
"signature": {
"parameters": {},
"additionalParameters": "allowed"
}
}
}
}
},
"sap.ui5": {
"flexEnabled": true,
"dependencies": {
"minUI5Version": "1.127.0",
"libs": {
"sap.m": {},
"sap.ui.core": {},
"sap.fe.templates": {}
}
},
"routing": {
"routes": [
{
"pattern": ":?query:",
"name": "FlightBookList",
"target": "FlightBookList"
},
{
"pattern": "FlightBook({key}):?query:",
"name": "FlightBookObjectPage",
"target": "FlightBookObjectPage"
}
],
"targets": {
"FlightBookList": {
"type": "Component",
"id": "FlightBookList",
"name": "sap.fe.templates.ListReport",
"options": {
"settings": {
"contextPath": "/FlightBook",
"variantManagement": "Page",
"navigation": {
"FlightBook": {
"detail": {
"route": "FlightBookObjectPage"
}
}
},
"initialLoad": "Enabled"
}
}
},
"FlightBookObjectPage": {
"type": "Component",
"id": "FlightBookObjectPage",
"name": "sap.fe.templates.ObjectPage",
"options": {
"settings": {
"contextPath": "/FlightBook",
"editableHeaderContent": false
}
}
}
}
}
}
}

Important Settings:

PropertyDescription
sap.app.idUnique app ID (namespace + name)
dataSources.mainService.uriPath to OData service
crossNavigation.inboundsLaunchpad integration (Semantic Object + Action)
variantManagementSave user-specific views
initialLoadLoad data on startup

xs-app.json

The Application Router uses this file for routing:

{
"welcomeFile": "/index.html",
"authenticationMethod": "route",
"routes": [
{
"source": "^/sap/opu/odata4/(.*)$",
"target": "/sap/opu/odata4/$1",
"destination": "BTP_ABAP_ENV",
"authenticationType": "xsuaa",
"csrfProtection": false
},
{
"source": "^(.*)$",
"target": "$1",
"service": "html5-apps-repo-rt",
"authenticationType": "xsuaa"
}
]
}

Route Explanation:

RoutePurpose
/sap/opu/odata4/(.*)Forward OData requests to ABAP Environment
^(.*)$All other requests (HTML, JS, CSS) from HTML5 Repository

mta.yaml

The Multi-Target Application Descriptor defines all components:

_schema-version: '3.2'
ID: flightbooking
version: 1.0.0
description: Flight Booking Fiori Elements App
parameters:
enable-parallel-deployments: true
deploy_mode: html5-repo
build-parameters:
before-all:
- builder: custom
commands:
- npm ci
- npx ui5 build --config=ui5-deploy.yaml --clean-dest --dest dist
modules:
# HTML5 App Deployer
- name: flightbooking-deployer
type: com.sap.application.content
path: dist
requires:
- name: flightbooking-html5-repo-host
parameters:
content-target: true
# Destination Content
- name: flightbooking-destination-content
type: com.sap.application.content
requires:
- name: flightbooking-destination-service
parameters:
content-target: true
- name: flightbooking-html5-repo-host
parameters:
service-key:
name: flightbooking-html5-repo-host-key
- name: flightbooking-uaa
parameters:
service-key:
name: flightbooking-uaa-key
parameters:
content:
instance:
destinations:
- Name: flightbooking_html5_repo_host
ServiceInstanceName: flightbooking-html5-repo-host
ServiceKeyName: flightbooking-html5-repo-host-key
sap.cloud.service: com.mycompany.flightbooking
- Authentication: OAuth2UserTokenExchange
Name: flightbooking_uaa
ServiceInstanceName: flightbooking-uaa
ServiceKeyName: flightbooking-uaa-key
sap.cloud.service: com.mycompany.flightbooking
existing_destinations_policy: update
resources:
# HTML5 Application Repository
- name: flightbooking-html5-repo-host
type: org.cloudfoundry.managed-service
parameters:
service: html5-apps-repo
service-plan: app-host
# Destination Service
- name: flightbooking-destination-service
type: org.cloudfoundry.managed-service
parameters:
service: destination
service-plan: lite
config:
HTML5Runtime_enabled: true
# UAA Service
- name: flightbooking-uaa
type: org.cloudfoundry.managed-service
parameters:
service: xsuaa
service-plan: application
path: ./xs-security.json

xs-security.json

Defines security configuration:

{
"xsappname": "flightbooking",
"tenant-mode": "dedicated",
"scopes": [],
"attributes": [],
"role-templates": [],
"oauth2-configuration": {
"redirect-uris": [
"https://*.cfapps.*.hana.ondemand.com/**"
]
}
}

3. Step-by-Step Deployment Process

Step 1: Cloud Foundry Login

In BAS terminal:

Terminal window
# CF CLI Login
cf login -a https://api.cf.eu10.hana.ondemand.com
# Select org and space
cf target -o my-org -s dev

Step 2: Check Destination

In BTP Cockpit under Connectivity → Destinations, a destination to ABAP Environment must exist:

Destination: BTP_ABAP_ENV
Type: HTTP
URL: https://<abap-env-host>.abap.eu10.hana.ondemand.com
Proxy Type: Internet
Authentication: OAuth2SAMLBearerAssertion
Additional Properties:
├── sap-client: 100
├── HTML5.DynamicDestination: true
└── WebIDEUsage: odata_gen,odata_abap

Step 3: MTA Build

Terminal window
# In project directory
cd /home/user/projects/flightbooking
# Execute MTA build
mbt build
# Result: mta_archives/flightbooking_1.0.0.mtar

The build process:

┌─────────────────────────────────────────────────────────┐
│ MTA Build │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. npm ci │
│ └── Install dependencies │
│ │
│ 2. npx ui5 build │
│ └── Compile UI5 app │
│ └── Minify │
│ └── Create dist/ directory │
│ │
│ 3. mbt build │
│ └── Combine modules │
│ └── Create .mtar archive │
│ │
│ Output: mta_archives/flightbooking_1.0.0.mtar │
│ │
└─────────────────────────────────────────────────────────┘

Step 4: Deploy to Cloud Foundry

Terminal window
# Deploy MTAR
cf deploy mta_archives/flightbooking_1.0.0.mtar
# Alternatively with progress indicator
cf deploy mta_archives/flightbooking_1.0.0.mtar --version-rule ALL

Deployment output:

Deploying multi-target app archive flightbooking_1.0.0.mtar...
Uploading 1 of 1 done
Processing service "flightbooking-html5-repo-host"...
Processing service "flightbooking-destination-service"...
Processing service "flightbooking-uaa"...
Uploading content module "flightbooking-deployer"...
Deploying content module "flightbooking-destination-content"...
Process finished successfully.

Step 5: Verify Deployment

Terminal window
# Check services
cf services
# Output:
# NAME SERVICE PLAN
# flightbooking-html5-repo-host html5-apps-repo app-host
# flightbooking-destination-service destination lite
# flightbooking-uaa xsuaa application
# List HTML5 apps
cf html5-list
# Output:
# name version app-host-id
# com.mycompany.flightbooking 1.0.0 abc123-def456

4. Launchpad Integration

After deployment, the app must be integrated into SAP Build Work Zone Launchpad.

Open Site Manager

1. BTP Cockpit → Instances and Subscriptions
2. SAP Build Work Zone, standard edition → Go to Application
3. Channel Manager → Content Provider "HTML5 Apps" → Refresh

Content Explorer

1. Content Manager → Content Explorer
2. HTML5 Apps → Find your app
3. Click "Add to My Content"

Define Role

1. Content Manager → Create → Role
2. Name: "FlightBookingUser"
3. Description: "Access to Flight Booking App"
4. Assign apps:
☑ Manage Flight Bookings (your app)
5. Save

Create Group

1. Content Manager → Create → Group
2. Title: "Flight Booking"
3. Assign apps:
☑ Manage Flight Bookings
4. Save

Create or Extend Site

1. Site Directory → Create Site (or open existing)
2. Site Settings → Content Assignment
3. Assign role "FlightBookingUser"
4. Save

Assign Users

In BTP Cockpit:

1. Security → Role Collections
2. Edit "FlightBookingUser_RC" (automatically created)
3. Users → Add User
4. Enter email or user ID
5. Save

5. Troubleshooting

Common Deployment Problems

ProblemCauseSolution
”Service not found”HTML5 Repo service unavailableCheck entitlement in subaccount
”Destination not found”Destination name wrong in xs-app.jsonCheck name in destination config
”CSRF token validation failed”csrfProtection enabledSet to false in xs-app.json
”Unauthorized”Missing permissionCheck UAA service key and roles
”Cannot read property…“manifest.json syntax errorUse JSON validator

Build Errors

Terminal window
# Error: Module not found
# Solution: Update dependencies
npm ci
npm update
# Error: UI5 build failed
# Solution: Update UI5 tooling
npm install -g @ui5/cli
# Clear cache
rm -rf node_modules
npm ci

OData Connection Problems

Problem: "Failed to load metadata"
Check:
1. Destination reachable?
→ BTP Cockpit → Connectivity → Destinations → "Check Connection"
2. Service Binding active?
→ ADT → Open Service Binding → "Publish" pressed?
3. CORS configured?
→ Destination: sap-client property set?
4. User authorized?
→ IAM Business Catalog assigned to user?

Launchpad Problems

Problem: App doesn't appear in launchpad
Check:
1. Content Explorer → App visible?
→ If not: Channel Manager → Refresh
2. Role assigned?
→ Content Manager → Role → App included?
3. Role Collection created?
→ Security → Role Collections → _RC exists?
4. User in Role Collection?
→ Role Collection open → Users tab

Activate Debug Mode

For detailed error messages:

URL parameter: ?sap-ui-debug=true
Example:
https://mysite.launchpad.cfapps.eu10.hana.ondemand.com/site#Shell-home?sap-ui-debug=true

Analyze Logs

Terminal window
# App Router logs (if managed approuter)
cf logs flightbooking-approuter --recent
# HTML5 Deployer logs
cf logs flightbooking-deployer --recent
# Service instance logs
cf service flightbooking-html5-repo-host

Best Practices

AreaRecommendation
VersioningIncrement version in mta.yaml with each deployment
Naming ConventionsConsistent namespace structure (com.company.app)
DestinationHTML5.DynamicDestination: true for flexibility
TestingLocal testing with mock data before deployment
CI/CDAutomate MTA build in pipeline
CachingEnable cache busting through version
MonitoringUse Application Logging in BTP Cockpit

Automated Deployment with CI/CD

For automated deployments in a pipeline:

# GitHub Actions example
name: Deploy Fiori App
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install MTA Build Tool
run: npm install -g mbt
- name: Install CF CLI
run: |
wget -q -O cf-cli.deb "https://packages.cloudfoundry.org/stable?release=debian64"
sudo dpkg -i cf-cli.deb
cf install-plugin multiapps -f
- name: Build MTA
run: |
npm ci
mbt build
- name: Deploy to Cloud Foundry
env:
CF_API: ${{ secrets.CF_API }}
CF_USER: ${{ secrets.CF_USER }}
CF_PASSWORD: ${{ secrets.CF_PASSWORD }}
CF_ORG: ${{ secrets.CF_ORG }}
CF_SPACE: ${{ secrets.CF_SPACE }}
run: |
cf login -a $CF_API -u $CF_USER -p $CF_PASSWORD -o $CF_ORG -s $CF_SPACE
cf deploy mta_archives/*.mtar -f

Conclusion

Deploying a Fiori Elements app to SAP BTP requires several configuration steps, but they are well supported by the Fiori generator. The key is understanding the individual components:

  1. manifest.json defines app metadata and OData connection
  2. xs-app.json configures routing via App Router
  3. mta.yaml orchestrates all services and modules
  4. Launchpad integration makes the app accessible to end users

With this knowledge, you can reliably deploy Fiori Elements apps to BTP and provide them in the Launchpad.