diff --git a/guides/deployment/microservices.md b/guides/deployment/microservices.md index 0f7215502..31dfd7d9c 100644 --- a/guides/deployment/microservices.md +++ b/guides/deployment/microservices.md @@ -37,7 +37,8 @@ This guide describes a way to manage development and deployment via *[monorepos] 2. Add the previously mentioned projects as `git` submodules: - ```sh + ::: code-group + ```sh [Node.js] git init git submodule add https://github.com/capire/bookstore git submodule add https://github.com/capire/reviews @@ -47,6 +48,17 @@ This guide describes a way to manage development and deployment via *[monorepos] git submodule add https://github.com/capire/data-viewer git submodule update --init ``` + ```sh [Java] + git init + git submodule add https://github.com/capire/bookstore-java + git submodule add https://github.com/capire/reviews-java + git submodule add https://github.com/capire/orders-java + git submodule add https://github.com/capire/common-java + git submodule add https://github.com/capire/bookshop-java + git submodule add https://github.com/capire/data-viewer-java + git submodule update --init + ``` + ::: Add a _.gitignore_ file with the following content: ```txt @@ -55,20 +67,21 @@ This guide describes a way to manage development and deployment via *[monorepos] ``` > The outcome of this looks and behaves exactly as the monorepo layout in *[cap/samples](https://github.com/capire/samples)*, so we can exercise the subsequent steps in there... + 3. Test-drive locally: - ```sh + + ::: code-group + ```sh [Node.js] npm install - ``` - - ```sh cds w bookshop ``` - - ```sh - cds w bookstore + ```sh [Java] + npm install + cd bookstore && npm start ``` + ::: - Each microservice can be started independently. If you start each microservice, one after the other in a different terminal, the connection is already established. + In Node.js, each microservice can be started independently. If you start each microservice, one after the other in a different terminal, the connection is already established. [Learn more about Automatic Bindings by `cds watch`](../extensibility/composition#bindings-via-cds-watch){.learn-more} @@ -77,7 +90,8 @@ This guide describes a way to manage development and deployment via *[monorepos] The project structure used here is as follows: -```txt +::: code-group +```txt [Node.js] / ├─ bookstore/ ├─ orders/ @@ -85,6 +99,14 @@ The project structure used here is as follows: ├─ ... └─ package.json ``` +```txt [Java] +/ +├─ bookstore-java/ +├─ orders-java/ +├─ reviews-java/ +├─ ... +└─ package.json +``` The individual services (`bookstore`, `reviews`, `orders`) can be one of the following: * folders, committed directly to the root project @@ -208,7 +230,9 @@ This section is about how to deploy all 3+1 projects at once with a common _mta. ![component diagram with synchronous and event communication for orders](./assets/microservices/bookstore.excalidraw.svg) -[@capire/samples](https://github.com/capire/samples#readme) already has an all-in-one deployment implemented. Similar steps are necessary to convert projects with multiple CAP applications into a shared database deployment. +For Node.js, [@capire/samples](https://github.com/capire/samples#readme) already has an all-in-one deployment implemented. Similar steps are necessary to convert projects with multiple CAP applications into a shared database deployment. + +TODO For CAP Java, [@capire/samples-java](https://github.com/capire/samples-java#readme) already has an all-in-one deployment implemented. Similar steps are necessary to convert projects with multiple CAP applications into a shared database deployment. ### Deployment Descriptor @@ -258,8 +282,7 @@ build-parameters: ``` ::: - -::: info `cds build --ws` +::: info `cds build --ws` with Node.js If the CDS models of every NPM workspace contained in the monorepo should be considered, then instead of creating this `shared-db` folder, you can also use: ```shell cds build --for hana --production --ws @@ -269,8 +292,8 @@ The `--ws` aggregates all models in the NPM workspaces. In this walkthrough, we only include a subset of the CDS models in the deployment. ::: +::: details Node.js: Configure each app for cloud readiness -::: details Configure each app for cloud readiness The preceding steps only added configuration to the workspace root. Additionally add database configuration to each module that we want to deploy - bookstore, orders, and reviews: @@ -280,15 +303,21 @@ npm i @cap-js/hana --workspace bookstore npm i @cap-js/hana --workspace orders npm i @cap-js/hana --workspace reviews ``` + ::: +::: details CAP Java: Configure each app for cloud readiness + +For each project add the **cds-starter-cloudfoundry** [starter bundle](https://cap.cloud.sap/docs/java/developing-applications/building#starter-bundles). + +::: ### Applications Replace the MTA module for `samples-srv` with versions for each CAP service and adjust `name`, `path`, and `provides[0].name` to match the module name. Also change the `npm-ci` builder to the `npm` builder. ::: code-group -```yaml [mta.yaml] +```yaml [Node.js (mta.yaml)] modules: - name: bookstore-srv # [!code focus] type: nodejs @@ -345,9 +374,79 @@ modules: - name: samples-destination ... ``` +```yaml [Java (mta.yaml)] +modules: + + - name: bookstore-srv # [!code focus] + type: java + path: bookstore/srv # [!code focus] + parameters: + instances: 1 + buildpack: sap_java_buildpack_jakarta + properties: + SPRING_PROFILES_ACTIVE: cloud,sandbox + JBP_CONFIG_COMPONENTS: "jres: ['com.sap.xs.java.buildpack.jre.SAPMachineJRE']" + JBP_CONFIG_SAP_MACHINE_JRE: '{ version: 21.+ }' + build-parameters: + builder: custom + commands: + - mvn clean package -DskipTests=true --batch-mode + provides: # [!code focus] + - name: bookstore-api # [!code focus] + properties: + srv-url: ${default-url} + requires: + - name: samples-db + - name: samples-auth + - name: samples-messaging + - name: samples-destination + + - name: orders-srv # [!code focus] + type: java + path: orders/srv # [!code focus] + parameters: + instances: 1 + buildpack: sap_java_buildpack_jakarta + build-parameters: + builder: custom + commands: + - mvn clean package -DskipTests=true --batch-mode + build-result: target/*-exec.jar + provides: # [!code focus] + - name: orders-api # [!code focus] + properties: + srv-url: ${default-url} + requires: + - name: samples-db + - name: samples-auth + - name: samples-messaging + - name: samples-destination + + - name: reviews-srv # [!code focus] + type: java + path: reviews/srv # [!code focus] + parameters: + instances: 1 + buildpack: sap_java_buildpack_jakarta + build-parameters: + builder: custom + commands: + - mvn clean package -DskipTests=true --batch-mode + build-result: target/*-exec.jar + provides: # [!code focus] + - name: reviews-api # [!code focus] + properties: + srv-url: ${default-url} + requires: + - name: samples-db + - name: samples-auth + - name: samples-messaging + - name: samples-destination +... +``` ::: -Add build commands for each module to be deployed: +In Node.js, add build commands for each module to be prepared for deployment: ::: code-group ```yaml [mta.yaml] @@ -367,7 +466,6 @@ build-parameters: Note that we use the *--ws-pack* option for some modules. It's important for node modules referencing other repository-local node modules. ::: - ### Authentication Add [security configuration](../security/authorization#xsuaa-configuration) using the command: @@ -400,7 +498,7 @@ Add the admin role ``` ::: -::: details Configure each app for cloud readiness +::: details Node.js: Configure each app for cloud readiness Add NPM dependency `@sap/xssec`: ```shell @@ -414,6 +512,8 @@ npm i @sap/xssec --workspace reviews The messaging service is used to organize asynchronous communication between the CAP services. +#### In Node.js + ```shell cds add enterprise-messaging ``` @@ -499,6 +599,63 @@ Enable messaging for the modules that use it: ::: +#### In CAP Java + +Create a new file named event-mesh.json to store the configuration for enterprise messaging. Skip the `emname` and `namespace` properties, as these will be parameterized dynamically in the mta.yaml file: + +::: code-group +```json [event-mesh.json] +{ + "version": "1.1.0", + "emname": "samples-emname", // [!code --] + "version": "1.1.0", + "namespace": "default/samples/1", // [!code --] + "options": { + "management": true, + "messagingrest": true, + "messaging": true + }, + "rules": { + "topicRules": { + "publishFilter": [ + "*" + ], + "subscribeFilter": [ + "*" + ] + }, + "queueRules": { + "publishFilter": [ + "*" + ], + "subscribeFilter": [ + "*" + ] + } + }, + "authorities": [ + "$ACCEPT_GRANTED_AUTHORITIES" + ] +} +``` +::: + +Add messaging resource in mta.yaml with parametrized `emname` and `namespace` properties: + +::: code-group +```yaml [mta.yaml] +resources: + - name: samples-messaging + type: org.cloudfoundry.managed-service + parameters: + service: enterprise-messaging + service-plan: default + path: ./event-mesh.json + config: # [!code ++] + emname: bookstore-${org}-${space} # [!code ++] + namespace: cap/samples/${space} # [!code ++] +``` +::: ### Destinations @@ -551,7 +708,7 @@ modules: Use the destinations in the bookstore application: ::: code-group -```yaml [mta.yaml] +```yaml [Node.js (mta.yaml)] modules: - name: bookstore-srv ... @@ -559,9 +716,27 @@ modules: cds_requires_ReviewsService_credentials: {"destination": "reviews-dest","path": "/reviews"} # [!code ++] cds_requires_OrdersService_credentials: {"destination": "orders-dest","path": "/odata/v4/orders"} # [!code ++] ``` +```yaml [Java (bookstore/srv/src/main/resources/application.yaml)] +cds: + odataV4.endpoint.path: / + messaging.services: + samples-messaging: + kind: enterprise-messaging + remote.services: # [!code ++] + OrdersService: # [!code ++] + type: "odata-v4" # [!code ++] + http: # [!code ++] + suffix: "/odata/v4" # [!code ++] + destination: # [!code ++] + name: "orders-dest" # [!code ++] + ReviewsService: # [!code ++] + type: "odata-v4" # [!code ++] + destination: # [!code ++] + name: "reviews-dest" # [!code ++] +``` ::: -::: details Configure each app for cloud readiness +::: details Node.js: Configure each app for cloud readiness Add `@sap-cloud-sdk/http-client` and `@sap-cloud-sdk/resilience` for each module utilizing the destinations: @@ -571,6 +746,30 @@ npm i @sap-cloud-sdk/resilience --workspace bookstore ``` ::: +::: details CAP Java: Configure each app for cloud readiness + +To access remote OData services, you need to add a dependency to the *cds-feature-remote-odata* [application plugin](https://cap.cloud.sap/docs/java/developing-applications/building#standard-modules) and provide the latest available version. Additionally, to retrieve destination configurations using the destination service, you must include a *com.sap.cloud.sdk.cloudplatform* dependency with artifact ID *scp-cf*, as described in the following steps: [Cloud SDK Integration](https://cap.cloud.sap/docs/java/cqn-services/remote-services#cloud-sdk-dependencies). + +::: code-group +```xml [bookstore/srv/pom.xml] +... + +... + + com.sap.cds + cds-feature-remote-odata + runtime + 4.0.2 + + + + com.sap.cloud.sdk.cloudplatform + scp-cf + +... +``` +::: + ### Approuter Add [approuter configuration](../deployment/to-cf#add-app-router) using the command: