SCP Cloud Foundry – Playing around with Node.js, MongoDB and UI5
- Create the Cloud Foundry based Node.js application structure
- Create a MongoDB service instance and connect to it
- Create an API layer
- Add a presentation layer using OpenUI5
- Deploy the application to the Cloud Foundry instance
After playing around with the available SCP Cloud Foundry demos based on Java (SAP Content Platform Tutorials) I was interested how to use Node.js and especially how to connect to a MongoDB Service instance with Node.js. For testing reasons I put a simple OpenUI5 application on top which consumes the data from the MongoDB using an API exposed via Express. So because of the usage of OpenUI5 it is not a classical MEAN stack application, but the principles are the same. An inoffical name used for such a scenario is NEMO (Node.js – Express – MongoDB – OpenUI5). Disclaimer: The following described points are not “high sophisticated” implementations, especially the API and UI5 part. They are just for testing reasons created. The main goal was to find out how the information about the MongoDB service instance(s) can be accessed and used within a Node.js application and how the connection to the MongoDB service instance can be established.
To be able to do the implementation steps some prerequisites have to be fullfilled.
First of all a SCP Cloud Foundry trial instance has to be created like described here.
To inteact with the Cloud Foundry instance via command line the Cloud Foundry CLI has to be installed on the local machine and the connection to the instance has to be established using the commands “cf api” and “cf logon”. All details are described here and here. The result should look like following:
On the local machine Node.js including the Node Package Manager needs to be installed. Follow the instructions on https://nodejs.org for that. If you are in a corporate network please consider to set the proxy settings for npm (https://docs.npmjs.com/misc/config).
To be able to test against a MongoDB instance on the local machine, MongoDB needs to be installed (https://www.mongodb.com/download-center?jmp=nav#community).
Create the Cloud Foundry based Node.js application structure
The package.json file
In the obligatory “package.json” file the name of the application, the required dependencies to npm packages and the node engine to be used are configured.
As node engine 6.2.1 is used which is supported by the Node.js Cloud Foundry buildpack in version 1.5.15 (Release v1.5.15 · cloudfoundry/nodejs-buildpack · GitHub). What version of the buildpack is available on the Cloud Foundry instance can be determined using command
The output of the command displays all available buildpacks including the version information in the file name.
The npm packages which are used as dependencies in this demo are:
They can be installed using command
npm install –save dev express body-parser mongoose cfenv path
Details, why they are necessary and how they are used, are described in the following paragraphs.
Finally the package.json file looks like following (version numbers of dependencies can be different depending on the point of time installing them):
The application manifest
In the application manifest file “manifest.yml”, information about the Node.js application and Cloud Foundry are described. The information is used by the “cf push” command for setting up the environment when the application is deployed to the Cloud Foundry instance. Later information will be added for the MongoDB service consumption.
Following information is provided in the file:
- name: The name of the application.
- buildpack: The name of the Node.js buildpack determined before with command “cf buildpacks”. It is also possible to reference the buildpack sources on GitHub. By default an auto determination of the buildpack is done if the buildpack information is missing in the application manifest. But from my point of view it is clearer to specify it in the application manifest.
- command: Node.js applications needs a start command to start the application. In the example “node app.js” is called which executes the JS code in a file “app.js” which is described later. The command is executed automatically after the application is successfully deployed to the Cloud Foundry instance.
- memory: Definition of the RAM available for the application. For the demo 128 MB are used.
- disk_quota: Definition of the disk space available for the application. For the demo 128 MB are used.
- host: Host information for the application which is used in the URL which makes the application accessible.
In the application root folder the folders “server” and “client” are created to separate the server/client logic from the beginning. Additionally a “.cfignore” file is created which contains all folders/files which have to be ignored by the “cf push” command. That means all files/folders listed in that file are not uploaded to the Cloud Foundry instance. For instance the “node_modules” folder can be excluded from the upload because the step to prepare the environment downloads the npm packages defined in the package.json file. For the demo case the sources are stored in a Git repository, therefore also a classic “.gitignore” file exists. Following you can see the initial application structure and the content of file “app.js” which contains the JS code executed after the successful upload/build of the application to the Cloud Foundry instance. At the moment the coding in the file just creates an Express instance, adds the body-parser middleware to process URL parameters and JSON bodies (for the later defined API) and starts a web server.
Create a MongoDB service instance and connect to it
Create a MongoDB service instance
MongoDB is available as service in the SCP CF environment. To display the available services the command
has to be executed. This produces following result.
To create an instance of the MongoDB service the command
cf create-service mongodb v3.0-container mongodb-nemo-t01-service
needs to be executed. “mongodb-nemo-t01-service” is the service instance name which is used to bind the service instance to the application.
shows the created service instance. The service instance can also be seen in the SCP CF cockpit “Service Instances” area.
To bind the service instance to the application, following “services” property using the name of the MongoDB service instance has to be added to the application manifest.
cfenv npm package – determine Cloud Foundry environment variables
The Cloud Foundry environment provides several environment variables which can be used in Node.js. For instance there is the environment variable VCAP_SERVICES which provides in that demo case information about the bound MongoDB service instance, e.g. the connection URI. The npm package cfenv (which was already added as dependency at the beginning) provides functionality which parses the information out of the environment variables, so that a developer has not to do it by himself. In addition the object created by the package provides also information if the application is running in a Cloud Foundry environment or locally. Depending on that, information is provided, like the PORT information, set to useful values (also in a local environment).
In the “app.js” file the functionality of the cfenv package is added.
Connection to the MongoDB service instance using mongoose
The connection to the MongoDB is done using mongoose which allows an easy object modeling in JS.
First a file “/server/db/mongo-connect.js” is created which coding establishes the connection to the MongoDB using the information provided by the cfenv object. As it can be seen in the coding it is checked if the application is running in a “local” mode. In that case the connection is done to a local running MongoDB “test”. So the application can also be tested locally with MongoDB.
In the “app.js” file the function exported by the “mongo-connect.js” file is called, passing the object created by the cfenv functionality. With that the connection to the MongoDB is established, but so far really nothing more is done.
Create an API layer
In that step a little User API is created which enables to create/read/update/delete users. Of course there exists API frameworks for Node.js (for instance loopback), but for demo purpuses this is done in a simple way from scratch.
First the moongoose schema and model are created in a file “/server/db/models/user.js”. The schema definition defines the fields the resulting MongoDB collection will get. The Node.js application interacts via the exported model with the collection.
In a file “/server/api/users/users.js” the previous created mongoose model is imported and the Express routes are defined. “oApp.get(‘/api/user’, …” for instance defines that via the URL “/api/user” all users can be determined. The coding for the create/update/delete functionalities can be found in the Git repository which is linked in the “Resources” paragraph.
That the routes are evaluated by the Express application, the function exported by the file has to be called in the “app.js” file passing the Express application object.
Starting the application with command “node app.js” allows to test the API locally. Two data records inserted with Postman using the API will return following by calling the URL “http://<host>:<port>/api/user”.
Add a presentation layer using OpenUI5
To be able to test the API also with a “real” frontend and not just via Postman or some other tool a simple OpenUI5 application is created. I don’t describe the details of the application here (it can be seen in the Git repository), but just the necessary steps to integrate it in the Express application. At time of writing this the beta version of OpenUI5 1.40 is used for that demo. The application provides a view which allows to display all users, to delete them and to add new ones. In addition an additional view is integrated which displays some information about the application (e.g. the values of the environment variable VCAP_SERVICES described above). The API for that can be found in the Git repository too. The access to the API layer defined previously is done using a UI5 JSONModel to read the data and jQuery AJAX requests to create and delete data.
In the folder “/client/public/webapp” the sources of the OpenUI5 application are stored. An “index.html” file is available which instantiates the OpenUI5 component and displays it in a component container.
File “/client/routes/routes.js” exports a function which adds a route to the Express application. Calling “http(s)://<host>:<port>/” will send the index.html file to the caller.
In the “app.js” file the function exported by “routes.js” file has to be called to register the route. In addition the “express.static” middleware is added to the express application which defines the OpenUI5 webapp folder as folder for static resources. So each file of the single page application can be loaded.
Testing the application locally produces following result.
Checking the MongoDB collection records on the console shows that the data is really available in the local MongoDB.
Deploy the application to the Cloud Foundry instance
So far the application was only tested on the local machine. Now it is time to deploy the application to the Cloud Foundry instance using command
executed in the application root folder where the application manifest file is available.
The log shows different information regarding the deployment steps and finally reports that the application is successfully started and running.
Afterwards the application information can also be found in the SCP CF cockpit.
Executing the application route URL displayed on the page opens the application.
The sources used above (and a little bit more) can be found at GitHub – pfefferf/hcp-cf-nemo-t01. If you wanna deploy the app to your on SCP CF instance, just change the host information in the application manifest to something unique.
With the above described steps I hope I could explain a little bit how easy it is to create a Node.js application connected to a MongoDB service instance and putting a simple OpenUI5 app on top. The options what to use from the Node.js universe and how to use it a nearly limitless within that Cloud Foundry based environment.