Chapter 7. Consuming Services Using a Microservice Web App

Now, after developing the microservices, it would be interesting to see how the services offered by the Online Table Reservation System (OTRS) could be consumed by web or mobile applications. We will develop the web application (UI) using AngularJS/bootstrap to build the prototype of the web application. This sample application will display the data and flow of this sample project – a small utility project. This web application will also be a sample project and will run independently. Earlier, web applications were being developed in single web archives (files with .war extensions) that contain both UI and server-side code. The reason for doing so was pretty simple as UI was also developed using Java with JSPs, servlets, JSF, and so on. Nowadays, UIs are being developed independently using JavaScript. Therefore, these UI apps also deploy as a single microservice. In this chapter, we'll explore how these independent UI applications are being developed. We will develop and implement the OTRS sample app without login and authorization flow. We'll deploy a very limited functionality implementation and cover the high level AngularJS concepts. For more information on AngularJS, you can refer to AngularJS by Example, Chandermani, Packt publishing.

In this chapter, we will cover the following topics:

  • AngularJS framework overview
  • Development of OTRS features
  • Setting up a web app (UI)

AngularJS framework overview

Now since we are ready with our HTML5 web app setup, we can go through the basics of AngularJS. This will help us to understand the AngularJS code. This section depicts the high level of understanding that you can utilize to understand the sample app and explore further using AngularJS documentation or by referring to other Packt publications.

AngularJS is a client side JavaScript framework. It is flexible enough to be used as a MVC (Model View Controller) or MVVM (Model-View-ViewModel). It also provides built-in services like $http or $log using a dependency injection pattern.

MVC

MVC is well-known design pattern. Struts and Spring MVC are popular examples. Let's see how they fit in the JavaScript world:

  • Model: Models are JavaScript objects that contain the application data. They also represent the state of the application.
  • View: View is a presentation layer that consists of HTML files. Here, you can show the data from models and provide the interactive interface to the user.
  • Controller: You can define the controller in JavaScript and it contains the application logic.

MVVM

MVVM is an architecture design pattern that specifically targets the UI development. MVVM is designed to make two-way data binding easier. Two-way data binding provides the synchronization between the Model and View. When the Model (data) changes, it reflects immediately on the View. Similarly, when the user changes the data on the View, it reflects on the Model.

  • Model: This is very similar to MVC and contains the business logic and data.
  • View: Like MVC, it contains the presentation logic or user interface.
  • ViewModel: ViewModel contains the data binding between the View and Model. Therefore, it is an interface between the View and Model.

Modules

A module is the first thing we define for any AngularJS application. A module is a container that contains the different parts of the app such as controllers, services, filters, and so on. An AngularJS app can be written in a single module or multiple modules. An AngularJS module can contain other modules also.

Many other JavaScript frameworks use the main method for instantiating and wiring the different parts of the app. AngularJS does not have the main method. It uses the module as an entry point due to following reasons:

  • Modularity: You can divide and create your application feature-wise or with reusable components.
  • Simplicity: You might have come across complex and large application code, which makes maintenance and enhancement a headache. No more, AngularJS makes code simple, readable, and easy to understand.
  • Testing: It makes unit testing and end-to-end testing easier as you can override configuration and load only those modules which are required.

Each AngularJS app needs to have a single module for bootstrapping the AngularJS app. Bootstrapping our app requires the following three parts:

  • App module: A JavaScript file (app.js) that contains the AngularJS module as shown:
    var otrsApp = AngularJS.module('otrsApp', [ ])
    // [] contains the reference to other modules
  • Loading Angular library and app module: An index.html file containing the reference to the JavaScript file with other AngularJS libraries:
    <script type="text/javascript" src="AngularJS/AngularJS.js"/>
    <script type="text/javascript" src="scripts/app.js"/></script>
  • App DOM configuration: This tells the AngularJS location of the DOM element where bootstrapping should take place. It can be done in either of two ways:
    • Index.html file that also contains an HTML element (typically <html>) with the ng-app (AngularJS directive) attribute having the value given in app.js. AngularJS directives are prefixed with ng (AngularJS): <html lang="en" ng-app="otrsApp" class="no-js">.
    • Or use this command if you are loading the JavaScript files asynchronously: AngularJS.bootstrap(document.documentElement, ['otrsApp']);.

An AngularJS module has two important parts, config() and run(), apart from other components like controllers, services, filters, and so on.

  • config() is used for registering and configuring the modules and it only entertains the providers and constants using $injector. $injector is an AngularJS service. We'll cover providers and $injector in the next section. You cannot use instances here. It prevents the use of services before it is fully configured.
  • run() is used for executing the code after $injector is created using the preceding config method. This only entertains the instances and constants. You cannot use providers here to avoid configuration at run time.

