Develop a web application with Angular2

Angular2 promises many improvements over the previous version.

It’s simpler to learn thanks to easier and more concise concepts like component-based architecture.

The Angular2 module system makes it easier to develop complex and larger projects.

Angular2 is faster than its ancestor thanks to completely rewritten data binding and change detection.

Router module is improved by providing new features like sibling views and nested states.

The aim of this post is to discover some new Angular2 features by developing a web project that uses apart Angular2 other projects like Express, TypeScript and MongoDb.

The source code is provided on GitHub here. You can run the project at this link.

Project structure

The Angular2 sample project has this structure.

    |   +-app 
    |   +-assets (Directoy conatins images and css)
    |   +-index.html
    |   +-tsconfig.json
    |   \-typings.json
    |   +-server.ts
    |   +-tsconfig.json
    |   \-typings.json
    +-dist (Directory generated by gulp)

You can explore the project structure on Github here

Project dependencies

The package.json file identifies npm package dependencies for the project.

  "name": "ng2-project",
  "version": "1.0.0",
  "main": "server/index.js",
  "license": "ISC",
  "scripts": {
    "start": "concurrently \"npm run tsc:w\" \"npm run lite\" ",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "lite": "lite-server",
    "postinstall": "gulp"
  "dependencies": {
    "@angular/core": "2.0.0",
    "@angular/common": "2.0.0",
    "@angular/compiler": "2.0.0",
    "@angular/http": "2.0.0",
    "@angular/platform-browser": "2.0.0",
    "@angular/platform-browser-dynamic": "2.0.0",
    "@angular/router": "3.0.0",
    "@angular/upgrade": "2.0.0",
    "systemjs": "0.19.27",
    "es6-shim": "^0.35.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.12",
    "zone.js": "^0.6.23",
    "angular2-in-memory-web-api": "0.0.20",
    "material-design-lite": "1.1.2",
    "express": "4.13.4",
    "mongodb": "2.1.18",
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.1.0",
    "typescript": "1.8.10",
    "del": "2.2.0",
    "gulp": "3.9.1",
    "gulp-concat": "2.6.0",
    "gulp-sourcemaps": "1.6.0",
    "gulp-typescript": "2.13.4",
    "gulp-tsd": "0.1.1",
    "gulp-typings": "1.3.6",
    "run-sequence": "1.1.5"

1- Server Side

We start with the server side implementation, and then we can test the rest API before using it in the client side code.

1.1 Add tsconfig.json file

The tsconfig.json file provides a TypeScript compiler configuration.

  "version": "1.8.10",
  "compilerOptions": {
    "target": "ES5",
    "module": "commonjs",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  "files": [
  "exclude": [

1.1 Add typings file

TypeScript compiler doesn’t recognize natively some JavaScript libraries features and syntax.
Some of the included files that provides required description for TypeScript. Others don’t provide it and they will require to be configured in typings.js file.

  "version": false,
  "ambientDependencies": {
    "node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#a44529fcb1e1cdc0355e71c42a6048de99b57c34",
    "express-serve-static-core": "github:DefinitelyTyped/DefinitelyTyped/express-serve-static-core/express-serve-static-core.d.ts#a44529fcb1e1cdc0355e71c42a6048de99b57c34",
    "express": "github:DefinitelyTyped/DefinitelyTyped/express/express.d.ts#a44529fcb1e1cdc0355e71c42a6048de99b57c34",
    "serve-static": "github:DefinitelyTyped/DefinitelyTyped/serve-static/serve-static.d.ts#a44529fcb1e1cdc0355e71c42a6048de99b57c34",
    "mime": "github:DefinitelyTyped/DefinitelyTyped/mime/mime.d.ts#a44529fcb1e1cdc0355e71c42a6048de99b57c34"

1.2 – Install and create database

To install MongoDB you can download and install it by following instructions in this link
Next we will need to initialize database data. you can use the code bellow:

use mydata

{"id" : "1" , "name" : "Steve" , "mail" : "" , "phone" : "+33 0120255555" , "adress" : "280 Central Park West New York, NY 10024"},
{"id" : "2" , "name" : "Narco" , "mail" : "" , "phone" : "+33 0120255555" , "adress" : "280 Central Park West New York, NY 10024"},
{"id" : "3" , "name" : "Bombasto" , "mail" : "" , "phone" : "+33 0120255555" , "adress" : "280 Central Park West New York, NY 10024"},
{"id" : "4" , "name" : "Celeritas" , "mail" : "" , "phone" : "+33 0120255555" , "adress" : "280 Central Park West New York, NY 10024"},
{"id" : "5" , "name" : "Magneta" , "mail" : "" , "phone" : "+33 0120255555" , "adress" : "280 Central Park West New York, NY 10024"},
{"id" : "6" , "name" : "RubberMan" , "mail" : "" , "phone" : "+33 0120255555" , "adress" : "280 Central Park West New York, NY 10024"}

You can use MongoDb as a service provided by mLab. All what you have to do is to sign up, create a database and add a user to access the database by using a simple web user interface.

1.3 – Implement the Rest API

In this project we use Express.js to implement the server side API.

Express.js is a web application framework for Node.js, It is designed for building web applications and APIs.

import express = require('express');
import path = require('path');
var port: number = process.env.PORT || 3000;
var app = express();
var MongoClient = require('mongodb').MongoClient;
var database;

app.use('/assets', express.static(path.resolve(__dirname, 'assets')));
app.use('/app', express.static(path.resolve(__dirname, 'app')));
app.use('/libs', express.static(path.resolve(__dirname, 'libs')));

var server = app.listen(port, function() {
    var port = server.address().port;
    console.log("This express app is listening on port " + port);

    function(err, db) {
    if (err) {
        throw err;
    database = db;

app.get("/api/users", (req, res) => {
    // Get all registrations
    database.collection('users').find().toArray(function(err, result) {
        if (err) {
            console.log("Can't get users from database : " + err);
            throw err;
        console.log("/api/users result size = " + result.length);

app.get("/api/users/:id", (req, res) => {
    database.collection('users').findOne( {id :} , function(err, item) {
        if (err) {
            console.log("Can't get users from database : " + err);
            throw err;
        console.log("found user :" + JSON.stringify(item));

var renderIndex = (req: express.Request, res: express.Response) => {
    res.sendFile(path.resolve(__dirname, 'index.html'));

app.get('/*', renderIndex);

1.4 Build and test server side code

To build a project we use Gulp that install typings and compiles TypeScript files.

Bellow the source code of gulpfile.js file

var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var ts = require('gulp-typescript');
var runSequence = require('run-sequence');
var gulpTypings = require("gulp-typings");

gulp.task("installTypings", function () {
    var stream = gulp.src(["./server/typings.json"])
    return stream;

gulp.task('buildServer', function () {
    var tsProject = ts.createProject('server/tsconfig.json');
    var tsResult = gulp.src('server/**/*.ts')
    return tsResult.js

gulp.task('build', function (callback) {
    runSequence('installTypings', 'buildServer', callback);

gulp.task('default', ['build']);

To build the project, Open a terminal window and enter this command:

npm install

Next, run the node server:

node dist/server.js

Then test the API in your browseron this url:

If everything is well done, the browser display an array of users in JSON format.

2- Client side

2.1 Add typings file

Bellow the source code of client typings.json

  "ambientDependencies": {
    "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654"

2.2 Add typescript configuration file

  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  "exclude": [

2.3 Add SystemJs config file

SystemJs is a dynamic module loader. It loads ES6 modules, AMD, CommonJS and global scripts in the browser and NodeJS.
SystemJs will load libraries when they are required.

The configuration below tells SystemJs where to look for a module when component is imported.

(function(global) {

    // map tells the System loader where to look for things
    var map = {
        'app':      'app',        
        // angular bundles
        '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
        '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
        '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
        '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
        '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
        '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
        '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
        'rxjs':     'libs/rxjs',
        '@angular': 'libs/@angular'

    // packages tells the System loader how to load when no filename and/or no extension
    var packages = {
        'app':      { main: './main.js',  defaultExtension: 'js' },
        'rxjs':     { defaultExtension: 'js' },
        'angular2-in-memory-web-api': {defaultExtension: 'js'}

    var config = {
        paths: { // paths serve as alias
          'npm:': 'libs/'
        map: map,
        packages: packages


2.4 Add index.html page

Here, we import style sheets, load libraries and configure SystemJs.

We provide to SystemJS the root module (app) of the application. Then SytemJs will look for all dependencies referenced by the app module.

<html lang="en">
    <base href="/"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href=",bold,italic,thin,light,bolditalic,black,medium&amp;lang=en">
    <link rel="stylesheet" href="">
    <link rel="stylesheet" href="">
    <link rel="stylesheet" href="assets/css/styles.css">

    <!-- 1. Load libraries -->
    <!-- IE required polyfills, in this exact order -->
    <script src="libs/es6-shim/es6-shim.min.js"></script>
    <script src="libs/zone.js/dist/zone.js"></script>
    <script src="libs/reflect-metadata/Reflect.js"></script>
    <script src="libs/systemjs/dist/system.src.js"></script>

    <!-- 2. Configure SystemJS -->
    <script src="app/systemjs.config.js"></script>
        System.import('app').catch(function (err) {

    <script src="libs/material-design-lite/dist/material.min.js"></script>


<!-- 3. Display the application -->
<body class="mdl-color--grey-100">

2.5 Add application module : app.module.ts

NgModule is a decorator function that describes the module. The most important properties are:

  • declarations – the view classes that belong to this module.
  • imports – other modules whose exported classes are needed by component templates declared in this module.
  • providers – creators of services that this module contributes to the global collection of services; they become accessible in all parts of the app.
  • bootstrap – the main application view, called the root component, that hosts all other app views. Only the root module should set this bootstrap property.

Here’s a root module of our application:

import { NgModule }             from '@angular/core';
import { BrowserModule }        from '@angular/platform-browser';
import { HttpModule }           from '@angular/http';
import { AppComponent }         from './app.component';
import { routing, appRoutingProviders }  from './app.routing';
import {HomeComponent}          from './home/home.comonent';
import {UserListComponent}      from './users/user-list.component';
import {UserDetailComponent}    from './users/user-detail.component';

  imports: [
  declarations: [
  providers: [
  bootstrap: [ AppComponent ]

export class AppModule { }

2.6 Add main.ts file

Here we launch the application by bootstrapping its root module.

/// <reference path="../typings/browser.d.ts" />
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app.module';

2.7 Configure router : app.routing.ts

Here we configure the router that looks for a corresponding Route from which it can determine the component to display.

In the following example, we configure our application with three route definitions.

import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import {HomeComponent}         from './home/home.comonent';
import {HomeResolver}         from './home/home.resolver';
import {HomeService}         from './home/home.service';
import {UserListComponent}     from './users/user-list.component';
import {UserDetailComponent}   from './users/user-detail.component';
import {UserDetailResolver}   from './users/user-detail.resolver';
import {UserListResolver}   from './users/user-list.resolver';
import {UserService}   from './users/user.service';

export const appRoutes : Routes =[
    {path: '',  
     component: HomeComponent,
     resolve : {technologies: HomeResolver}
    {path: 'users', 
     component: UserListComponent,
     resolve : {users: UserListResolver}
    {path: 'user/:id', 
     component: UserDetailComponent, 
     resolve : {user: UserDetailResolver}

export const appRoutingProviders: any[] = [HomeResolver, UserListResolver, 
        UserDetailResolver, HomeService, UserService];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);

To achieve a better user-experience when browsing between pages, we use resolver.

It avoids displaying pages before data finished loading.

It also makes the controller’s code much cleaner in contrast to fetching data inside the controller.

import {Injectable} from '@angular/core';
import {Resolve, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {Observable} from 'rxjs/Observable';
import { User, UserService } from './user.service';

export class UserListResolver implements Resolve<User[]> {
        private service: UserService
 ) {}
 resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<User[]> {
        return this.service.getUsers();

2.7 Add components

2.6.1 Add application main component

import {Component} from '@angular/core';
import {MDL} from './directives/MaterialDesignLite';
import './rxjs-operators';

    selector: 'my-app',
    templateUrl: 'app/app.component.html'

export class AppComponent { }

“rxjs-oppertors” references the “rxjs-oppertors.ts” file where we will imports all required rxjs statics and operators we need for this application.

// Statics
import 'rxjs/add/observable/throw';
// Operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';

Next, we write the template html (app.component.html) code.

<div mdl class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
  <header class="mdl-layout__header">
    <div class="mdl-layout__header-row">
      <!-- Title -->
      <span class="mdl-layout-title">Title</span>
      <!-- Add spacer, to align navigation to the right -->
      <div class="mdl-layout-spacer"></div>
      <!-- Navigation. We hide it in small screens. -->
      <nav class="mdl-navigation mdl-layout--large-screen-only">
        <a class="mdl-navigation__link" [routerLink]="['/']" >Home</a>
        <a class="mdl-navigation__link" [routerLink]="['users']">Users</a>
  <div class="mdl-layout__drawer">
    <span class="mdl-layout-title">Title</span>
    <nav class="mdl-navigation">
      <a class="mdl-navigation__link" [routerLink]="['/']" >Home</a>
      <a class="mdl-navigation__link" [routerLink]="['/users']">Users</a>
  <main class="mdl-layout__content">

2.6.2 Add users list component

This page calls a rest web service and display users list.

First, we develop service module.

import {Injectable} from '@angular/core';
import {Http, Headers, Response} from '@angular/http';
import {Observable}     from 'rxjs/Observable';

export class User {
    constructor(public id:number, public name:string, 
         public email:string, public phone:string, public adress:string) {

export class UserService {
    constructor (private http: Http) {}
    private _usersUrl = 'api/users';

    private extractData(res: Response) {
        if (res.status < 200 || res.status >= 300) {
            throw new Error('Bad response status: ' + res.status);
        return res.json();

    private handleError (error: any) {
        let errMsg = error.message || 'Server error';
        console.error(errMsg); // log to console instead
        return Observable.throw(errMsg);

    getUsers() : Observable<User[]> {
        return this.http.get(this._usersUrl)

    getUser(id:number | string) : Observable<User> {
        return this.http.get(this._usersUrl + "/" + id)

Next, we develop the UsersList component.

import {Component, OnInit}   from '@angular/core';
import {Router, ActivatedRoute} from '@angular/router';
import {User}   from './user.service';

    templateUrl: 'app/users/user-list.component.html'
export class UserListComponent implements OnInit {
    private selectedId:number;

    constructor(private route: ActivatedRoute,
                private router:Router) {

    ngOnInit() {
        this.users =['users'];

    isSelected(user:User) {
        return === this.selectedId;

    onSelect(user:User) {

The source code bellow presents the template html code

<div class="page-content mdl-grid">
    <div class="mdl-grid--no-spacing mdl-card mdl-shadow--4dp mdl-cell mdl-cell--12-col">
    <div class="users-card-wide">
        <div class="mdl-card__title mdl-color--purple-700">
            <h1 class="mdl-card__title-text">Users</h1>
        <div class="mdl-list">
          <div class="mdl-list__item mdl-list__item--two-line" *ngFor="let user of users"
            <span class="mdl-list__item-primary-content">
              <img class="user-list-avatar mdl-list__item-avatar" 
              <span class="mdl-list__item-sub-title">
            <a class="mdl-list__item-secondary-action" href="#">
                <i class="material-icons">star</i>

3. Build project

To build the client side and the server side code of our project, we update gulpfile.js.

var gulp = require('gulp');
var path = require('path');
var sourcemaps = require('gulp-sourcemaps');
var ts = require('gulp-typescript');
var del = require('del');
var runSequence = require('run-sequence');
var gulpTypings = require("gulp-typings");

gulp.task('clean', function () {
    return del('dist')

gulp.task("installTypings", function () {
    var stream = gulp.src(["./client/typings.json", "./server/typings.json"])
    return stream;

gulp.task("deleteDupTypings", function () {
    return del(["./client/typings/main.d.ts",

gulp.task('buildServer', function () {
    // code provided previded in the previous section

 jsNPMDependencies, sometimes order matters here! so becareful!
var jsNPMDependencies = [

gulp.task('buildIndex', function () {
    var mappedPaths = (file) {
        return path.resolve('node_modules', file)

    //Let's copy our head dependencies into a dist/libs
    var copyJsNPMDependencies = gulp.src(mappedPaths, {base: 'node_modules'})

    //Let's copy html and js to dist
    var copyIndex = gulp.src(['client/**/*.html', 'client/**/*.js'])

    var copyAsserts = gulp.src('client/assets/**/*')

    return [copyJsNPMDependencies, copyIndex, copyAsserts];

gulp.task('buildClient', function () {
    var tsProject = ts.createProject('client/tsconfig.json');
    var tsResult = gulp.src('client/**/*.ts')
    return tsResult.js

gulp.task('watch', ['buildServer'], function () {'server/*.ts', ['buildServer']);'client/**/*.ts', ['buildClient']);

gulp.task('build', function (callback) {
    runSequence('clean', 'installTypings', 'deleteDupTypings', 'buildServer', 
                  'buildIndex', 'buildClient', callback);

gulp.task('default', ['build']);

Next, Open a terminal window and enter this command:

npm install

4. Run the project

Finally, we launch the node server.

node dist/server.js

Open your browser and test the application at this URL http://localhost:8080.



First impression after developing this sample project, Angular2 needs more investment than its ancestor from developer to start developing application. It requires learning Typescript and understanding other features like SystemJs and Typings.

Angular2 have the advantage to be modular and more structured than its previous version that make it a good choice for large applications development.

Integrate Gulp on a Maven managed project

Using front-end frameworks for a java web application like AngularJs and Bootstrap needs some caution to manage JavaScript and Css dependencies.

There are two tools family for front-end libraries management. The Java ones like Wro4j and Jawr witch have the advantage to integrate easily to Java project management softs like maven and grails and don’t need any extra knowledge.

The second ones are JavaScript tools like Grunt, Bower and Gulp. Those tools have a great success and have the advantage to be used for front-end frameworks development.

Photo credit: Tony lea

As a result, you will face less problems where managing front-end dependencies and optimizing web resources.

This this post presents a solution to use Maven, Bower and Gulp to manage front-end libraries for a java web project.

The source code of this post is available in this link and you can test it here.

Add frontend maven Plugin

Frontend plugin install node and npm and It lets you run Bower and Gulp.

Add the xml bellow to your project pom.xml file to configure “frontend-maven-plugin”.

                     <id>install node and npm</id>
                     <id>npm install</id>
                     <id>bower install</id>
                     <id>gulp build</id>

Add front-end dependencies

Bower works by fetching and installing front-end packages. For more information about bower visit the website

Add a bower.json file with front-end dependencies in the root directory of your maven project (next to the pom.xml file).

  "name": "example",
  "version": "0.0.1",
  "dependencies": {
    "jquery": "~2.1.3",
    "angular": "1.4.5",
    "angular-route": "1.4.5",
    "angular-resource": "1.4.5",
    "angular-sanitize": "1.4.5",
    "bootstrap": "3.3.4",
    "bootstrap-material-design": "0.3.0",
    "angular-swagger-ui": "~0.2.3"
  "private": true

Add Glup module dependencies

Add package.json file with the content bellow.

  "name": "example",
  "version": "0.0.1",
  "dependencies": {
    "bower": "~1.3.12",
    "gulp": "^3.9.0",
    "gulp-concat": "^2.6.0",
    "gulp-concat-vendor": "0.0.4",
    "gulp-uglify": "^1.3.0",
    "main-bower-files": "^2.9.0",
    "gulp-minify-css" : "^1.2.1",
    "gulp-inject": "1.5.0",
    "gulp-run-sequence": "0.3.2",
    "stream-series": "0.1.1",
    "gulp-gzip": "1.2.0",
    "gulp-clone": "1.0.0"
  "jspm": {
    "dependencies": {
      "jquery": "github:jquery/jquery@^2.1.3"
    "devDependencies": {
      "traceur": "github:jmcriffey/bower-traceur@0.0.88",
      "traceur-runtime": "github:jmcriffey/bower-traceur-runtime@0.0.88"
  "scripts": {
    "prebuild": "npm install",
    "build": "gulp"

Add a Gulp execution file

Create the Gulp execution file gulpfile.js with the content bellow.

var gulp           = require('gulp');
var concat         = require('gulp-concat');
var concatVendor   = require('gulp-concat-vendor');
var uglify         = require('gulp-uglify');
var minify         = require('gulp-minify-css')
var mainBowerFiles = require('main-bower-files');
var inject         = require('gulp-inject');
var runSequence    = require('gulp-run-sequence');
var gzip           = require('gulp-gzip');
var clone          = require('gulp-clone');
var series         = require('stream-series');

var vendorJs;
var vendorCss;

gulp.task('lib-js-files', function () {
    vendorJs = gulp.src(mainBowerFiles('**/*.js'),{ base: 'bower_components' })


gulp.task('lib-css-files', function () {
    vendorCss = gulp.src(mainBowerFiles('**/*.css'), {base: 'bower_components'})


gulp.task('index', function () {
    var target = gulp.src("src/main/webapp/index.html");
    var sources = gulp.src(['src/main/webapp/resources/js/*.js', 'src/main/webapp/resources/css/*.css'], {read: false});
    return target.pipe(inject(series(vendorJs, vendorCss, sources), {relative: true}))

gulp.task('copyFonts', function() {

// Default Task
gulp.task('default', function () {
    runSequence('lib-js-files', 'lib-css-files', 'index', 'copyFonts');

The gulp script has 4 tasks:

  • lib-js-files : concat, uglify and compress all vendor javascript dependencies
  • lib-css-files : concat, minify and compress all vendor css dependencies
  • index : inject the dependencies to file
  • copyFonts : copy fonts to vendor/font directory to keep css references

The graph bellow presents gulp tasks flows.


Configure Spring to resolve Gzip files

In this step, we configure Spring MVC framework to look for Gzip files for the application web resources.

// Extra config annotations 
public class MvcConfig extends WebMvcConfigurerAdapter {

    public void addResourceHandlers(ResourceHandlerRegistry registry) {
                .addResolver(new GzipResourceResolver())
                .addResolver(new PathResourceResolver());

    // Extra config here


Build and deploy your application

Build your application by running :

mvn clean install

Under OpenShift, you may need to change home directory (npm needs to create files under HOME directory):

If everything is well done, your project directory will have the structure described below.

   +-- bower_components **
   +-- node **
   +-- node_module **
   +-- src
   |    +-- main
   |    |     +-- java
   |    |     +-- resources
   |    |     \-- webapp
   |    |           +-- resources
   |    |           |      +-- css
   |    |           |      +-- js
   |    |           |      \-- vendor **
   |    |           |            +-- css
   |    |           |            |    +-- lib.min.css
   |    |           |            |    \-- lib.min.css.gz
   |    |           |            +-- fonts 
   |    |           |            |    +-- glyphicons-halflings-regular.svg
   |    |           |            |    +-- ....
   |    |           |            \-- js
   |    |           |                 +-- lib.min.js
   |    |           |                 \-- lib.min.js.gz
   |    |           +-- WEB-INF
   |    |           \-- index.html 
   |    +-- test
   +-- target
   +-- bower.json
   +-- gulpfile.js
   +-- package.json
   \-- pom.xml

Finally, deploy and run the application. The sample application of this post is deployed on this link.

The two pictures bellow present Chrome DevTools to compare network performance of the optimized web application which has a load time of 2.74s and the same application without resource optimization which has a load time of 3.37s.

2015_09_23_16_02_46_tomcat7_samerabdelkafi.rhcloud.com_fng_project_apiDoc 2015_09_23_16_03_24_tomcat7_samerabdelkafi.rhcloud.com_ng_swagger_apiDoc