Getting Started

Installation


                        From the command line:

                        Run npm install -g aquajs-cli
                        cd into working directory
                        Run aqua create (projectname) to create new microservice

                        Options as argument for aqua create :
                            --workflow to create workflow project
                            --dir  to specify output directory
                            --scheduler to create a scheduler-server
                            --basic to generate empty schema

                        Run aqua validate  to verify that the yaml file in the 'schema' directory is valid before scaffolding the API.

                        The schema can (and should) be customized before scaffolding.

                        Run aqua scaffold  to scaffold API and models files based on any valid yaml files in the 'schema' directory.

                        (If project is a workflow, cd into 'orchestrator' directory.)

                        Options:

                            --force to force update on existing project
                            --schema  to specify alternate path to schema files
                            --backup to create a backup of current service files

                        Run npm install to install dependencies (if not automatically installed during create)
                        Run aqua start to start node server
                        Or aqua apidoc to start server

                        open http://localhost:8080/apidoc to see the API doc .
                    

BluePrints

Like any good web framework, Aqua aims to reduce both the amount of code you write and the time it takes to get a functional app up and running. Blueprints are Aqua’s way of quickly generating API routesand actions based on your application design. Together, blueprint routes and blueprint actions constitute the blueprint API, the built-in logic that powers the RESTful JSON API you get every time you create a model and controller. Blueprints are great for prototyping, but they are also a powerful tool in production due to their ability to be overridden, protected, extended or disabled entirely. Aquajs available moduels are
  • aquajs
  • aquajs-error
  • aquajs-loadtest
  • aquajs-cli
  • aquajs-oracle
  • aquajs-logger
  • aquajs-soap
  • aquajs-mailer
  • aquajs-crypto
  • aquajs-scheduler-server
  • testutils
  • aquajs-scheduler
  • aquajs-swagger-ui
  • aquajs-workflow

Configuration

While Aquajs dutifully adheres to the philosophy of convention-over-configuration, it is important to understand how to customize those handy defaults from time to time. For almost every convention in Aquajs, there is an accompanying set of configuration options that allow you to adjust or override things to fit your needs. This section of the docs includes a complete reference of the configuration options available in Aquajs. Aquajs apps can be configured programmatically, by specifying environment variables or command-line arguments. Configuring the CLI

The default configuration for Aqua CLI requires access to the private registry via a .npmrc file in your home directory. To override these settings: Create a yaml (or json) file called .aquaconfig in the CLI directory. Users should not edit config.yaml directly. Configuration settings are loaded in the following order (later settings override earlier settings):

  • /config.yaml
  • /.aquaconfig (or aquaconfig)
  • <$HOME/%USERPROFILE%>/.aquaconfig (or aquaconfig)
NOTE: if .aquaconfig is not found, the CLI will check in the same location to see if aquaconfig exists. Ex: In .aquaconfig
  • commands:
  • create:
  • packages:
  • microservice: source: http://api.github.com/repos/aquajs/aquajs-microservice
  • workflow: source: /aqua/aquajs-workflow
  • github: token: With this custom configuration, the CLI create command will use the github repo when creating a new microservice,
    and copy the specified directory when creating a new workflow. NOTE: If using a github repo as the source, you must also provide an authorization token.
    For the time being, source url must follow the same format as above.


Controllers

In MVC framework C is for controller. A place to take user requests, bring data from the model and pass it back to the view.They often act as a middleman between your models and views. For many applications, the controllers will contain the bulk of your project’s business logic. Controllers process incoming requests, handle user input and interactions, and execute appropriate application logic.

