| name | mta-descriptor |
| description | Invoke this skill to generate MTA deployment descriptor (mtad.yaml) for Cloud Foundry. Creates mtad.yaml with proper service bindings based on migration skills applied. Always invoke LAST after all other migration skills. |
| disable-model-invocation | false |
| allowed-tools | Read, Edit, Write, Bash, Grep, Glob |
MTA Descriptor Generation
Generate a Multi-Target Application deployment descriptor (mtad.yaml) for deploying Neo-migrated applications to SAP BTP Cloud Foundry.
Usage
Generate an mtad.yaml for my migrated application
Create MTA descriptor with XSUAA and HANA services
Overview
The MTA descriptor (mtad.yaml) defines:
- Application modules (Java app, approuter)
- Required Cloud Foundry services (XSUAA, HANA, Destination, etc.)
- Service bindings between modules and services
- Build and deployment parameters
This skill analyzes which migration skills were applied to your application and generates the appropriate mtad.yaml configuration.
Prerequisites
Working directory: This skill must run inside the -cf-migration copy of your app, created by jakarta-java25-migration or neo-to-cf-migration-orchestrator. If your current directory does not end in -cf-migration, switch to it before proceeding.
Before invoking this skill, ensure you have invoked all required migration skills:
- jakarta-java25-migration -
Use the jakarta-java25-migration skill (REQUIRED)
- sdk-replacement -
Use the sdk-replacement skill (REQUIRED)
- Any feature skills that apply to your application
Also required:
- Application successfully compiles:
mvn clean compile
- Understanding of which CF services your application requires
Determine Required Services
Based on the migration skills you've applied, identify required CF services:
| Migration Skill Applied | Required CF Service | Service Type |
|---|
| authentication-xsuaa | XSUAA | org.cloudfoundry.managed-service |
| destinations | Destination | org.cloudfoundry.managed-service |
| connectivity-onpremise | Destination + Connectivity | org.cloudfoundry.managed-service |
| persistence-hana | HANA Schema | com.sap.xs.hana-schema |
| document-management-sdm | SDM | org.cloudfoundry.managed-service |
| mail-destinations | (uses Destination service) | - |
| keystore-credstore | Credential Store | org.cloudfoundry.managed-service |
| monitoring-logging | (built-in CF logging) | - |
| tomee-runtime | (requires TARGET_RUNTIME property) | - |
MTA Templates
Template Selection
Choose the appropriate base template:
| Scenario | Template | When to Use |
|---|
| Basic app without web authentication | mtad-base.yaml | Internal services, background jobs, APIs with technical auth |
| App with XSUAA and Approuter | mtad-with-approuter.yaml | User-facing web applications requiring authentication |
| TomEE application | Add TARGET_RUNTIME: tomee | Apps using EJB or requiring TomEE runtime |
Template: Basic Application (mtad-base.yaml)
For applications without user authentication:
_schema-version: "3.3"
ID: my-app
version: 1.0.0
parameters:
parameters:
enable-parallel-deployments: true
modules:
- name: my-app-backend
type: java.tomcat
path: target/ROOT.war
parameters:
memory: 1024M
disk-quota: 1024M
buildpack: sap_java_buildpack_jakarta
properties:
JBP_CONFIG_COMPONENTS: "jres: ['com.sap.xs.java.buildpack.jdk.SAPMachineJDK']"
JBP_CONFIG_SAP_MACHINE_JDK: "{ version: 25.+ }"
TARGET_RUNTIME: tomcat
build-parameters:
builder: maven
build-result: target/*.war
provides:
- name: backend-api
properties:
url: ${default-url}
requires:
- name: my-app-hana
- name: my-app-destination
resources:
Template: Application with XSUAA (mtad-with-approuter.yaml)
For user-facing web applications:
_schema-version: "3.2"
ID: my-app
version: 0.0.1
parameters:
enable-parallel-deployments: true
modules:
- name: my-app-approuter
type: nodejs
path: approuter
parameters:
memory: 256M
disk-quota: 256M
routes:
- route: '${protocol}://my-app.${default-domain}'
protocol: http1
properties:
XS_APP_LOG_LEVEL: debug
TENANT_HOST_PATTERN: '(.*).cfapps.sap.hana.ondemand.com'
CF_NODEJS_LOGGING_LEVEL: "info"
requires:
- name: my-app-xsuaa
- name: my-app-java-app
group: destinations
properties:
name: backend-app-destination
url: '~{neo-app-url}'
forwardAuthToken: true
- name: my-app-backend
type: java.tomcat
path: target/ROOT.war
parameters:
memory: 1024M
disk-quota: 1024M
buildpack: sap_java_buildpack_jakarta
properties:
ENABLE_SECURITY_JAVA_API_V2: true
JBP_CONFIG_COMPONENTS: "jres: ['com.sap.xs.java.buildpack.jdk.SAPMachineJDK']"
JBP_CONFIG_SAP_MACHINE_JDK: "{ version: 25.+ }"
TARGET_RUNTIME: tomcat
SET_LOGGING_LEVEL: 'ROOT: INFO'
provides:
- name: my-app-java-app
properties:
neo-app-url: '${default-url}'
requires:
- name: my-app-xsuaa
- name: my-app-destination
resources:
- name: my-app-xsuaa
type: org.cloudfoundry.managed-service
parameters:
service: xsuaa
service-plan: application
path: ./xs-security.json
- name: my-app-destination
type: org.cloudfoundry.managed-service
parameters:
service: destination
service-plan: lite
Critical: The Java backend path must point to target/ROOT.war (not target/myapp.war). See "WAR context path" in Troubleshooting below.
Note on type: nodejs vs type: approuter.nodejs: Use type: nodejs when deploying the approuter with your own approuter/ directory and package.json (which is the standard pattern for migrated Neo applications). The type approuter.nodejs is for the "managed approuter" pattern which is used only in specific multi-tenant scenarios.
Service Configuration Examples
Add these resource definitions based on services your application needs:
XSUAA (Authentication)
resources:
- name: ${app-name}-xsuaa
type: org.cloudfoundry.managed-service
parameters:
service: xsuaa
service-plan: application
path: ./xs-security.json
Module requires:
requires:
- name: ${app-name}-xsuaa
Destination Service
resources:
- name: ${app-name}-destination
type: org.cloudfoundry.managed-service
parameters:
service: destination
service-plan: lite
Module requires:
requires:
- name: ${app-name}-destination
Connectivity Service (On-Premise)
resources:
- name: ${app-name}-connectivity
type: org.cloudfoundry.managed-service
parameters:
service: connectivity
service-plan: lite
Module requires:
requires:
- name: ${app-name}-connectivity
- name: ${app-name}-destination
HANA Schema
resources:
- name: ${app-name}-hana
type: com.sap.xs.hana-schema
parameters:
schema-name: ${app-name}
properties:
hdi-service-name: ${service-name}
Module requires:
requires:
- name: ${app-name}-hana
properties:
TARGET_CONTAINER: ~{hdi-service-name}
Document Management (SDM)
resources:
- name: ${app-name}-sdm
type: org.cloudfoundry.managed-service
parameters:
service: sdm
service-plan: standard
Module requires:
requires:
- name: ${app-name}-sdm
Credential Store
resources:
- name: ${app-name}-credstore
type: org.cloudfoundry.managed-service
parameters:
service: credstore
service-plan: standard
config:
encryption:
user_key_name: "credstore-key"
Module requires:
requires:
- name: ${app-name}-credstore
Generation Steps
1. Analyze Application Requirements
Identify which services your application needs:
grep -r "com.sap.cloud.security.xsuaa" pom.xml
grep -r "com.sap.cloud.sdk.cloudplatform.connectivity" pom.xml
grep -r "javax.sql.DataSource\|jakarta.persistence" src/main/java/
grep -r "com.sap.ecm.api" src/main/java/
2. Select Base Template
Copy the appropriate template:
cp skills/mta-descriptor/assets/mtad-base.yaml mtad.yaml
cp skills/mta-descriptor/assets/mtad-with-approuter.yaml mtad.yaml
3. Customize Application Properties
Update the mtad.yaml with your application details:
ID: my-application-name
version: 1.0.0
modules:
- name: my-app-backend
path: target/ROOT.war
parameters:
memory: 1024M
disk-quota: 1024M
WAR naming: The SAP Java buildpack deploys the WAR using its filename as the Tomcat context path. A WAR named auth.war is served at /auth, not /. Always configure maven-war-plugin with <warName>ROOT</warName> so the app is served at the root path, and reference target/ROOT.war in mtad.yaml.
4. Add Required Services
Based on your analysis in step 1, add the necessary service resources and module requirements.
Example: App with XSUAA, Destination, and HANA:
modules:
- name: my-app-backend
requires:
- name: my-app-xsuaa
- name: my-app-destination
- name: my-app-hana
resources:
- name: my-app-xsuaa
type: org.cloudfoundry.managed-service
parameters:
service: xsuaa
service-plan: application
path: ./xs-security.json
- name: my-app-destination
type: org.cloudfoundry.managed-service
parameters:
service: destination
service-plan: lite
- name: my-app-hana
type: com.sap.xs.hana-schema
5. Configure TomEE Runtime (if applicable)
If you used the tomee-runtime skill:
modules:
- name: my-app-backend
properties:
TARGET_RUNTIME: tomee
6. Validate the Descriptor
Check the syntax and structure:
yamllint mtad.yaml
python3 -c "import yaml; yaml.safe_load(open('mtad.yaml'))"
Build and Deploy
After generating the mtad.yaml:
Build MTA Archive
mbt build
Deploy to Cloud Foundry
cf deploy mta_archives/my-app_1.0.0.mtar
cf deploy .
Verify Deployment
cf apps
cf services
cf logs my-app-backend --recent
Common Configurations
Multi-Module Application
modules:
- name: my-app-ui
type: html5
path: ui-module
- name: my-app-backend
type: java
path: backend-module
provides:
- name: backend-api
properties:
url: ${default-url}
- name: my-app-worker
type: java
path: worker-module
requires:
- name: backend-api
Environment Variables
modules:
- name: my-app-backend
properties:
MY_CUSTOM_VAR: "production-value"
SPRING_PROFILES_ACTIVE: "cloud"
JBP_CONFIG_RESOURCE_CONFIGURATION: "[tomcat/webapps/ROOT/WEB-INF/web.xml: {'web-app/session-config/session-timeout': 60}]"
Health Check Configuration
modules:
- name: my-app-backend
parameters:
health-check-type: http
health-check-http-endpoint: /actuator/health
health-check-timeout: 180
Troubleshooting
Issue: Service binding fails
Symptom: Application fails to bind to services during deployment
Solution: Verify service names in requires match service names in resources:
resources:
- name: my-app-xsuaa
modules:
- name: my-app-backend
requires:
- name: my-app-xsuaa
Issue: Module fails to build
Symptom: Build errors during cf deploy
Solution: Verify build parameters:
modules:
- name: my-app-backend
build-parameters:
builder: maven
build-result: target/*.war
Issue: Memory errors
Symptom: Application crashes with out-of-memory errors
Solution: Increase memory allocation:
modules:
- name: my-app-backend
parameters:
memory: 2048M
disk-quota: 1024M
Issue: 404 Not Found — app deployed but all routes return 404
Symptom: App starts successfully but every request returns 404. Logs show Tomcat started but requests don't match any servlet.
Cause: WAR is named myapp.war so Tomcat serves it at /myapp, not /. All servlet URL patterns are relative to the context path.
Solution: Configure maven-war-plugin to produce ROOT.war:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<warName>ROOT</warName>
</configuration>
</plugin>
Update mtad.yaml path to target/ROOT.war and rebuild.
Note: <finalName> in <build> does NOT control the WAR name — only <warName> in the plugin configuration does.
Issue: Routes quota exceeded
Symptom: cf deploy fails with Routes quota exceeded for organization '<org>'. quota: SUBSCRIPTION_QUOTA — total memory: 0, routes: 0
Cause: The CF org uses SUBSCRIPTION_QUOTA which has 0 routes and 0 memory by default. This is set by SAP's entitlement system.
Solution: A Global Account Administrator must assign CF Runtime memory in BTP Cockpit:
- BTP Cockpit → Global Account → Entitlements → Entity Assignments
- Select the subaccount → Configure Entitlements → Cloud Foundry Runtime → assign memory (e.g. 3GB)
- BTP automatically creates a new org quota named
<guid>-t-<subaccount-guid> and applies it
Note: cf create-space-quota and cf create-quota do NOT fix this — org-level route limits cannot be overridden by space quotas, and creating new org quotas requires CF admin rights.
Issue: maven-war-plugin fails with Cannot access defaults field of Properties
Symptom: Maven build fails with this error when using Java 25.
Cause: Default maven-war-plugin:2.2 is incompatible with Java 25.
Solution: Explicitly pin maven-war-plugin to 3.4.0 in pom.xml.
Integration with CF Plugin
After generating the mtad.yaml, use the cf-plugin skills for deployment:
# Use cf-plugin to deploy the MTA
/sap-btp-cf:cf-push-app my-app
# View deployment logs
/sap-btp-cf:cf-get-app-logs my-app
Post-Deployment Configuration
Assign Role Collections (XSUAA)
If using authentication-xsuaa:
- Open SAP BTP Cockpit
- Navigate to Security → Role Collections
- Assign role collection to users/user groups
- Verify by logging into the application
Create Destinations (Destination Service)
If using destinations skill:
- Open SAP BTP Cockpit
- Navigate to Connectivity → Destinations
- Create destinations as defined in the destinations skill
- Test connectivity from the application
Configure Cloud Connector (Connectivity)
If using connectivity-onpremise:
- Install and configure Cloud Connector
- Add virtual hosts matching destination configuration
- Map to on-premise systems
- Test connectivity
See Also
References