diff --git a/guides/deployment/microservices.md b/guides/deployment/microservices.md index 75a2b746e..5525d1304 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 + git submodule add https://github.com/capire/bookshop-java + git submodule add https://github.com/capire/data-viewer + git submodule update --init + ``` + ::: Add a _.gitignore_ file with the following content: ```txt @@ -54,21 +66,20 @@ This guide describes a way to manage development and deployment via *[monorepos] gen ``` > 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 +88,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 +97,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 +228,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. + +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 +280,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 +290,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 +301,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 +372,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 +464,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 +496,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 +510,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 +597,62 @@ 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 the mta.yaml file parameterizes these dynamically: + +::: code-group +```json [event-mesh.json] +{ + "version": "1.1.0", + "emname": "samples-emname", // [!code --] + "namespace": "default/samples/1", // [!code --] + "options": { + "management": true, + "messagingrest": true, + "messaging": true + }, + "rules": { + "topicRules": { + "publishFilter": [ + "*" + ], + "subscribeFilter": [ + "*" + ] + }, + "queueRules": { + "publishFilter": [ + "*" + ], + "subscribeFilter": [ + "*" + ] + } + }, + "authorities": [ + "$ACCEPT_GRANTED_AUTHORITIES" + ] +} +``` +::: + +Add a messaging resource in mta.yaml with parameterized `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 +705,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 +713,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 +743,31 @@ npm i @sap-cloud-sdk/resilience --workspace bookstore ``` ::: +::: details CAP Java: Configure each app for cloud readiness + +To access remote OData services, 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, include a *com.sap.cloud.sdk.cloudplatform* dependency with the *scp-cf* artifact ID, as described in [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 + +... +``` + +::: + ### App Router Add _App Router_ configuration using the command: