KEMBAR78
Creating Modular Test-Driven SPAs with Spring and AngularJS | PDF
Creating Modular Test Driven SPAs with 
Spring And AngularJS 
By Gunnar Hillert - @ghillert 
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Goals 
• AngularJS Introduction 
• Build and Deployment 
• Integration with Spring 
• Modularization 
• Testing 
• UI Considerations 
2
Me 
• (Java) Web developer since 2005 
• Struts 1+2, Spring MVC, GWT, Flex 
• Spring Integration + XD committer 
• AngularJS since Jan 2014 
• Co-organize 
3
Non-screen activities 
4
AngularJS Introduction 
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Audience - What do you use*? 
• AngularJS 
• Backbone 
• JQuery 
• Are you using any other SPA Framework? Ember.js 
• Spring MVC 
• Spring Boot 
6 
60% 
20% 
80% 
1 user 
80% 
20% 
* Recorded from memory
What are SPAs? 
7 
A single-page application (SPA), also known as single-page 
interface (SPI), is a web application or web site that 
fits on a single web page with the goal of providing a more 
fluid user experience akin to a desktop application. 
Wikipedia
What are SPAs? 
8
JavaScript WTF 
• http://wtfjs.com/ 
9 
parseInt('crap'); // NaN 
parseInt('crap', 16);// 12 
! 
(2 + "3"); // 23 
(2 + +"3"); // 5 
(+""); // 0
Read this 
10
From Backbone to Angular 
• Too many moving parts, choices 
• Boilerplate Code 
• Marionette, Backbone.ModelBinder, Backbone.Relational 
11
Alternatives 
12
AngularJS Basics 
• Model 
• View (Templates) 
• Controller 
• Dependency Injection 
• Expressions 
• Filters 
• Directives 
• Routing 
• Modules 
• See also: AngularJS Concepts 
13
Model 
• Angular is very flexible about your model 
• Ultimately expressed via the $scope 
• $scope = Glue between Controller and View 
• $scope mimics DOM (Hierarchical, one $rootScope) 
14
Model 
• Killer Feature: Data-Binding 
• Model === single-source-of-truth 
• View reflects model changes automatically 
• $watch, $apply 
15
View 
• HTML is your templating Engine 
• Minimize logic as much as possible 
• Consider Custom Directives 
16
¡Hola! 
• Demo 
17 
<div ng-app ng-init="firstName='Eric';lastName='Cartman'"> 
<div> 
First Name: <input type="text" ng-model="firstName"> 
</div> 
<div> 
Last Name: <input type="text" ng-model="lastName"> 
</div> 
<div> 
<b>Complete Name:</b> {{firstName + ' ' + lastName | uppercase}} 
</div> 
</div>
Controller 
• Used to "setup" your $scope (values) 
• Add behavior to your $scope (functions) 
• Don't do UI work using controllers!! 
• Use directives and filters instead 
18
¡Hola! v2.0 - View 
• Demo 
19 
<div ng-app="hola" ng-controller="NameController"> 
<div> 
First Name: <input type="text" ng-model="firstName"> 
</div> 
<div> 
Last Name: <input type="text" ng-model="lastName"> 
</div> 
<div> 
<b>Complete Name:</b> {{firstName + ' ' + lastName | uppercase}} 
</div> 
</div>
¡Hola! v2.0 - Controller 
• Demo 
20 
<script> 
(function(){ 
var app = angular.module('hola', []); 
app.controller('NameController', function($scope){ 
$scope.firstName='Angular'; 
$scope.lastName='rocks'; 
}); 
})(); 
</script>
Dependency Injection 
• Consider using array notation: 
app.controller('NameCtrl', function($scope){ ... }); 
app.controller('NameCtrl', ['$scope', function($scope){ ... }]); 
• Or use ngmin ng-annotate 
• grunt-ngmin, gulp-ngmin, grunt-ng-annotate, gulp-ng-annotate 
21
Expressions 
• {{ expression }} 
• No Control Flow Statements 
• Can use filters inside expressions: 
• {{ 'abcd' | uppercase }} 
22
Filters 
23 
...! 
<tr ng-repeat=! 
! "item in jobDefinitions | filter:filterQuery 
| orderBy:'name'">! 
...
Directives 
• Are markers on a DOM element 
• Attach behavior/transform DOM elements 
• ng-controller, ng-app ... 
24
Types of Directives 
• Attribute (default) 
• Element 
• Class 
• See: https://gist.github.com/CMCDragonkai/6282750 
25
Routing 
• ngRoute (built-in) 
• Routing on steroids using ui-router 
26
Routing using UI-Router 
• state machine 
• nested views 
• Spring XD's routes.js 
27
Modules 
• Hang on tight… 
28
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission. 
botanic | NG
Build and Deployment 
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Build and Deployment 
• Do everything via Maven and Gradle? 
• What about Non-Java Tooling? 
• Consider Web Resource Optimization 
31
Web Resources Optimization 
• Minification 
• Merging 
• Compression 
• Caching (and Cache busting) 
32
Web Resources Optimization 
33
Strategies - Java Tooling 
• Wro4j 
• Jawr 
• Spring 4.1 
• Flexible resolution and transformation of 
static web resources 
• See Blog Post 
• WebJars 
34
Strategies - JavaScript Tooling 
• Node (Npm) 
• Grunt (Gulp) 
• Bower 
• Yeoman (angular-seed) 
35
Make Maven and Gradle Grunt 
• Plugins exist for Gradle and Maven 
• Spring XD uses Gradle integration 
• botanic-ng uses Maven integration 
• Spring Boot plus Maven Frontend Plugin 
36
Integration with Spring (Boot) 
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Hello World fits into Tweet 
38 
@Controller 
class ThisWillActuallyRun 
{ 
@RequestMapping("/") 
@ResponseBody 
String home() { 
"Hello World!" 
} 
}
Rapid Prototyping 
• Spring Scripts (Samples) 
• Starter POMs 
• Über-Jars support (can create WARs also) 
• Maven + Gradle Plugins 
• AutoConfiguration support 
39
Main is BACK 
40 
@EnableAutoConfiguration @ComponentScan @EnableScheduling 
public class MainApp extends RepositoryRestMvcConfiguration { 
@Override 
protected void configureRepositoryRestConfiguration( 
RepositoryRestConfiguration config) { 
config.exposeIdsFor(Image.class, Garden.class, Plant.class); 
config.setBaseUri(URI.create("/api")); 
} 
public static void main(String[] args) { 
final ConfigurableApplicationContext context = 
SpringApplication.run(MainApp.class, args); 
... 
} 
@Bean 
MultipartConfigElement multipartConfigElement() { ... } ... 
}
Security 
41 
• Best strategy in regards to plugging in Spring Security? 
• Authentication and Authorization 
• How does it affect Testing 
• Consider Spring Session 
• org.springframework.session.web.http.HttpSessionStrategy 
• HeaderHttpSessionStrategy (x-auth-token) 
• CookieHttpSessionStrategy
Serving Static Content 
• /META-INF/resources/ 
• /resources/ 
• /static/ 
• /public/ 
• Also supports WebJars 
• Make Boot modules (UI) Pluggable 
42
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission. 
Demo Backend
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission. 
Modularization
Modularization Now 
• AngularJS Modules 
• RequireJS 
45
AngularJS Modules 
• Compartmentalize sections of your application 
• Does not deal with script loading 
• https://docs.angularjs.org/guide/module 
46 
angular.module('myModule', []). 
config(function(injectables) { // provider-injector 
// This is an example of config block. 
}). 
run(function(injectables) { // instance-injector 
// Like a Main method 
});
RequireJS 
• RequireJS 
• JavaScript file 
and module loader 
• RequireJS Optimizer 
47 
require.config({ 
paths: { 
angular: '../lib/angular/angular', 
jquery: '../lib/jquery/jquery', 
bootstrap: '../lib/bootstrap/bootstrap', 
… 
}, 
shim: { 
angular: { 
exports: 'angular' 
}, 
bootstrap: { 
deps: ['jquery'] 
} 
} 
});
Modularization Future 
• ECMAScript 6 modules 
• AngularJS 2 is being written in ES6 
• Web Components 
48
Componentization using Directives 
• angular-masonry 
• cgBusy 
• ngGrowl 
• angular-google-maps 
• angular-leaflet-directive 
• AngularUI 
• Bootstrap directives 
49
File Upload 
• angular-file-upload (nervgh) 
• angular-file-upload (danialfarid) 
• File Reader 
• Traditional Post 
50
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission. 
Testing
Testing 
• E2E testing with Protractor 
• Unit Testing using Karma and Jasmine 
• Consider using SauceLabs 
52
UI Considerations 
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
UI Consideration 
• Bootstrap (It is the baseline) 
• Keep your CSS maintainable with Less and Sass 
• Check your production results with YSlow and PageSpeed 
• Load your site from different corners of the planet using 
http://www.webpagetest.org/ 
54
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission. 
Resources
Books 
56
Videos and More 
• Angular JS Website - Tutorial, Docs 
• Angular JS Youtube Channel 
• ng-conf has almost 30 session videos 
• Shaping up with Angular JS (Videos + Course) 
• Dan Wahlin - Videos and Bog 
• AngularJS Fundamentals In 60-ish Minutes 
• https://egghead.io/ 
• Ben Nadel Blog 
• Year of Moo 
57
Thank You! 
58 
Source Code + Preso: 
https://github.com/ghillert/botanic-ng 
Related Talks 
Spring 4 Web Applications (R. Stoyanchev) 
Deep dive into Spring WebSockets (S. Almar) 
Spring Boot for the Web Tier (D. Syer/P. Webb) 
Resource Handling in Spring MVC 4.1 (B. Clozel/R. Stoyanchev) 
Introducing RaveJS (J. Hann) 
Great single page apps need great backends (Adib Saikali)

Creating Modular Test-Driven SPAs with Spring and AngularJS

  • 1.
    Creating Modular TestDriven SPAs with Spring And AngularJS By Gunnar Hillert - @ghillert © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
  • 2.
    Goals • AngularJSIntroduction • Build and Deployment • Integration with Spring • Modularization • Testing • UI Considerations 2
  • 3.
    Me • (Java)Web developer since 2005 • Struts 1+2, Spring MVC, GWT, Flex • Spring Integration + XD committer • AngularJS since Jan 2014 • Co-organize 3
  • 4.
  • 5.
    AngularJS Introduction ©2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
  • 6.
    Audience - Whatdo you use*? • AngularJS • Backbone • JQuery • Are you using any other SPA Framework? Ember.js • Spring MVC • Spring Boot 6 60% 20% 80% 1 user 80% 20% * Recorded from memory
  • 7.
    What are SPAs? 7 A single-page application (SPA), also known as single-page interface (SPI), is a web application or web site that fits on a single web page with the goal of providing a more fluid user experience akin to a desktop application. Wikipedia
  • 8.
  • 9.
    JavaScript WTF •http://wtfjs.com/ 9 parseInt('crap'); // NaN parseInt('crap', 16);// 12 ! (2 + "3"); // 23 (2 + +"3"); // 5 (+""); // 0
  • 10.
  • 11.
    From Backbone toAngular • Too many moving parts, choices • Boilerplate Code • Marionette, Backbone.ModelBinder, Backbone.Relational 11
  • 12.
  • 13.
    AngularJS Basics •Model • View (Templates) • Controller • Dependency Injection • Expressions • Filters • Directives • Routing • Modules • See also: AngularJS Concepts 13
  • 14.
    Model • Angularis very flexible about your model • Ultimately expressed via the $scope • $scope = Glue between Controller and View • $scope mimics DOM (Hierarchical, one $rootScope) 14
  • 15.
    Model • KillerFeature: Data-Binding • Model === single-source-of-truth • View reflects model changes automatically • $watch, $apply 15
  • 16.
    View • HTMLis your templating Engine • Minimize logic as much as possible • Consider Custom Directives 16
  • 17.
    ¡Hola! • Demo 17 <div ng-app ng-init="firstName='Eric';lastName='Cartman'"> <div> First Name: <input type="text" ng-model="firstName"> </div> <div> Last Name: <input type="text" ng-model="lastName"> </div> <div> <b>Complete Name:</b> {{firstName + ' ' + lastName | uppercase}} </div> </div>
  • 18.
    Controller • Usedto "setup" your $scope (values) • Add behavior to your $scope (functions) • Don't do UI work using controllers!! • Use directives and filters instead 18
  • 19.
    ¡Hola! v2.0 -View • Demo 19 <div ng-app="hola" ng-controller="NameController"> <div> First Name: <input type="text" ng-model="firstName"> </div> <div> Last Name: <input type="text" ng-model="lastName"> </div> <div> <b>Complete Name:</b> {{firstName + ' ' + lastName | uppercase}} </div> </div>
  • 20.
    ¡Hola! v2.0 -Controller • Demo 20 <script> (function(){ var app = angular.module('hola', []); app.controller('NameController', function($scope){ $scope.firstName='Angular'; $scope.lastName='rocks'; }); })(); </script>
  • 21.
    Dependency Injection •Consider using array notation: app.controller('NameCtrl', function($scope){ ... }); app.controller('NameCtrl', ['$scope', function($scope){ ... }]); • Or use ngmin ng-annotate • grunt-ngmin, gulp-ngmin, grunt-ng-annotate, gulp-ng-annotate 21
  • 22.
    Expressions • {{expression }} • No Control Flow Statements • Can use filters inside expressions: • {{ 'abcd' | uppercase }} 22
  • 23.
    Filters 23 ...! <tr ng-repeat=! ! "item in jobDefinitions | filter:filterQuery | orderBy:'name'">! ...
  • 24.
    Directives • Aremarkers on a DOM element • Attach behavior/transform DOM elements • ng-controller, ng-app ... 24
  • 25.
    Types of Directives • Attribute (default) • Element • Class • See: https://gist.github.com/CMCDragonkai/6282750 25
  • 26.
    Routing • ngRoute(built-in) • Routing on steroids using ui-router 26
  • 27.
    Routing using UI-Router • state machine • nested views • Spring XD's routes.js 27
  • 28.
    Modules • Hangon tight… 28
  • 29.
    © 2014 SpringOne2GX. All rights reserved. Do not distribute without permission. botanic | NG
  • 30.
    Build and Deployment © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
  • 31.
    Build and Deployment • Do everything via Maven and Gradle? • What about Non-Java Tooling? • Consider Web Resource Optimization 31
  • 32.
    Web Resources Optimization • Minification • Merging • Compression • Caching (and Cache busting) 32
  • 33.
  • 34.
    Strategies - JavaTooling • Wro4j • Jawr • Spring 4.1 • Flexible resolution and transformation of static web resources • See Blog Post • WebJars 34
  • 35.
    Strategies - JavaScriptTooling • Node (Npm) • Grunt (Gulp) • Bower • Yeoman (angular-seed) 35
  • 36.
    Make Maven andGradle Grunt • Plugins exist for Gradle and Maven • Spring XD uses Gradle integration • botanic-ng uses Maven integration • Spring Boot plus Maven Frontend Plugin 36
  • 37.
    Integration with Spring(Boot) © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
  • 38.
    Hello World fitsinto Tweet 38 @Controller class ThisWillActuallyRun { @RequestMapping("/") @ResponseBody String home() { "Hello World!" } }
  • 39.
    Rapid Prototyping •Spring Scripts (Samples) • Starter POMs • Über-Jars support (can create WARs also) • Maven + Gradle Plugins • AutoConfiguration support 39
  • 40.
    Main is BACK 40 @EnableAutoConfiguration @ComponentScan @EnableScheduling public class MainApp extends RepositoryRestMvcConfiguration { @Override protected void configureRepositoryRestConfiguration( RepositoryRestConfiguration config) { config.exposeIdsFor(Image.class, Garden.class, Plant.class); config.setBaseUri(URI.create("/api")); } public static void main(String[] args) { final ConfigurableApplicationContext context = SpringApplication.run(MainApp.class, args); ... } @Bean MultipartConfigElement multipartConfigElement() { ... } ... }
  • 41.
    Security 41 •Best strategy in regards to plugging in Spring Security? • Authentication and Authorization • How does it affect Testing • Consider Spring Session • org.springframework.session.web.http.HttpSessionStrategy • HeaderHttpSessionStrategy (x-auth-token) • CookieHttpSessionStrategy
  • 42.
    Serving Static Content • /META-INF/resources/ • /resources/ • /static/ • /public/ • Also supports WebJars • Make Boot modules (UI) Pluggable 42
  • 43.
    © 2014 SpringOne2GX. All rights reserved. Do not distribute without permission. Demo Backend
  • 44.
    © 2014 SpringOne2GX. All rights reserved. Do not distribute without permission. Modularization
  • 45.
    Modularization Now •AngularJS Modules • RequireJS 45
  • 46.
    AngularJS Modules •Compartmentalize sections of your application • Does not deal with script loading • https://docs.angularjs.org/guide/module 46 angular.module('myModule', []). config(function(injectables) { // provider-injector // This is an example of config block. }). run(function(injectables) { // instance-injector // Like a Main method });
  • 47.
    RequireJS • RequireJS • JavaScript file and module loader • RequireJS Optimizer 47 require.config({ paths: { angular: '../lib/angular/angular', jquery: '../lib/jquery/jquery', bootstrap: '../lib/bootstrap/bootstrap', … }, shim: { angular: { exports: 'angular' }, bootstrap: { deps: ['jquery'] } } });
  • 48.
    Modularization Future •ECMAScript 6 modules • AngularJS 2 is being written in ES6 • Web Components 48
  • 49.
    Componentization using Directives • angular-masonry • cgBusy • ngGrowl • angular-google-maps • angular-leaflet-directive • AngularUI • Bootstrap directives 49
  • 50.
    File Upload •angular-file-upload (nervgh) • angular-file-upload (danialfarid) • File Reader • Traditional Post 50
  • 51.
    © 2014 SpringOne2GX. All rights reserved. Do not distribute without permission. Testing
  • 52.
    Testing • E2Etesting with Protractor • Unit Testing using Karma and Jasmine • Consider using SauceLabs 52
  • 53.
    UI Considerations ©2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
  • 54.
    UI Consideration •Bootstrap (It is the baseline) • Keep your CSS maintainable with Less and Sass • Check your production results with YSlow and PageSpeed • Load your site from different corners of the planet using http://www.webpagetest.org/ 54
  • 55.
    © 2014 SpringOne2GX. All rights reserved. Do not distribute without permission. Resources
  • 56.
  • 57.
    Videos and More • Angular JS Website - Tutorial, Docs • Angular JS Youtube Channel • ng-conf has almost 30 session videos • Shaping up with Angular JS (Videos + Course) • Dan Wahlin - Videos and Bog • AngularJS Fundamentals In 60-ish Minutes • https://egghead.io/ • Ben Nadel Blog • Year of Moo 57
  • 58.
    Thank You! 58 Source Code + Preso: https://github.com/ghillert/botanic-ng Related Talks Spring 4 Web Applications (R. Stoyanchev) Deep dive into Spring WebSockets (S. Almar) Spring Boot for the Web Tier (D. Syer/P. Webb) Resource Handling in Spring MVC 4.1 (B. Clozel/R. Stoyanchev) Introducing RaveJS (J. Hann) Great single page apps need great backends (Adib Saikali)