NodeJS and CQRS Based REST APIs Using ExpressJS SubApps

Before going on this post, i highly recommend to read first my last post about CQRS , this will give you how i am thinking about CQRS and the added value to build CQRS based REST APIs.

Implementation Steps

  1. Create Authorization Module
  2. Building two SubApps (1st for Commands and other for Queries)
  3. Handle the logging and Authorization
  4. Create App (Entry point) to consume the SubApps

If you are new in NodeJS sub apps – its is an ExpressJS way to extract part of your API functionality in separate JS Node and consume (use) it when ever you need.

lets start with the code …

1. Create Authorization Module

//  ./authorization-handler.js
function functionAuth(req,res,next)
{
     var auth = true; // Write Down Your Auth Logic Here
     if(!auth)
     {
          console.log('Non Authorized To Function.');
          res.status(403).send('Not Authorized');
     }
     else
          console.log('Authorized.');
}

function modelAuth(req,res)
{
     var auth = true; // Write Down Your Auth Logic Here
     if(!auth)
     {
          console.log('Non Authorized To Model.');
          throw ('Invalid Token');
     }
     else
          console.log('Authorized.');
     }

exports.modelAuth = modelAuth;
exports.functionAuth = functionAuth;

2. Building Sub App for Commands

//  ./commands.js (POST, PUT, DELETE)
const express= require('express');
const authhandler = require('./authorization-handler');
var app = new express();

app.on('mount', function (parent) {
  console.log('Commands API Mounted');
});

app.all('*',function(req,res,next){
  try{
    authhandler.modelAuth();
    next();
  }
  catch(ex)
  {
    res.status(403).send(ex)
  }
})
app.post('/get',authhandler.functionAuth,function(req,res,next)
{
  res.send('get command executed');
})

module.exports = app;

3. Building Sub App for Queries

//  ./queries.js
//Do the same as the commands for GET functions

4. Building the Entry Point

//  ./app.js
const express = require('express');
const authhandler = require('./authorization-handler');
const commands = require('./commands');
const queries = require('./queries');
var app = new express();

app.use('/commands',commands);
app.use('/queries',queries);

app.listen(7777,function(req,res){
  console.log('7777 Server Is Working ...');
});

And we have done 🙂

Advertisements

Introducing CQRS (Command Query Responsibility Segregation)

Dears,

If you are a Domain Driven or Micro-services based developer, you might be interested to build your coming API(s) in CQRS models instead of the current traditional CRUD approach.

First, based on Martin Fowler article about CQRS, Greg Young is the founder of this pattern, but honestly is don’t believe CQRS is a pattern at all, it is more simpler than that, the pattern is something solving a specific problem, but CQRS is not a solution for anything, it is a way to separate and elevate your code to be more expandable and easy to handle specially with complex domains.

What is CQRS

Its easy to figure out the target from the name (Command Query Responsibility Segregation) where you separate between the API Commands and Queries.

  • Commands (Changes the state of the object) [Post, Put, Delete] (e.g. Writes or Update on the DataSource)
  • Query (Never Changes the state of the object) [Get] (e.g. Selecting from DataSource)

and the first thing comes to your mind, yes its really important for code security !

I remember a project written in NodeJS where i elevated the CQRS models to be with different security token check.

1. Simply How It works ?

Define your domain (keep the business in mind)

Domain is always maps to business value, an independent and totally agnostic in terms of behavior, and we might talk about this later in separate post, but first remember that business separation is all you should care about.

Create two models (Command & Query)

Its kind of extra domain separation but not a sub-domain, as Commands and Queries give the domain its full behavior.

CQRS and Token Authorization

I am talking about API authorization where you just allow authorized requests to access specific API, and this could be on the Model Route or on the Function Route.

NodeJS (Model Level Authorization)

const express= require('express');
const authorizationHandler = require('/authorization-handler');
var app = new express();

app.all('*',function(req,res,next){
  try{
   authorizationHandler.authorizeModel();
   next();
  }
  catch(ex)
  {
    res.status(403).send(ex);
  }
});

app.get("/get/:id",function(req,res){
 res.send(/*What Ever ...*/);
});

app.post("/post",function(req,res){
 res.send(/*What Ever ...*/);
});

C# (Model Level Authorization)

[RoutePrefix("api/employee/{token}")]
[Authorize]
public class EmployeeController : ApiController
{
    [Route("get/{id}")]
    public async Task Get(int id, string token)
    {
          return Ok(/*What Ever*/);
    }
    [Route("post")]
    public async Task Post([FromBody] Employee employee, string token)
    {
          return Ok(/*What Ever*/);
    }
}

NodeJS (Function Level Authorization)

const express= require('express');
var app = new express();

app.all('*',function(req,res,next){
 /*No Authorization here ...*/
 next();
});

app.get("/get/:id",authorizationHandler.authorizeFunction,function(req,res,next){
 res.send(/*What Ever ...*/);
});

