Skip to content
239 changes: 218 additions & 21 deletions guides/deployment/microservices.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider improving clarity by specifying what "previously mentioned projects" refers to. Since this appears to be step 2, it would be helpful to reference step 1 or provide more context.

Suggestion:

2. Add the projects mentioned in step 1 as `git` submodules:


```sh
::: code-group
```sh [Node.js]
Comment on lines +40 to +41
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a brief explanation of what code groups are and why they're being used here to help readers understand the new structure.

git init
git submodule add https://github.com/capire/bookstore
git submodule add https://github.com/capire/reviews
Expand All @@ -47,28 +48,38 @@ 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When will those be available? Asking to make sure we don't merge this PR before

```
:::

Add a _.gitignore_ file with the following content:
```txt
node_modules
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...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra blank line to maintain consistent spacing throughout the document.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra blank line to maintain consistent spacing throughout the document.

3. Test-drive locally:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line before the numbered list item for better readability and consistency with markdown formatting.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line before the numbered list item for better readability and consistency with markdown formatting.

```sh

Comment on lines 69 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after step 3 for consistent formatting with other numbered steps in the document.

Comment on lines 69 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after step 3 for better readability and consistency with the document structure.

::: 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace "In Node.js," with "For Node.js," to maintain consistency with the Java section that follows and improve clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence structure can be improved for better clarity and flow.

Suggestion:

In Node.js, you can start each microservice independently. When you start each microservice one after the other in different terminals, the connection is already established.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence structure can be improved for clarity. Consider revising to: "In Node.js, you can start each microservice independently. When you start each microservice one after the other in different terminals, the connection is automatically established."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence structure is awkward. Consider revising to: "In Node.js, you can start each microservice independently. When you start each microservice one after the other in different terminals, the connection is automatically established."


[Learn more about Automatic Bindings by `cds watch`](../extensibility/composition#bindings-via-cds-watch){.learn-more}

Expand All @@ -77,14 +88,23 @@ 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]
<PROJECT-ROOT>/
├─ bookstore/
├─ orders/
├─ reviews/
├─ ...
└─ package.json
```
```txt [Java]
<PROJECT-ROOT>/
├─ 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
Expand Down Expand Up @@ -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.
Comment on lines +231 to +233
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider improving the sentence structure for better readability and consistency.

Suggestion:

For Node.js, [@capire/samples](https://github.com/capire/samples#readme) already has an all-in-one deployment implemented. You need similar steps 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. You need similar steps to convert projects with multiple CAP applications into a shared database deployment.


### Deployment Descriptor

Expand Down Expand Up @@ -258,8 +280,7 @@ build-parameters:
```
:::


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra blank line to maintain consistent spacing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra blank line to maintain consistent spacing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra blank line to maintain consistent spacing.

::: 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
Expand All @@ -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:
Expand All @@ -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
```

:::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after the details block for better readability.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after the closing ::: for better visual separation between sections.


::: details CAP Java: Configure each app for cloud readiness
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after the :::details directive for better readability and consistency with other sections.


For each project add the **cds-starter-cloudfoundry** [starter bundle](https://cap.cloud.sap/docs/java/developing-applications/building#starter-bundles).

:::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra blank line to maintain consistent spacing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after this line for consistency with the Node.js section above.


### 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
Expand Down Expand Up @@ -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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change "In Node.js, add" to "For Node.js, add" to maintain consistency with the terminology used throughout the document.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence structure can be improved for better clarity and to use active voice.

Suggestion:

In Node.js, add build commands for each module to prepare it for deployment:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve clarity by revising to: "Add build commands for each module to prepare it for deployment:" This uses active voice and present tense as required.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence is unclear and uses passive voice. Consider revising to: "Add build commands to prepare each module for deployment:"


::: code-group
```yaml [mta.yaml]
Expand All @@ -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.
:::


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra blank line to maintain consistent spacing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra blank line to maintain consistent spacing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra blank line to maintain consistent spacing.

### Authentication

Add [security configuration](../security/authorization#xsuaa-configuration) using the command:
Expand Down Expand Up @@ -400,7 +496,7 @@ Add the admin role
```
:::

::: details Configure each app for cloud readiness
::: details Node.js: Configure each app for cloud readiness
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after the :::details directive for consistency with other sections.

Add NPM dependency `@sap/xssec`:

```shell
Expand All @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add "For" before "Node.js" to maintain consistency with other section headings in the document.


```shell
cds add enterprise-messaging
```
Expand Down Expand Up @@ -499,6 +597,62 @@ Enable messaging for the modules that use it:

:::

#### In CAP Java
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change "In CAP Java" to "For CAP Java" to maintain consistency with the Node.js section heading format.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after this heading for consistency with the Node.js section above.


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

Expand Down Expand Up @@ -551,17 +705,35 @@ modules:
Use the destinations in the bookstore application:

::: code-group
```yaml [mta.yaml]
```yaml [Node.js (mta.yaml)]
modules:
- name: bookstore-srv
...
properties: # [!code ++]
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:

Expand All @@ -571,6 +743,31 @@ npm i @sap-cloud-sdk/resilience --workspace bookstore
```
:::

::: details CAP Java: Configure each app for cloud readiness
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after the :::details directive for consistency with other sections.


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]
...
<dependencies>
...
<dependency>
<groupId>com.sap.cds</groupId>
<artifactId>cds-feature-remote-odata</artifactId>
<scope>runtime</scope>
<version>4.0.2</version>
</dependency>

<dependency>
<groupId>com.sap.cloud.sdk.cloudplatform</groupId>
<artifactId>scp-cf</artifactId>
</dependency>
...
```

:::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after the details block for better readability.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after this line for consistency with other sections.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank line after the closing ::: for better visual separation between sections.


### App Router

Add _App Router_ configuration using the command:
Expand Down
Loading