Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Optimizing Push Framework for the Web: Use of Websocket, SSL, Json, AngularJs and MySQL

4.79/5 (16 votes)
29 Nov 2014CPOL8 min read 40.8K   1.5K  
Websocket, SSL, Json, MySQL are all combined together with Push Framework to produce a C++ server that interacts with an Angularjs web front-end. The application shows the ease of implementing CRUD.

Image 1

Introduction

Using C++ as backend to a Web application may sound like a strange way to do things today. In this article I will show you a combination of technologies that will make you think otherwise. By demo-ing the implementation of some of common scenarios, the reader can judge the complexity of extending this to a real world case application.

Goal

Let's define our goal here. First we ask: what are the common scenarios that developers face to implement ?

The answer must be easy:

  • A list of item types T1, T2, .. have to be defined and persisted.
  • Given a type T, user wants the front end to display a list of available items 
  • The front end must provide a way to display a form that creates or edits an instance of a given type T
  • Given a UI, we need a way for the user to easily lookup for an item of a given type T. A common case of this is when a type T1 has an external relationship with a type T2, meaning that the editing of an instance of T1, involves the selection of an instance of T2.

Even if some would disagree on this answer, I believe, they would still agree that these are enough important scenarios for them to appreciate any easy and extensible way of their implementation. So let our goal be defined as proving it is easy to implement these scenarios.

AngularJs

There are too many devises and operating systems today. Web applications using HTML5 and Javascript are being the best answer to building a cross plateform front end. With the advent of new libraries like AngularJs, Javascript development is really starting to make sens. The demo-application that is developed here, will have its front end part coded using controls built using AngularJs.

 

Websocket

Websocket is a protocol on top of TCP that most browsers implement nowadays. It allows a Web page to open a full duplex TCP connection with a compliant server. It is important to note that this is a much more powerful idea than Ajax.

AngularJs + Websocket = ?

The combination of these two technologies makes it possible to create a desktop-grade UI , using most of interaction logic executing client-side, and all the data and commands flowing to a real time server that has nothing to do with the Web server through which application was accessed. In our demo here, the Web server merely servs to the download of assets from the application machine to the end user devise.

Push Framework

Push Framework will be used to build the server that will interact with the Front end part, by receiving commands and sending back data.

Version 3 has optimized the design in a way it is possible to:

  • Plug any protocol implementation. (Separation of protocol logic to a separate abstract library: protocol foundation)
  • Plug any number of protocols, vertically and horizontally:
    • A Push Framework- server can listen through different ports. A different stack of protocols can be specified for each port. That is horizontal direction.
    • For each port, we can plug different protocols as layers on top of each others: that is vertical direction.
  • Plug any type of serialization method regardless of protocol choice.

Building protocols for Push Framework

Before we build the server application, we need to solve 3 problems. First, since Javscript will open up a Websocket connection, we need the server to be able to decode this protocol. We therefore need a protocol layer implementation of Websocket. Second, many will need a secured connection by means of TLS. We therefore need to have a layer implementation of TLS. Third, since Json is the default, integrated serialization method for Javascript, we need the server to expect data structured in that way. Therefore we need a a Json serialization implementation.

MySQL

This server is a good choice especially for those who want to embark into a new project and dont to risk money in an expensive Oracle or SQL Server license. We will use MySQL++ library to easily communicate with the server. This library also has implementation for connection pools which is great for application speed.

DAO, DTO, and server-side pagination

MySQL++ library helps a lot reduce the complexity of interacting with MySQL default API to send SQL queries and retrieve data after query execution. However many people today got used to persistance framework that do all the job of interacting with the DBMS automatically. Since there is no such frameworks in C++, this article uses the approach of code generation:

  • Using a generator that is supplied, you connect to an existing MySQL database and select a SQL Table.
  • The generator creates .h and .cpp files containing C++ class that represents your DAO. Say, you have a table called Person. You get a C++ class called Person deriving from a base object called BaseDAO. The class contains all the table fields in form of attributes. It also contains getters and setters and implement all virtual logic for the following members in the base class to be possible:
    • bool SaveChanges();
    • bool GetFromDatabase(int _id);
    • void SerializeToJson(Json::Value& jsonObjVal);
    • void UpdateFromJson(Json::Value& jsonObjVal);
    • bool deleteFromDB(int id);
  • The C++ class has all logic to turn itself into a DTO that can be sent to the client.
  • A helper View class allows you to easily access SQL views. This is used to return a list of DTOs that can feed client grids or look-up controls with all paging logic executing server-side.

 