app.post("/post",authorizationHandler.authorizeFunction,function(req,res,next){
 res.send(/*What Ever ...*/);
});

C# (Function Level Authorization)

[RoutePrefix("api/employee/{token}")]
public class EmployeeController : ApiController
{
    [Route("get/{id}")]
    [Authorize]
    public async Task Get(int id, string token)
    {
          return Ok(/*What Ever*/);
    }
    [Route("post")]
    [Authorize]
    public async Task Post([FromBody] Employee employee, string token)
    {
          return Ok(/*What Ever*/);
    }
}

In CQRS, it will be a little different where you have to authorize on the Model Level to make sure the request accessing the Commands model is authorized to change the object state, and the authorization is less sensitive here. For this case in specific you can use my implementation for a simple NodeJS two levels authorization, where the primary Authorization will be on the model level (Mandatory) and second will be on the function level (Optional).

CQRS and Event Sourcing working together

If you are not following, Event Sourcing is a design approach to publish events instead of executing DataSource operations and a publisher will execute these events in order (if dependent) to the data source.

I wish you started to figure out how CQRS is very useful for Event Sourcing !

We will talk about this in future post in details because it deserves.

Thanks for now, try it by your self and make it a life style 😉

Regards,

Sameh Selem

Create your private team NuGet and manage your source code

Intro.

The major purpose from this post is to give simple and clear hands on how to create your first Nuget repository and publish Nugets to it to use in other projects, and indeed hands on how to build your project as a Nuget package.

As one of the products i am working on now, the arch. is a MicroService oriented which is perfect for the Product, but when we think more behind the scene , how can we organize the whole solution artifacts and components separately with respect to the fact to still have some common services to handle such a generic or shared logic.

Here i found to build our own solution NuGet repository is a suitable idea to handle the whole things instead of us.

How To start

  1. Define the common services, (e.g. ImageProcessing Service), Encryption Service, System Models or MicroService Models (usually these models is shared between the MicroServices).
  2. Define the Naming convention you will use later for (Nuget Name, Description, Author).

How to create a Nget packege for the progect ?

  1. Assuming you have a separate project performing a functionality to use later in various projects (e.g. ImageCompression Service).
  2. There are many ways to package your project as a Nuget, but in this case i will use an easy and stable way to  “Create a Nuget Package With Every Successful Build”.

Steps …

  1. In project (e.g. ImageCompression), install Nuget package from nuget.org with Id (CreateNewNuGetPackageFromProjectAfterEachBuild), you can do it by the Visual Studio Nuget Manager or directly from the Tools > Nuget Package Manager > Package Manager Console.
  2. Installing this Nuget will add a (_CreateNewNuGetPackage) folder in the project, (Config.ps1) is the file where you can customise to change the way the Nuget qill be created.
  3. If you build your project now, a .nupkg file will be created with AssemplyName and extra info about the build (e.g. Debug or Release, X86 or AllCPU or whatever …), read the coming points to figure out how to change the Nuget Info. and Name.
  4. And to control the Nuget Information (Name, Description, Author, Version), follow these points.
  5. Open the project (AssemblyInfo.cs) file inside (Properties), Setting the [AssemblyDescription] will set the Nuger Description,  Setting the [AssemblyCompany] will set the Nuget Author.
  6. Open (Config.ps1), find [$versionNumber = “”] at line 19, set the version number or keep it empty and it will use the default build version, find [$appendConfigurationAndPlatformToNuGetPackageFileName = $true] at line 50, keep it true and the Nuget name will contains the Platform and Configuration info (e.g. Comp.ImageCompression.1.0.0.0.Debug.AnyCPU.nupkg) or set to false and it will be shorter like (e.g. Comp.ImageCompression.1.0.0.0.nupkg)
  7. Now you have the  Nuget (.nupkg) and you are ready to publish.

 

Publish your Nuget

We are here talking about your private repository starting from (Local machine repository to cloud hosted repository).

Local Machine Repository

  1. Create a Directory at your local machine (e.g. c:\\MyNugetRepo) and push your .nupkg file(s) to it.
  2. from Visual Studio, open Tools > Nuget Package Manager > Package Manager Settings
  3. open from left menu, Nuget Package Manager > Package Source
  4. Click on the green (+) Btn. to add new source
  5. Write the source Name and Source to (c:\\MyNugetRepo)
  6. Click ok and now you have a new custom private local machine Nuget Source.

 

Site (Shared Repository)