A controller class typically calls a separate view component to generate the HTML markup for the request. The Controller class is responsible for the following processing stages: Locating the appropriate action method to call and validating that it can be called. Getting the values to use as the action method's arguments. Handling all errors that might occur during the execution of the action method.

                    module.exports = loginController;
                    loginController.login = function(req, res) {
                    $logger.info("Entered the  LoginController method : login");

                    var inputData = generateInputData(req);
                    $logger.debug("Entered the  LoginController method : getUserByUserKey with input data: %s", stringify(inputData));

                    loginValidationImpl.validateParams("login", schema, inputData, function(err) {
                    if (err && err !== null) {
                    $logger.error('login  validation error: %s', stringify(err)); // sends the  email with errors attached in case of error
                    loginControllerCallBack(err, null);
                    } else {
                    $logger.info("Input Parameter Validation Success for method: login");
                    loginServiceImpl.login(inputData, loginControllerCallBack);
                    }
                    });
                    

Routes

The most basic feature of any web application is the ability to interpret a request sent to a URL, then send back a response. In order to do this, your application has to be able to distinguish one URL from another.

Like most web frameworks, Aqua provides a router: a mechanism for mapping URLs to controllers and views. Routes are rules that tell Aquajs what to do when faced with an incoming request.

A controller class typically calls a separate view component to generate the HTML markup for the request. The Controller class is responsible for the following processing stages: Locating the appropriate action method to call and validating that it can be called. Getting the values to use as the action method's arguments. Handling all errors that might occur during the execution of the action method.

                            $app.use(constants.ECX_CONTEXT, loginRouter);
                            loginRouter.post(constants.ECX_HOSTED_URL, LoginController.login);
                            loginRouter.get(constants.ECX_HOSTED_USER_CHALLENGE_QUESTIONS_URL_GET,
                                LoginController.getUserChallengeQuestionAnswer);
                        

Models

Models simply provide a nice abstraction for your data. Instead of thinking in terms of "how do I write this inner join to get all the fields I need", models enable you to think in terms of "how are my application's objects related to each other, how do they interact and how can I get the data I need from them. Model objects are the parts of the application that implement the domain logic, also known as business logic. Domain logic handles the data that is passed between the database and the UI.

For example, in an inventory system, the model keeps track of the items in storage and the logic to determine whether an item is in stock. In addition, the model would be the part of the application that updates the database when an item is sold and shipped out of the warehouse. Often, the model also stores and retrieves model state in a database.

Persist model


                    var persist = require("persist");
                    var type = persist.type;

                    // define some model objects
                    Phone = persist.define("Phone", {
                    "number": type.STRING
                    });

                    Person = persist.define("Person", {
                    "name": type.STRING
                    }).hasMany(this.Phone);

                    persist.connect({
                    driver: 'sqlite3',
                    filename: 'test.db',
                    trace: true
                    }, function(err, connection) {
                    Person.using(connection).all(function(err, people) {
                    // people contains all the people
                    });
                    });


                    

waterline model


                    var persist = require("persist");
                    var type = persist.type;

                    // define some model objects
                    Phone = persist.define("Phone", {
                    "number": type.STRING
                    });

                    Person = persist.define("Person", {
                    "name": type.STRING
                    }).hasMany(this.Phone);

                    persist.connect({
                    driver: 'sqlite3',
                    filename: 'test.db',
                    trace: true
                    }, function(err, connection) {
                    Person.using(connection).all(function(err, people) {
                    // people contains all the people
                    });
                    });


                    

Schema

The Schema specification defines a set of files required to describe the rest API's. The files describing the RESTful API in accordance with the Swagger specification are represented as JSON objects and conform to the JSON standards. YAML, being a superset of JSON, can be used as well to represent a Swagger specification file.

The schema exposes two types of fields. Fixed fields, which have a declared name, and Patterned fields, which declare a regex pattern for the field name. Patterned fields can have multiple occurrences as long as each has a unique name.

Sample Schema

                     Sample Definition of .yml file:
                    resourcePath: /Sample-Example-Order_App
                    description: All about API
                    version: 1.0.0
                    target: microservice
                    host: localhost:8090
                    apis:
                    - path: /orders
                      operations:
                      - httpMethod: GET
                        summary: Get all the orders for a pizza order example
                        notes: Returns all orders of a pizza order example
                        responseClass: Orders
                        requestClass: Orders
                        nickname: getOrders
                        responseMessages:
                        - code: 200
                          message: "Expected response to a valid request"
                          responseModel: OrderAdd
                        - code: 400
                          message: "unexpected error"
                          responseModel: Status
                        consumes:
                        - text/json
                      - httpMethod: POST
                        summary: Add a new order
                        notes:  adds new pizza order
                        responseClass: OrderAdd
                        requestClass: Orders
                        nickname: postOrder
                        consumes:
                        - application/json
                        parameters:
                        - name: body
                          dataType: object
                          paramType: body
                          required: true
                          description: Order to be added
                    - path: /orders/{id}
                      operations:
                      - httpMethod: GET
                        summary: Get a particular pizza order by id
                        notes: Returns an pizza order with specified id
                        responseClass: Orders
                        requestClass: Orders
                        nickname: getOrderById
                        consumes:
                        - text/json
                        parameters:
                        - name: id
                          dataType: integer
                          paramType: path
                          required: true
                          description: Pizza Order Id to be fetched
                      - httpMethod: DELETE
                        summary: Delete the particular  pizza order by id
                        notes: Delete an pizza order with specified id
                        responseClass: Status
                        requestClass: Orders
                        nickname: deleteOrderById
                        consumes:
                        - text/json
                        parameters:
                        - name: id
                          dataType: integer
                          paramType: path
                          required: true
                          description: Order Id for pizza to be deleted
                      - httpMethod: PUT
                        summary: Update the particular pizza order by id
                        notes: updates an pizza order with specified id
                        responseClass: Orders
                        requestClass: Orders
                        nickname: updateOrderById
                        consumes:
                        - application/json
                        parameters:
                        - name: id
                          dataType: integer
                          paramType: path
                          required: true
                          description: Order Id for pizza  to be updated

                        - name: body
                          dataType: object
                          paramType: body
                          required: true
                          description: Order for pizza  to be updated
                    - path: /pizza/{id}
                      operations:
                      - httpMethod: GET
                        summary: Get the particular pizza type by id
                        notes: Returns a pizza type with specified id
                        responseClass: Pizza
                        requestClass: Pizza
                        nickname: getPizzaById
                        consumes:
                        - text/json
                        parameters:
                        - name: id
                          dataType: integer
                          paramType: path
                          required: true
                          description: pizza Oder Id to be fetched
                    - path: /pizza
                      operations:
                      - httpMethod: POST
                        summary: Add a new type of pizza
                        notes: adds a new type of pizza
                        responseClass: Pizza
                        requestClass: Pizza
                        nickname: postPizza
                        consumes:
                        - application/json
                        parameters:
                        - name: body
                          dataType: object
                          paramType: body
                          required: true
                          description: Pizza to be added

                    models:
                      Orders:
                        id: Orders
                        adapter: mongo-orm
                        connection : mongo
                        properties:
                          id:
                            type: int
                            primaryKey: true
                          order_name:
                            type: string
                          order_contents:
                            type: string
                          quantity:
                           type: int
                          order_status:
                            type: string
                      OrderAdd:
                        id: OrderAdd
                        properties:
                          id:
                            type: int
                          orderName:
                            type: string
                      Pizza:
                        id: Pizza
                        adapter: mongo-orm
                        connection : mongo
                        properties:
                          id:
                            type: int
                        pizza_name:
                          type: string
                        pizza_contents:
                          type: string
                        pizza_size:
                          type: int
                      Status:
                        id: Status
                        properties:
                          statusInfo:
                            type: string

                    configuration:
                      mongo:
                        adapter: mongo-orm
                        module: aquajs-mongo
                        host: localhost
                        port: 27017
                        database: xxxxx
                      persist:
                        driver: oracle
                        name: testConn
                        hostname: xxxxxx
                        user: test
                        password: xxxxx
                        port: 1521
                        database: TEST1
                        pooling:
                          name: ecxPool
                          max: 2
                          min: 1
                          idleTimeoutMillis: 30000
                      test_oracle:
                        name: testConn
                        log: true
                        max: 10
                        hostname: xxxx
                        user: test
                        password: xxxxx
                        port: 1521
                        database: TEST1
                    

Tests

Test-driven development (TDD) , as many of you might know, is one of the main, agile development techniques. The genius of TDD lies in increased quality of code, faster development resulting from greater programmer confidence, and improved bug detection (duh!).

Historically, web apps have been hard to autotest, and developers relied heavily on manual testing. But, certain parts such as standalone services and REST API can be and should be tested thoroughly by the TDD.

The behavior-driven development (BDD) concept is based on TDD. It differs from TDD in language, which encourages collaboration between product owners and programmers. Similar to building apps themselves, most of the time software engineers should use a testing framework Aquajs uses the mocha,chai and sinon to build the test suites for TDD.


100% Javascript

Like other MVC frameworks, Aqua is built with an emphasis on developer happiness and a convention-over-configuration philosophy. But Node.js takes this principle to the next level. Building on top of Aquajs means your app is written entirely in JavaScript, the language you and your team are already using in the browser. Since you spend less time context-shifting, you're able to write code in a more consistent style, which makes development more productive and fun.

Powerful Associations

Aqua offers a new take on the familiar relational model, aimed at making data modeling more practical. You can do all the same things you might be used to (one-to-many, many-to-many), but you can also assign multiple named associations per-model (for instance, a cake might have two collections of people: "havers" and "eaters"). Better yet, you can assign different models to different databases, and your associations/joins will still work-- even across NoSQL and relational boundries. Aqua has no problem implicitly/automatically joining a MySQL table with a Mongo collection and vice versa.

Auto Generated Rest APIs

Aqua comes with blueprints that help jumpstart your app's backend without writing any code.. Since these blueprint actions are built on the same underlying technology as Aqua, they also work with Websockets and any supported database out of the box.

Historically, web apps have been hard to autotest, and developers relied heavily on manual testing. But, certain parts such as standalone services and REST API can be and should be tested thoroughly by the TDD.

The behavior-driven development (BDD) concept is based on TDD. It differs from TDD in language, which encourages collaboration between product owners and programmers. Similar to building apps themselves, most of the time software engineers should use a testing framework Aquajs uses the mocha,chai and sinon to build the test suites for TDD.

Rock Solid Foundation

Aqua is built on Node.js, a popular, lightweight server-side technology that allows developers to write blazing fast, scalable network appliations in JavaScript. Aqua uses Express for handling HTTP requests, and wraps socket.io for managing WebSockets. So if your app ever needs to get really low-level, you can access the raw Express or socket.io objects. Another nice side-effect is that your existing Express routes work perfectly well in a aqau app, so migrating an existing Node app is a breeze.