Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
545
Objective is to build a multi-modular CAP Java application supporting multi-tenancy where the services within each module can be used to fulfil individual business logics and can use the same models. The structure is:
|-- db/

`-- data-model.cds

|--app/

|--approuter/

|--mtx/sidecar/

|--srv1

`-- monitoringservice.cds

`--pom.xml

|--srv2

`-- integrationservice.cds

`--pom.xml

Note: The services should be distinct for each sub module.

Add the following in parent pom.xml
<commands>
<command>deploy db srv2 --to h2 --dry &gt; srv2/src/main/resources/schema.sql</command>
<command>deploy db srv1 --to h2 --dry &gt; srv1/src/main/resources/schema.sql</command>
</commands>

Or


srv/pom.xml
<commands>
<command>build --for java --src srv1</command>
<command>deploy db srv1 --to h2 --dry &gt;"${project.basedir}/src/main/resources/schema.sql"
</command>
</commands>

srv2/pom.xml
<commands>
<command>build --for java --src srv2</command>
<command>deploy db srv2 --to h2 --dry &gt;"${project.basedir}/src/main/resources/schema.sql"</command>
</commands>

Use the below command to clean install:
mvn clean install

For each module use:
mvn clean install -pl srv1 -am
mvn clean install -pl srv2 -am

Add the following in the .cdsrc.json
{
"requires": {
"multitenancy": true
},
"build": {
"target": ".",
"tasks": [
{
"for": "java",
"src": "srv1",
"options": {
"model": [
"db",
"srv1",
"app"
]
}
},
{
"for": "java",
"src": "srv2",
"options": {
"model": [
"db",
"srv2",
"app"
]
}
},
{
"for": "mtx-sidecar"
},
{
"for": "hana",
"src": "db",
"options": {
"model": [
"db",
"srv1",
"srv2",
"app"
]
}
}
]
},
"hana": {
"deploy-format": "hdbtable"
}
}

Note: To create a multi-tenant application add mtxs to the project and add the same .cdsrc.json in /mtx/sidecar

Add the srv2 module in mta.yaml:
# --------------------- SERVER MODULE ------------------------
- name: mis-srv2
# ----------------------------------------------------------
deployed-after:
- mis-mtx-sidecar
type: java
path: srv2
properties:
SPRING_PROFILES_ACTIVE: cloud
CDS_MULTITENANCY_APPUI_TENANTSEPARATOR: "-"
JBP_CONFIG_COMPONENTS: "jres: ['com.sap.xs.java.buildpack.jre.SAPMachineJRE']"
JBP_CONFIG_SAP_MACHINE_JRE: "{ use_offline_repository: false, version: 17.+ }"
parameters:
memory: 2048M
disk-quota: 1024M
buildpack: sap_java_buildpack
routes:
- route: "${app-prefix}-${service_route}.${default-domain-host}"
build-parameters:
builder: custom
commands: [mvn clean package]
build-result: "target/*-exec.[wj]ar"
provides:
- name: srv-api2 # required by consumers of CAP services (e.g. approuter)
properties:
srv-url: "${protocol}://${app-prefix}-${service_route}.${default-domain-host}"
requires:
- name: mis-uaa
- name: mis-service-manager
- name: mis-saas-registry
- name: mtx-sidecar
properties:
CDS_MULTITENANCY_MTXS_ENABLED: true
CDS_MULTITENANCY_SIDECAR_URL: ~{url}
- name: approuter_api
properties:
CDS_MULTITENANCY_APPUI_URL: ~{url}

Add the dependencies in mtx-sidecar,app-router and saas-registry in mta.yaml for both the modules:
 # ----------------- MTX-SIDECAR MODULE -----------------------
- name: mis-mtx-sidecar
# ----------------------------------------------------------
type: nodejs
path: mtx/sidecar
build-parameters:
builder: custom
build-result: gen
commands:
- npm run build
requires:
- name: mis-srv1
- name: mis-srv2
parameters:
memory: 512M
disk-quota: 1024M
requires:
- name: mis-uaa
- name: mis-service-manager
provides:
- name: mtx-sidecar
properties:
url: ${default-url}

# --------------------- APPROUTER MODULE ---------------------
- name: mis-approuter
# ----------------------------------------------------------
type: approuter.nodejs
path: mis-approuter
requires:
- name: mis-html-repo-runtime
- name: mis-uaa
- name: mis-saas-registry
- name: srv-api1
- name: srv-api2
parameters:
disk-quota: 256M
memory: 256M
keep-existing-routes: true
routes:
- route: "${app-prefix}-${approuter_route}.${default-domain-host}"
provides:
- name: approuter_api
properties:
url: "${protocol}://${app-prefix}-${approuter_route}.${default-domain-host}"
properties:
TENANT_HOST_PATTERN: "^(.*)-${app-prefix}-${approuter_route}.${default-domain-host}"
destinations:
- name: backend
url: "~{srv-api1/srv-url}"
- name: backend2
url: "~{srv-api2/srv-url}"
forwardAuthToken: true

- name: mis-saas-registry
type: org.cloudfoundry.managed-service
parameters:
service: saas-registry
service-plan: application
requires:
- name: srv-api2

Note: saas-registry should be binded only to one of the modules. In this example we have binded it to mis-srv2

Build the application with the command:
mbt build -t gen --mtar mta.tar

Individual modules can be build using mbt :
mbt module-build -m=mis-srv2 -t gen --mtar mta.tar
mbt module-build -m=mis-srv1 -t gen --mtar mta.tar

Advantages of multi-modular:

  • Loosely coupled business logics

  • Separated code logics

  • Lesser conflicts with code merges

  • Easier to test

  • Need not deploy all the modules for any individual business logic changes


 

Co-Author: piyush.ranjan@sap.com