I mean a shared Site (URL), either network on company IIS server or to cloud site to access from outside the network,. its all depends on your need.

  1. Create a new project of type (ASP.net Empty Web Application)
  2. Install the Nuget Package (Nuget.Server) by .net foundation  on this Application, this will re structure the whole app to be a Nuget Feed App.
  3. a (Packages) folder now created and ready to contain all your .nupkg(s)
  4. Publish the App to (IIS) or (Cloud based site) (e.g. AZURE app service)
  5. When publish done, open the site and the default page should be ibstructions for the Nuget(s) repository URL and also how to push new .nupkg, for me, you can push new Nuget package to this Repository by simply add the .nupkg to the (Packages) folder and re publish again.
  6. be noted that you will need to use the URL (e.g. http:// mysiterepo:2255/nuget) as the Repository Source.
  7. also note that ot might take few minutes until the package displayed in the list of available packages after installation.

 

More Info …

The (CreateNewNuGetPackageFromProjectAfterEachBuild) handles the dependencies from the installed packages, so ant project installed packages will be added to the project package dependencies.

Building a MicroService APIs using the GateWay Pattern

Intro.

I will assume that you know the theory of MicroServices, and i will assume that you need a hands on reference aid on how to build a Complete MicroService Based REST APIs utilizing the benefits of the concept and also simple enough to build over.

Values we seek from MicroService 

  1. Build as much independent raw functioning services fulfilling the whole domain functionality.

  2. Making sure that every Service is running and maintained separately without any crack due to another service defect.

  3. Providing a separate deployment ready services, the thing that will aid on managing the load upon certain service separately with MAX. cost control.

  4. Supporting any combination of workflows using the MicroServices without the need to change the Services implementations.

I use a GateWay for MicroServices communication

The alternative is “Point to Point” communication, where the services can communicate with each other for sake of certain workflow or dependencies, but the issue about this technique is that we are no fully satisfying the Services dependencies and highly coupling the services stability on each others, and further more the Point to Point configuration is a nightmare specially when we have many domains.

The Design Essentials

  1. Every MicroService represents a different domain with standalone and self concerned business logic.

  2. Every MicroService doesn’t has aware enough with the other MicroServices end points of even functionality, so MicroServices direct communication is totally prohibited.

  3. Every MicroService is a REST API with unique EndPoint and could be hosted separately with unique security configurations.

  4. GateWay is a REST API with unique EndPoint.

  5. GateWay is the only EndPoint exposed to the FrontEnd Applications, so Microservices are only accessible by the GateWay.

  6. GateWay is the the place to build specific business workflow using the different MicroServices.

  7. Finally, and i haven’t seen any one apply this role 100%, is to make sure that every MicroService using its own DataBase and DataModels with any need to data from other Services DataBases, this is perfect to keep improving you Design to fulfill this concept and to save the separation down to all layers.

Sample Generic Business Practice

We need to build a Microservices to handle a TimeSheet System functionality.

we will need the following MicroService:

  1. UserAPI (Host In http://ip:port/api)
    1. PostNewUser        http://ip:port/api/post
    2. PutExistUser         http://ip:port/api/put/id
    3. DeleteExistUser   http://ip:port/api/delete/id
    4. GetAllUsers           http://ip:port/api/get
    5. GetUserById          http://ip:port/api/get/id
  2. MessagingAPI (Host In http://ip:port/api)
    1. GetAllMessages
    2. PostMessage
    3. DeleteMessage
    4. PostReply
  3. VacationAPI
    1. PostNewVacation
    2. DeleteNewVacation
    3. GetAllVacations
    4. PutExistVacation
  4. TimesheetAPI
    1. PostNewTimeSheet
    2. PutExistTimeSheet
    3. GetAllTimeSheets
  5. ReportingAPI
    1. GetReportDataById
  6. ProjectAPI
    1. PostNewProject
    2. PutExistProject
    3. DeleteProject
    4. GetAllProjects
    5. GetProjectById
    6. AddUserToProject

Now, we have 6 Separate and independent MicroServices hosted separately in different endpoints (ip/port).

Now we need to build another REST API represents the GateWay handelling the business Workflows to call from the FrontEnd Application (DeskTop APP., Web. APP. , Mobile, another Service , …etc).

 

e.g. Build GateWay REST function to Create Project and Add all users to it.

Steps In GateWay :

  1. Create Project by calling the ProjectAPI function PostNewProject

  2. Get All User by calling the  UserAPI function GetAllUsers

  3. Enumerate on the Users and Call The ProjectAPI function AddUserToProject.

  4. Return Operation Status

This Function should be a Post function expects [From Request Body] an object of Project, and the GateWay function should respond with Status (200, 404, 400, 500, …etc) according to how you handle the API errors.

so at the end , the FrontEnd application communicates with an API like http://gatewayip:port/api/postprojecttoeveryone

Important Notes

  1. The Microservices changes cadence should be minimal as it provides a row fundamental CRUD operations over specifuc business model.

  2. Every business Application with different requirements require New GateWay and not new MicroServices.

  3. Exception Handling and Error Pulling should be in a way to stop the technical inner exception on the layer of GateWay and Log It, and send Friendly helpful messages with Error Code as a GateWay responce.