Providers and services

Let's have a look at the following code:

.controller('otrsAppCtrl', function ($injector) {
var log = $injector.get('$log');

$log is an inbuilt AngularJS service that provides the logging API. Here, we are using another inbuilt service, $injector, that allows us to use the $log service. $injector is an argument in the controller. AngularJS uses function definitions and regex to provide the $injector service to a caller, also known as the controller. These are examples of how AngularJS effectively uses the dependency injection pattern.

AngularJS heavily uses the dependency injection pattern. AngularJS uses the injector service ($injector) to instantiate and wire most of the objects we use in our AngularJS app. This injector creates two types of objects – services and specialized objects.

For simplification, you can say that we (developers) define services. On the contrary, specialized objects are AngularJS stuff like controllers, filters, directives, and so on.

AngularJS provides five recipe types that tell the injector how to create service objects – provider, value, factory, service, and constant.

  • The provider is the core and most complex recipe type. Other recipes are synthetic sugar on it. We generally avoid using the provider except when we need to create reusable code that requires global configuration.
  • The value and constant recipe types works as their name suggests. Both cannot have dependencies. Moreover, the difference between them lies with their usage. You cannot use value service objects in the configuration phase.
  • The factory and service are the most used services types. They are of a similar type. We use the factory recipe when we want to produce JavaScript primitives and functions. On the other hand, the service is used when we want to produce custom defined types.

As we have now some understanding of services, we can say that there are two common uses of services – organizing code and sharing code across apps. Services are singleton objects, which are lazily instantiated by the AngularJS service factory. By now, we have already seen a few of the in-built AngularJS services like $injector, $log, and so on. AngularJS services are prefixed with the $ symbol.

Scopes

In AngularJS apps, two types of scopes are widely used: $rootScope and $scope:

  • $rootScope is the top most object in the scope hierarchy and has the global scope associated with it. That means that any variable you attached to it will be available everywhere and therefore use of $rootScope should be a carefully considered decision.
  • Controllers have $scope as an argument in the callback function. It is used for binding data from the controller to the view. Its scope is limited to the use of the controller it is associated with.

Controllers

The controller is defined by the JavaScript constructor function as having a $scope as an argument. The controller's main purpose is to tie the data to the view. The controller function is also used for writing business logic – setting up the initial state of the $scope object and adding the behavior to $scope. The controller signature looks like the following:

RestModule.controller('RestaurantsCtrl', function ($scope, restaurantService) {

Here, the controller is a part of RestModule. The name of the controller is RestaurantCtrl. $scope and restaurantService are passed as arguments.

Filters

The purpose of filters is to format the value of a given expression. In the following code we have defined the datetime1 filter that takes date as an argument and changes the value in dd MMM yyyy HH:mm format like 04 Apr 2016 04:13 PM.

.filter('datetime1', function ($filter) {
    return function (argDateTime) {
        if (argDateTime) {
            return $filter('date')(new Date(argDateTime), 'dd MMM yyyy HH:mm a');
        }
        return "";
    };
});

Directives

As we have seen in the Modules section, AngularJS directives are HTML attributes with an ng prefix. Some of the popular directives are:

  • ng-app: This directive defines the AngularJS application
  • ng-model: This directive binds the HTML form input to data
  • ng-bind: This directive binds the data to the HTML view
  • ng-submit: This directive submits the HTML form
  • ng-repeat: This directive iterates the collection
    <div ng-app="">
        <p>Search: <input type="text" ng-model="searchValue"></p>
        <p ng-bind="searchedTerm"></p>
    </div>

UI-Router

In single page applications (SPAs), the page only loads once and the user navigates through different links without page refresh. It is all possible because of routing. Routing is a way to make SPA navigation feel like a normal site. Therefore, routing is very important for SPA.

The AngularUI team built UI-Router, an AngularJS routing framework. UI-Router is not a part of core AngularJS. UI-Router not only changes the route URL, but it also changes the state of the application when the user clicks on any link in the SPA. Because UI-Router can also make state changes, you can change the view of the page without changing the URL. This is possible because of the application state management by UI-Router.

If we consider the SPA as a state machine then the state is a current state of the application. We will use the attribute ui-sref in a HTML link tag when we create the route link. The attribute href in the link will be generated from this and point to certain states of the application which are created in app.js.

We use the ui-view attribute in the HTML div to use UI-Router: for example, <div ui-view></div>.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset