Deploy a java-based CAP with frontend into BTP

If you want to deploy a full stack CAP project using a MTA file, there are many small but crucial details to consider.

1 Path

The path must be defined correctly in order for the frontend to access the backend APIs.

1.1 Definition

Typically the path looks like this:

1.1.1 Service Name

For custom paths, define the service name in the *service.cds file in the srv folder using the annotation “@path”. For example:

The path will look like this:

So, now we know the function of the annotation “@path” is to rename the service.

1.1.2 Servlet Path

In addition, you may need to define the servlet path in the application.yaml file.

The result is:

1.2 Consume

Once the path is defined, or you just use the default path.

In order for the frontend to consume the service, maintain the three required areas: mainfest.json and xs-app.json.

  • mainfest.json

  • xs-app.json

2 Some configuration files

2.1 Spring-boot pom configuration and package

In the pom.xml of spring-boot, define <groupId> and <artifactId> .Make sure your java package containing “Application.java” is */main/<groupId>/<artifactId>. This prevents a 404 error when the app is deployed in BTP.

2.2 MTA file

The MTA file is the key to deploy cap project, for the simple project, you can see the mandatory configuration and their relationship:

For the “html5” module, it will be used to generate a zip file which is consumed by “ui-deployer”.

The blow is an example, take care of their relationship and change the path according to your project.

_schema-version: "3.1"
ID: 
description: 
version: 2.0.0
parameters:
  enable-parallel-deployments: true

build-parameters:
  before-all:
    - builder: custom
      commands:
        - npx -p @sap/cds-dk cds build --profile production,java
        - npx -p @sap/cds-dk cds build --profile production,hana

modules:
  - name: myapp_srv
    type: java
    path: srv
    properties:
      SPRING_PROFILES_ACTIVE: cloud
      JBP_CONFIG_COMPONENTS: "jres: ['com.sap.xs.java.buildpack.jdk.SAPMachineJDK']"
      JBP_CONFIG_SAP_MACHINE_JRE: "{ jre: { version: 11.+ } }"
    requires:
      - name: myapp_uaa
      - name: myapp_db
    provides:
      - name: srv-api
        properties:
          srv-url: ${default-url}
    build-parameters:
      builder: custom
      commands:
        - mvn clean package -DskipTests=true
      build-result: target/*-exec.jar
      ignore: ["node_modules/"]
  - name: myapp_db-deployer
    type: hdb
    path: db
    requires:
      - name: myapp_db
      - name: myapp_uaa
    parameters:
      buildpack: nodejs_buildpack
  - name: myapp_destination_content
    type: com.sap.application.content
    requires:
      - name: myapp_uaa
        parameters:
          service-key:
            name: myapp_uaa-key
      - name: myapp_html5_repo_host
        parameters:
          service-key:
            name: myapp_html5_repo_host-key
      - name: myapp-destination-service
        parameters:
          content-target: true
    parameters:
      content:
        subaccount:
          destinations:
            - Name: myapp_service_html5_repo_host
              ServiceInstanceName: myapp_html5_repo_host
              ServiceKeyName: myapp_html5_repo_host-key
              sap.cloud.service: myapp_service
            - Authentication: OAuth2UserTokenExchange
              Name: myapp_service_uaa
              ServiceInstanceName: myapp_uaa
              ServiceKeyName: myapp_uaa-key
              sap.cloud.service: myapp_service
          existing_destinations_policy: update
    build-parameters:
      no-source: true
  - name: myapp_ui_deployer
    type: com.sap.application.content
    path: app
    requires:
      - name: myapp-destination-service
      - name: myapp_html5_repo_host
        parameters:
          content-target: true
    build-parameters:
      build-result: resources
      requires:
        - artifacts:
            - fiori-content.zip
          name: myapp
          target-path: resources/
  - name: myapp
    type: html5
    path: app/myapp
    build-parameters:
      build-result: dist
      builder: custom
      commands:
        - npm install
        - npm run build
      supported-platforms: []
resources:
  - name: myapp_db
    type: com.sap.xs.hdi-container
    parameters:
      service: hana
      service-plan: hdi-shared
    properties:
      hdi-service-name: ${service-name}
  - name: myapp-destination-service
    type: org.cloudfoundry.managed-service
    requires:
      - name: srv-api
    parameters:
      service: destination
      service-plan: lite
      config:
        init_data:
          subaccount:
            existing_destinations_policy: update
            destinations:
              - Name: myapp-destination
                Description: Sales Order Request service
                Authentication: NoAuthentication
                ProxyType: Internet
                Type: HTTP
                URL: ~{srv-api/srv-url}
                HTML5.DynamicDestination: true
                HTML5.ForwardAuthToken: true
  - name: myapp_html5_repo_host
    type: org.cloudfoundry.managed-service
    parameters:
      service: html5-apps-repo
      service-plan: app-host

  - name: myapp_html5_repo_runtime
    type: org.cloudfoundry.managed-service
    parameters:
      service: html5-apps-repo
      service-plan: app-runtime
  - name: myapp_uaa
    type: org.cloudfoundry.managed-service
    parameters:
      path: ./xs-security.json
      service: xsuaa
      service-plan: application

2.3 Adjust your frontend file to make sure the html5 app can consume the service deployed in BTP.

2.3.1 Change the destination in the xs-app.json

2.3.2 Change the sap-service in manifest.json

To be honest, I don’t understand this attribute.

3 Little tips

Add your frontend location of index.html in the application.yaml file, then you can run the frontend and backend together by the commend “mvn spring-boot:run”.

spring:
    web.resources.static-locations: “file:./app/salesorderrequest/webapp”
Scroll to Top