Let's run the application first

Let us make sure you are able to get the application code, compile it and run it successfully. 

  1. Unzip the package
  2. Optionally deploy the WebApp directory to a Webserver. This contains the Index.html that you can navigate to, or openup locally.
  3. Open Demo.sln solution file using Visual Studio 2012 (Demo.sln is found in Example directory)
  4. Compile the solution for Debug
  5. "Output" directory will contain the binaries after successful compilation.
  6. Now that the server application is built, before it can be started we need to setup a database.
  7. Download and setup MySQL server from Internet. Optionally download and setup MySQL Workbench to easily manage the server.
  8. The directory Database contains a sql script. Use the script to create the database along with views and tables and populate them with data.
  9. Before running DemoAngularJsServer.exe, modify DemoAngularJsServer.ini to reflect the database settings specific to your environent.
  10. Run the server. It will start listening on port 81.
  11. Open the WebApp starting page. You should see a Grid of items. 
  12. Select a row in the grid and click Edit. Use the Form to edit property of the item and hit Save.

Explaining what happens

  • When the page is opened, an AngularJs controller (HeaderCtrl) requests a Websocket connection with the server.
  • Two other controllers EmployeeListCtrl and CompanyListCtrl will make calls to retrieve list of items (employees and companies) and show them in their grids.
  • When a grid is initialized, or a header is sorted, or a grid page is clicked, a Javascript callback is made, supplying all options that allow server to access a SQL view and return a limited set of rows.
  • When 'Edit Selection' is clicked, the Id of the object of the grid row is sent to the server to get full details of the object
  • When the full details of the object are received, they are show in a web form.
  • Changing the fom, will change the Javascript object bound to it.
  • Clicking Save, will send the modified object to the C++ server, which prepares a DAO, updates it with changes found in the incoming Json object and calls SaveToDatabase which contains generated code that takes care of calling the database, executing an UPDATE statement.

The complexity of supporting new types.

When a new type is added, only the following steps need be done:

  1. Manually create a MySQL table for the new type.
  2. Execute MySQL.Codegen.exe, input the database information, the table name, and click Generate.
  3. Move the generated .h and .cpp class files to the C++ server project. Add them to list of project files.
  4. Modify AngularClient::getDAOByName so that it can support the new type. 
  5. Create a SQL view for the type if you need to show a list of items or do lookup in client side. If the type has external relationship with other types, the view may be improved by enriching the columns with columns from the external types. For example, each employee row has a companyId, but when displaying a list of employees we also show the company name.
  6. At this step, that is really all what is needed for server-side. Only two lines of coding to be manually written in Step 4 !
  7. Going to the client-side, add a new desired view plus controller, and link them with the application (mainly in app.js)
  8. To add similar behavior to what we have with existing types (Company and Employee), you can copy the files. All what really changes is the following:
    1. For the grid to work, when it makes a call to WebsocketService.getView, supply it with the proper SQL view name your created!
    2. For the form to work, bound your controls to exact same table fields names, then evrywhere the controller calls WebsocketService.getItem or WebsocketService.deleteItem, make sure to supply the proper type name !
  9. If the type has external relationships, you need to allow the user to set those relationships when editing a form. For that, look at the existing code for Employee Form: all is needed is 
    1. For editing, bind the relationship field to a typeahead control
    2. To display the name of the entity represented by the Id found in the edited/displayed object, do a lookup at start of controller to retrieve the external object and intialize the typeahead display text with the proper field.

From these steps, it is possible to judge how much effort is needed to implement all these standard scenarios.

History

This is currently the intial version of this article. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)