How to use MongoDB in combination with SAP CAP?

If you know the SAP Cloud Application Programming model (short SAP CAP), you may already be familiar with the OData interface and the CDS entities, which you can create with it. This is a cool definition framework, where you simply define the properties and associations to business objects and later create from it a real HTTP service, which can be used for a various of applications.

Now the downside of this framework is sometimes, that you need to subscribe to the SAP HANA Cloud service or bring your own SAP HANA system to store your data. This is a fair service for large companies or companies already using SAP as an ERP.

The idea

I recently also got familiar with MongoDB and the corresponding cloud service MongoDB Atlas, which provides managed MongoDB deployments. And it also offers you the possibility to run a free instance with 512MB storage to get started.

This brought me to an idea to connect the useful SAP CAP framework together with another database technology to build a small example project. The implementation of the service can be completely customized with JavaScript, which we will use to save back and load data to MongoDB.

In the example above you see that the SAP CAP can be consumed primary by SAP Fiori (Elements) apps, as well as any REST consumer. This allows the flexibility to use the

Implementation: The CDS definition

First, we create an SAP CAP project, which can be done inside the SAP Business Application Studio or directly in VS Code with the corresponding extensions. How you can do that is described in many of SAP Learning Journeys, just google it, or follow this link.

Then we define a simple entity and expose it as service:

db/schema.cds

using {cuid} from '@sap/cds/common';

namespace db;

entity Movies : cuid {
    key ID          : UUID @readonly;
        title       : String;
        description : String;
        rating      : Integer;
}

srv/service.cds

using { db } from '../db/schema';

service MovieService {
    entity Movies as projection on db.Movies;
}

When we start our service with cds watch, now we see our service with the entity Movie running in the environment:

The running SAP CAP instance

Implementation: The CAP implementation

Now that we have defined our service, we are ready to implement the service. For that you need to note that we use TypeScript. That means also that you need to do some small tweaks on your project. These tweaks are described here in the official documentation.

Then we can install the library cap_mdb_handler from npm.

npm install cap_mdb_handler

This library does then complete handling of the later requests, which has been received by CAP and being forwarded to this library. This is also a manual step which have to be done later.

For that we adding a new file called srv/service.ts

import type { Request } from "@sap/cds/apis/services"
import cds = require('@sap/cds');
import MDBHandler from "cap_mdb_handler";

require('dotenv').config();

module.exports = cds.service.impl(async function () {
    const oHandler = new MDBHandler(process.env["MONGO_URL"], process.env["MONGO_DB"]);

    this.on('READ', '*', async (req : Request) => {
        return await oHandler.read(req);
    });

    this.on('CREATE', '*', async (req : Request) => {
        return await oHandler.create(req);
    });

    this.on('UPDATE', '*', async (req : Request) => {
        return await oHandler.update(req);
    });

    this.on('DELETE', '*', async (req : Request) => {
        return await oHandler.delete(req);
    });
});

This snippet above does the real CDS service implementation and registers the MongoDB handler at the beginning of the start of the service. It ensures the connection to the database, which has been provided by environment variables. Each time, an event has been fired like READ, CREATE, UPDATE or DELETE, this will be forward to the library. The result of the corresponding methods will be returned back to the service. The events just have to be registered once for a service and does work for all entites the same way. It will be automatically determinated, which entity has been called with which data and how to store or read it to/from the MongoDB.

To formerly run and deploy the application later, I recommend to check a sample package.json file. Checkout especially the highlighted parts:

{
  "name": "cap-mongodb",
  "version": "1.0.0",
  "description": "A CAP project using MongoDB as a database",
  "repository": "https://github.com/julianschmuckli/sap_cap_mongodb",
  "license": "UNLICENSED",
  "private": true,
  "dependencies": {
    "@sap/cds": "^7",
    "@sap/xssec": "^3.6.1",
    "@types/node": "*",
    "cap_mdb_handler": "^1.0.12",
    "dotenv": "^16.4.5",
    "express": "^4",
    "mongodb": "^6.3.0",
    "sqlite3": "^5.1.7",
    "typescript": ">=4.3.5"
  },
  "devDependencies": {
    "@cap-js/sqlite": "^1"
  },
  "scripts": {
    "start": "cds-serve",
    "build-and-deploy": "tsc & cds build --production && mbt build -t gen --mtar mta.tar && cf deploy gen/mta.tar",
    "watch": "cds-ts watch"
  },
  "cds": {
    "requires": {
      "db": {
        "kind": "sqlite",
        "credentials": {
          "database": ":memory:"
        }
      },
      "[production]": {
        "auth": "mocked"
      }
    }
  }
}

Another definition has to be done in the .env file in the root project folder. There, you have to define the

MONGO_URL=mongo+srv://.... # Your connection string
MONGO_DB=sap-cap-movies # Your database name

Now when we start the application again, we can see that the service implementation in the console log will now also be loaded.

You can see the srv/service.ts implementation has been loaded and the [mdb for cds] Mongo DB instance prepared has been shown.

Now when we use the CAP APIs, we now automatically have MongoDB as the data source, the SQLite in-memory database is still loaded, but not in use anymore.

MongoDB Atlas collection dashboard

Now you are ready to use your CAP project with a MongoDB as primary database.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Ads Blocker Image Powered by Code Help Pro

Ad blocker detected

We have detected that you are using extensions to block ads. Please support us by disabling your ad blocker.

Powered By
100% Free SEO Tools - Tool Kits PRO