SlideShare a Scribd company logo
1 of 40
Download to read offline
Testdrive 
AngularJS with Spring 4 
Dr. Oliver Wahlen 
oliver.wahlen@infinit-group.de 
! 
September 2014 
© 2014 INFINIT GmbH 
1
Motivation 
INFINIT creates software products for customers 
Specialized on Java server and mobile technology 
Hardware & Software are constantly improving at all levels 
Market success of fixed price projects = Efficiency + Quality 
We are constantly improving our processes and tools 
It’s Fun!!! 
© 2014 INFINIT GmbH 2
Challenges of JavaEE projects 
using EJB and JSF… 
fixed component set (xxxFaces) is difficult to customize 
slow due to JSF lifecycle / application state 
hard to integrate with pure Javascript 
does not scale because sessions are huge 
no integrated testing concept: views, unit, integration, function 
variety of IoC frameworks with different constraints (JSF, EJB, CDI) 
slow development roundtrips 
(no hot reloading, monolithic App Server) 
© 2014 INFINIT GmbH 3
Challenges of JavaScript projects 
pure jQuery is no good idea: 
no structure by convention: how to stay clean? 
no test support 
what events are bound to what components? 
maintaining high quality with many developers is difficult 
Javascript is becoming more important in mobile apps 
© 2014 INFINIT GmbH 4
Motivation for AngularJS 
UI experience of Single Page Applications 
Elegant programmers model based on JavaScript: 
Model View Whatever pattern 
Dependency Injection 
Modularization using modules, directives 
Testing support 
Popularity and community support 
© 2014 INFINIT GmbH 5
What is new in Spring 4 
New project Spring Boot: Convention over Configuration 
Integrates with Spring Loaded: reloading classes and resources 
Approved, consistent and complete tool chain: 
Spring Core: Dependency Injection, 
Transaction Mgmt, testing, etc. 
Spring Data: Consistent approach 
to access data stores, Querydsl 
Spring Security 
… many more 
© 2014 INFINIT GmbH 6
The CV Database Application 
Source Code: https://bitbucket.org/infinit-group/cvdb 
Demo App: http://cvdb.elasticbeanstalk.com/ 
Application is as responsive as a desktop app 
CV Database is just complex enough for real-world template 
© 2014 INFINIT GmbH 7
Software Architecture 
© 2014 INFINIT GmbH 8
Client Tooling: JavaScript 
npm Node Packet Manager installs NodeJS packages 
Yeoman Code Generator generates AngularJS project skeleton from shell 
Grunt build tool executes tasks defined in JSON file (similar to ant) 
Bower dependency resolver fetches dependent JS components from Repos 
(similar to ivy) 
Karma test driver runs JS tests in JS engine 
(e.g. phantomjs, Browser with plugin) 
Jasmine testing Framework tests are written in Jasmine format (similar to Spock) 
JSHint JavaScript validator ensures good JavaScript code style (IDE integration) 
JavaScript uses its own optimized toolchain! 
-> Bad idea: use java tools like maven, junit, … 
© 2014 INFINIT GmbH 9
Server Tooling: Java 
gradle build tool incl. dependency resolver, test driver 
gradle grunt plugin maps grunt tasks onto gradle tasks 
spring-boot gradle plugin adds Spring Boot specific tasks 
Spring Boot Convention over Configuration Framework 
Embedded Tomcat servlet container managed by Spring Boot 
Gradle is used as master build system: 
orchestrates grunt and builds Java 
© 2014 INFINIT GmbH 10
Overall Project Structure 
cvdb-client 
separate project for AngularJS client 
cvdb-server 
Spring based sever code that includes 
client WAR 
docker 
optionally packaging for Elastic 
Beanstalk 
slides 
these slides 
© 2014 INFINIT GmbH 11
Client Side - AngularJS Part 
views html fragments with AngularJS tags 
controllers two way binding view elements, 
actions, routing 
services singletons for business logic, 
DAO layer 
interceptors for request&responses 
(e.g. Security) 
directives componentization, 
encapsulation of DOM manipulations 
tests techniques to test all components 
other images, css, fonts, etc. 
© 2014 INFINIT GmbH 12
Enough Theory! Where is the Code? 
Note: For education the following code examples are simplifications taken from https://bitbucket.org/infinit-group/cvdb 
© 2014 INFINIT GmbH 13
The entry page: index.html 
<!doctype html>! 
<!-- Link body tag with AngularJS module (see app.js) -->! 
<body ng-app="cvdbClientApp">! 
! 
<!-- include html fragments -->! 
<div ng-include="'views/header.html'"></div>! 
© 2014 INFINIT GmbH 14 
! 
<!-- define main view used by routing (usage of $routeProvider)-->! 
<div class="container" ng-view=""></div>! 
! 
<!-- build:js script tags generated by grunt -->! 
<!-- external scripts retrieved by bower -->! 
<script src="bower_components/angular/angular.js"></script>! 
<!-- script files of the application -->! 
<script src="scripts/app.js"></script>! 
<script src="scripts/controllers/headercontroller.js"></script>! 
<!-- endbuild -->! 
</body>! 
</html> Using AngularJS to build a single page application
Central AngularJS Configuration: app.js 
// Definition of dependant modules! 
angular.module('cvdbClientApp', [! 
'ngRoute', // makes $routeProvider injectable! 
'ui.bootstrap'! 
])! 
.config(['$httpProvider', '$routeProvider', function ($httpProvider, $routeProvider) {! 
// Configuration phase - only providers injectable! 
© 2014 INFINIT GmbH 15 
! 
// Spring security will respond with a "WWW-Authenticate" header! 
// if the "X-Request-With" header is not sent in the request.! 
// This will in turn trigger a login popup in the browser.! 
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';! 
! 
$routeProvider! 
.otherwise({! 
// default view to be used if no other URL matcher fits! 
redirectTo: '/resume/list'! 
});! 
}])! 
.run(function () {! 
// bootstrap the application - only instances are injectable! 
/* global FastClick: false */! 
FastClick.attach(document.body);! 
});
AngularJS Controller: ResumeController.js 
angular.module('cvdbClientApp')! 
.config(['$routeProvider', function ($routeProvider) {! 
© 2014 INFINIT GmbH 16 
$routeProvider! 
.when('/resume/list', {! 
templateUrl: '/views/resume/list.html',! 
controller: 'ResumeListController'! 
})! 
}])! 
.controller('ResumeListController', ['$scope', '$location', 'ResumeService', function ($scope, 
$location, ResumeService) {! 
! 
// Actions live in the $scope hierarchy: one $scope per Controller! 
$scope.onRowClicked = function (row) {! 
// change browser URL, active Controller and view! 
$location.path('/resume/show/' + row.id);! 
};! 
! 
// ResumeService is used to load rows asynchronously! 
ResumeService.list().$promise.then(! 
// 'then' is called back when received response! 
function (result) {! 
// 'mode' is bindable from view! 
$scope.model = result;! 
});! 
};! 
}]); Routing URLs to Controllers
Associated HTML template: list.html 
<h2>Resumes</h2>! 
<p>! 
<!-- binding a button to a create action -->! 
<button class="btn btn-primary" ng-click="create()">! 
<i class="fa fa-plus fa-lg"></i> Add Resume! 
</button>! 
</p>! 
! 
<!-- table is rendered by custom directive -->! 
<!-- 'content' is a JSON element from the server response -->! 
<my-table rows="model.content" on-row-clicked="onRowClicked(row)">! 
</my-table> 
© 2014 INFINIT GmbH 17
Custom Directive for tables: mytable.js 
angular.module('cvdbClientApp')! 
.directive('myTable', function () {! 
return {! 
templateUrl: '/views/directives/mytable.html',! 
restrict: 'E', // directive applies to a html element! 
scope: {! 
rows: '=', // bind row attribute to directive's $scope! 
onRowClicked: '&' // bind attribute to function reference! 
},! 
controller: ['$scope', function ($scope) {! 
// called on click in row passing the row as parameter! 
$scope._onRowClicked = function (row) {! 
$scope.onRowClicked({row: row});! 
};! 
}]! 
};! 
}); 
© 2014 INFINIT GmbH 18
Directive’s HTML template: mytable.html 
<table>! 
<!-- iterate over rows and colums of directive's scope -->! 
<tr ng-repeat="row in rows" ng-click="_onRowClicked(row)">! 
<td ng-repeat="column in [0,1]">! 
{{row[column]}}! 
</td>! 
</tr>! 
</table> 
© 2014 INFINIT GmbH 19
Consuming Server Data: resumeservice.js 
angular.module('cvdbClientApp')! 
.service('ResumeService', ['$resource', function ($resource) {! 
this._apiUrl = '/api/resume'; // define the REST URL! 
this._apiUrlId = this._apiUrl + '/:id';! 
© 2014 INFINIT GmbH 20 
! 
this.list = function () {! 
// $resource encapsulates asynchronous REST calls! 
var resource = $resource(this._apiUrl);! 
return resource.get({page: 0, size: 1000});! 
};! 
! 
this.get = function (id) {! 
return $resource(this._apiUrlId).get({id: id});! 
};! 
! 
this.remove = function (id) {! 
return $resource(this._apiUrlId).delete({id: id});! 
};! 
! 
this.save = function (resume) {! 
return $resource(this._apiUrl).save(resume);! 
};! 
}]);
Authentication: responseinterceptor.js 
angular.module('cvdbClientApp')! 
.factory('responseInterceptor', ['$q', '$location', function($q, $location) {! 
return {! 
responseError: function (rejection) {! 
if (rejection.status === 401) {! 
$location.path('/auth/login');! 
} else {! 
console.log('Error processing request: '! 
+ rejection.statusText! 
+ ' [' + rejection.status + ']');! 
}! 
return $q.reject(rejection);! 
}! 
};! 
}])! 
.config(['$httpProvider', function ($httpProvider) {! 
$httpProvider.interceptors.push('responseInterceptor');! 
}]); 
© 2014 INFINIT GmbH 21
Server Side - Spring Part 
config Config Beans with Spring Configurers 
controller Spring MVC controllers 
domain folder for JPA-Entities 
repositories Spring Data repositories 
services Spring Beans with business logic 
utils.security Utility classes for Spring Security 
© 2014 INFINIT GmbH 22
Spring Configuration without XML 
@Configuration // annotation for configuration Bean! 
public class MyBeanDefinitions {! 
@Bean // annotation for bean definition! 
public PasswordEncoder passwordEncoder() {! 
// Method name = Bean name! 
// Method type = Bean type! 
// Spring calls the method to create the bean! 
return new StandardPasswordEncoder();! 
}! 
};! 
! 
@Component // annotation for a Spring Bean! 
public class MyBean {! 
@Autowired // Inject a Spring Bean! 
private PasswordEncoder passwordEncoder;! 
} 
© 2014 INFINIT GmbH 23
Spring Boot Configurations 
@EnableAutoConfiguration // Enable Magic! 
@Controller // Define MVC Controller! 
public class SampleController {! 
@RequestMapping("/")! 
@ResponseBody! 
String home() {! 
return "Hello World!";! 
}! 
© 2014 INFINIT GmbH 24 
! 
public static void main(String[] args) throws Exception {! 
SpringApplication.run(SampleController.class, args);! 
}! 
} 
An extreme simple but working Spring MVC application!
@EnableAutoConfiguration 
/**! 
Enable auto-configuration of the Spring Application Context,! 
attempting to guess and configure beans that you are likely to need.! 
Auto-configuration classes are usually applied based on your! 
classpath and what beans you have defined.! 
**/ 
Our Experience: Using Convention over Configuration you can create applications efficiently. 
But you have to know the Conventions! 
© 2014 INFINIT GmbH 25
Spring’s Convention Implementation [1] 
@Configuration! 
// ...! 
public class WebMvcAutoConfiguration {! 
// ...! 
@Bean! 
@ConditionalOnMissingBean(RequestContextListener.class)! 
public RequestContextListener requestContextListener() {! 
return new RequestContextListener();! 
}! 
// ...! 
} Conditional configurations: Sprint Boot Beans are only used 
if Bean with that class is not yet contained in BeanFactory. 
© 2014 INFINIT GmbH 26
Spring’s Convention Implementation [2] 
@Configuration! 
public class Security extends WebSecurityConfigurerAdapter {! 
// ...! 
@Override // Override standard configurations! 
protected void configure(final HttpSecurity http)! 
throws Exception {! 
http! 
.httpBasic() // basic authentication shall be used! 
http! 
.rememberMe(); // rememberMe cookies shall be honoured! 
http! 
.csrf().disable() // disable XSS checks with static pages! 
.authorizeRequests() // define request authorization! 
// admins can monitor! 
.antMatchers("/monitoring/**").hasRole("ADMIN")! 
// API calls must be authenticated! 
.antMatchers("/api/**").authenticated()! 
// static content is allowed for anyone - use a CDN!! 
.anyRequest().permitAll()! 
}! 
// ...! 
} Security Configurers based on @Override 
© 2014 INFINIT GmbH 27
Spring Data 
"Makes it easy to use new data access technologies, such 
as non-relational databases" 
Spring Data JPA: 
part of the larger Spring Data family […] makes it easy to 
implement JPA based repositories. 
© 2014 INFINIT GmbH 28
JPA Repositories 
© 2014 INFINIT GmbH 29 
public interface UserRepository! 
extends PagingAndSortingRepository<User, Long> {! 
! User findByUsername(String username);! 
}! 
! 
// Spring Code below this line:! 
public interface PagingAndSortingRepository<T, ID extends Serializable> extends 
CrudRepository<T, ID> {! 
! Iterable<T> findAll(Sort sort);! 
! Page<T> findAll(Pageable pageable);! 
}! 
! 
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {! 
<S extends T> S save(S entity); // save the entity! 
T findOne(ID id); // lookup the entity! 
void delete(T entity); // delete the entity! 
// and many other methods...! 
} 
Define a custom interface and Spring 
creates the DAO implementation
Implementing Custom DAO Methods 
// create a custom interface for the custom DAO method! 
public interface ResumeRepositoryCustom {! 
// custom DAO method! 
Page<Resume> search(String search, Pageable pageable);! 
}! 
! 
// create an implementation class ending with "Impl"! 
public class ResumeRepositoryImpl! 
implements ResumeRepositoryCustom {! 
@Override! 
public Page<Resume> search(String search, Pageable pageable) {! 
// perform custom query and return result page! 
// removed for simplicity! 
}! 
}! 
! 
// extend Spring Repository and custom implementation! 
public interface ResumeRepository! 
extends PagingAndSortingRepository<Resume, Long>,! 
ResumeRepositoryCustom {! 
} 
© 2014 INFINIT GmbH 30
QueryDSL for SQL Queries 
Motivation: JPA has some significant disadvantages: 
JPQL String concatenation leads to mess: 
no Compiler or IDE-Support 
CriteriaBuilder is unreadable for queries of relevant size 
Native queries are way more powerful than JPA queries 
QueryDSL is a DB-Query Technology that is: 
Type Safe (in contrast to String concatenation) 
Readable (in contrast to CriteriaBuilder API) 
Supports for JPA queries and native queries 
© 2014 INFINIT GmbH 31
QueryDSL Example 
// Query using JPA EntityManager! 
JPQLQuery query = new JPAQuery (entityManager);! 
cats = query.from(cat)! 
.innerJoin(cat.mate, mate)! 
.orderBy(cat.name.asc())! 
.list(cat);! 
! 
// Query and project into DTO! 
query = new JPASQLQuery(entityManager, templates);! 
List<CatDTO> catDTOs = query.from(cat)! 
.orderBy(cat.name.asc())! 
.list(EConstructor.create(CatDTO.class, cat.id, cat.name));! 
! 
// Query in SQL, but project as entity! 
query = new JPASQLQuery(entityManager, templates);! 
cats = query.from(cat)! 
.innerJoin(mate).on(cat.mateId.eq(mate.id))! 
.where(cat.dtype.eq("Cat"), mate.dtype.eq("Cat"))! 
.list(catEntity); 
QueryDSL allows: 
type save queries 
complex subselects 
returning entities or DTOs 
© 2014 INFINIT GmbH 32
QueryDSL Drawback 
Sourcecode Generator is Needed: 
generated Java Source Code contains Entity metadata 
QueryDSL uses the Java-Compiler with an 
JPAAnnotationProcessor to perform this 
cvdb contains a querdsl.gradle file to illustrate the usage. 
© 2014 INFINIT GmbH 33
QueryDSL Integration with Spring 
// Implement Custom Query! 
public interface ResumeRepositoryCustom {! 
Page<Resume> search(String search, Pageable pageable);! 
}! 
! 
// Use QueryDsl! 
public class ResumeRepositoryImpl implements ResumeRepositoryCustom {! 
@Autowired! 
© 2014 INFINIT GmbH 34 
private ResumeRepository resumeRepository;! 
! 
@Override! 
public Page<Resume> search(String search, Pageable pageable) {! 
QResume resume = QResume.resume;! 
Predicate predicate =! 
resume.firstName.containsIgnoreCase(search).! 
or(resume.lastName.containsIgnoreCase(search));! 
return resumeRepository.findAll(predicate, pageable);! 
}! 
}! 
! 
// Spring generates an Implementation for the ResumeRepository! 
public interface ResumeRepository extends! 
PagingAndSortingRepository<Resume, Long>,! 
QueryDslPredicateExecutor<Resume>,! 
ResumeRepositoryCustom {! 
}
Hot Code Replacement also known as Hot Swapping 
Allows exchanging of classes and/or resources in a running application or 
debugging session. 
© 2014 INFINIT GmbH 
! 
! 
! 
! 
! 
Spring-Loaded can reload class definitions with changed method signatures 
Similar to JRebel but less powerfull 
Integrated in gradle bootRun 
35 
Hot Code Replacement
Testing with Spring 
IoC is available in tests 
Profiles allow custom test injection setup 
Database can be used for integration tests 
MockServlet available 
© 2014 INFINIT GmbH 36
Profiles and Properties 
@ContextConfiguration(classes = TestApplication,! 
loader = SpringApplicationContextLoader)! 
@ActiveProfiles("test") // activate test profile! 
@Transactional // rollback after each test method! 
abstract class TestSpec extends Specification {! 
} 
Test Baseclass 
spring.datasource.driverClassName=org.h2.Driver! 
spring.datasource.password=! 
spring.datasource.url=jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000! 
spring.datasource.username=sa! 
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect! 
spring.jpa.hibernate.ddl-auto=create! 
spring.jpa.show-sql=false 
application-test.properties 
© 2014 INFINIT GmbH 37
Testing Controllers 
def "get resume should get 20 results"() {! 
when:! 
ResultActions result = mockMvc.perform(get('/api/resume')! 
.contentType(MediaType.APPLICATION_JSON)! 
)! 
© 2014 INFINIT GmbH 38 
! 
then:! 
result.andExpect(status().isOk())! 
result.andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8))! 
result.andExpect(jsonPath('$.content', hasSize(20)))! 
}
Conclusion 
AngularJS 
removes server state 
enables native application experience 
puts view logic into Javascript 
requires new skill profiles and processes 
! 
Spring 4 
introduces Convention over Configuration with Spring Boot 
comes with ecosystem of sub projects 
allows for efficient development 
© 2014 INFINIT GmbH 39
Thank Your For Your Attention 
Visit Us 
Van-der-Smissen-Straße 3 
22767 Hamburg 
! 
Tel: +49 (0)40 38 65 18 80 
Fax: +49 (0)40 38 65 18 81 
! 
Web: www.infinit-group.de 
E-Mail: info@infinit-group.de 
© 2014 INFINIT GmbH 40

More Related Content

What's hot

Spring Portlet MVC
Spring Portlet MVCSpring Portlet MVC
Spring Portlet MVCJohn Lewis
 
Create Restful Web Application With Node.js Express Framework
Create Restful Web Application With Node.js Express FrameworkCreate Restful Web Application With Node.js Express Framework
Create Restful Web Application With Node.js Express FrameworkEdureka!
 
Vue 2.0 + Vuex Router & Vuex at Vue.js
Vue 2.0 + Vuex Router & Vuex at Vue.jsVue 2.0 + Vuex Router & Vuex at Vue.js
Vue 2.0 + Vuex Router & Vuex at Vue.jsTakuya Tejima
 
Refactor Large applications with Backbone
Refactor Large applications with BackboneRefactor Large applications with Backbone
Refactor Large applications with BackboneColdFusionConference
 
Design & Development of Web Applications using SpringMVC
Design & Development of Web Applications using SpringMVC Design & Development of Web Applications using SpringMVC
Design & Development of Web Applications using SpringMVC Naresh Chintalcheru
 
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...Luciano Mammino
 
Java EE 8: On the Horizon
Java EE 8:  On the HorizonJava EE 8:  On the Horizon
Java EE 8: On the HorizonJosh Juneau
 
Introduction to Vaadin
Introduction to VaadinIntroduction to Vaadin
Introduction to Vaadinnetomi
 
Spring andspringboot training
Spring andspringboot trainingSpring andspringboot training
Spring andspringboot trainingMallikarjuna G D
 
Spring Web Service, Spring JMS, Eclipse & Maven tutorials
Spring Web Service, Spring JMS, Eclipse & Maven tutorialsSpring Web Service, Spring JMS, Eclipse & Maven tutorials
Spring Web Service, Spring JMS, Eclipse & Maven tutorialsRaghavan Mohan
 
Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까장현 한
 
2015 JavaOne LAD JSF 2.3 & MVC 1.0
2015 JavaOne LAD JSF 2.3 & MVC 1.02015 JavaOne LAD JSF 2.3 & MVC 1.0
2015 JavaOne LAD JSF 2.3 & MVC 1.0mnriem
 
Javascript MVVM with Vue.JS
Javascript MVVM with Vue.JSJavascript MVVM with Vue.JS
Javascript MVVM with Vue.JSEueung Mulyana
 

What's hot (20)

Spring Portlet MVC
Spring Portlet MVCSpring Portlet MVC
Spring Portlet MVC
 
JSF 2.2
JSF 2.2JSF 2.2
JSF 2.2
 
Reactjs Basics
Reactjs BasicsReactjs Basics
Reactjs Basics
 
Create Restful Web Application With Node.js Express Framework
Create Restful Web Application With Node.js Express FrameworkCreate Restful Web Application With Node.js Express Framework
Create Restful Web Application With Node.js Express Framework
 
Vue 2.0 + Vuex Router & Vuex at Vue.js
Vue 2.0 + Vuex Router & Vuex at Vue.jsVue 2.0 + Vuex Router & Vuex at Vue.js
Vue 2.0 + Vuex Router & Vuex at Vue.js
 
Refactor Large applications with Backbone
Refactor Large applications with BackboneRefactor Large applications with Backbone
Refactor Large applications with Backbone
 
Design & Development of Web Applications using SpringMVC
Design & Development of Web Applications using SpringMVC Design & Development of Web Applications using SpringMVC
Design & Development of Web Applications using SpringMVC
 
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
Universal JS Web Applications with React - Luciano Mammino - Codemotion Rome ...
 
Spring boot jpa
Spring boot jpaSpring boot jpa
Spring boot jpa
 
Java EE 8: On the Horizon
Java EE 8:  On the HorizonJava EE 8:  On the Horizon
Java EE 8: On the Horizon
 
Why Vue.js?
Why Vue.js?Why Vue.js?
Why Vue.js?
 
Introduction to Vaadin
Introduction to VaadinIntroduction to Vaadin
Introduction to Vaadin
 
Spring andspringboot training
Spring andspringboot trainingSpring andspringboot training
Spring andspringboot training
 
Spring Web Service, Spring JMS, Eclipse & Maven tutorials
Spring Web Service, Spring JMS, Eclipse & Maven tutorialsSpring Web Service, Spring JMS, Eclipse & Maven tutorials
Spring Web Service, Spring JMS, Eclipse & Maven tutorials
 
Getting started with angular js
Getting started with angular jsGetting started with angular js
Getting started with angular js
 
Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까Angular 2 어디까지 왔을까
Angular 2 어디까지 왔을까
 
2015 JavaOne LAD JSF 2.3 & MVC 1.0
2015 JavaOne LAD JSF 2.3 & MVC 1.02015 JavaOne LAD JSF 2.3 & MVC 1.0
2015 JavaOne LAD JSF 2.3 & MVC 1.0
 
Javascript MVVM with Vue.JS
Javascript MVVM with Vue.JSJavascript MVVM with Vue.JS
Javascript MVVM with Vue.JS
 
Spring mvc
Spring mvcSpring mvc
Spring mvc
 
Booting up with polymer
Booting up with polymerBooting up with polymer
Booting up with polymer
 

Similar to Testdrive AngularJS with Spring 4

A gently introduction to AngularJS
A gently introduction to AngularJSA gently introduction to AngularJS
A gently introduction to AngularJSGregor Woiwode
 
Isomorphic JavaScript: #DevBeat Master Class
Isomorphic JavaScript: #DevBeat Master ClassIsomorphic JavaScript: #DevBeat Master Class
Isomorphic JavaScript: #DevBeat Master ClassSpike Brehm
 
Tutorial: Develop Mobile Applications with AngularJS
Tutorial: Develop Mobile Applications with AngularJSTutorial: Develop Mobile Applications with AngularJS
Tutorial: Develop Mobile Applications with AngularJSPhilipp Burgmer
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSAntonio Peric-Mazar
 
Developing a Demo Application with Angular 4 - J2I
Developing a Demo Application with Angular 4 - J2IDeveloping a Demo Application with Angular 4 - J2I
Developing a Demo Application with Angular 4 - J2INader Debbabi
 
WJAX 2012 - Web Apps With AngularJS
WJAX 2012 - Web Apps With AngularJSWJAX 2012 - Web Apps With AngularJS
WJAX 2012 - Web Apps With AngularJSPhilipp Burgmer
 
Refactoring JavaScript Applications
Refactoring JavaScript ApplicationsRefactoring JavaScript Applications
Refactoring JavaScript ApplicationsJovan Vidić
 
Introduction to angular js for .net developers
Introduction to angular js  for .net developersIntroduction to angular js  for .net developers
Introduction to angular js for .net developersMohd Manzoor Ahmed
 
Android Development : (Android Studio, PHP, XML, MySQL)
Android Development : (Android Studio, PHP, XML, MySQL)Android Development : (Android Studio, PHP, XML, MySQL)
Android Development : (Android Studio, PHP, XML, MySQL)Kavya Barnadhya Hazarika
 
Angularjs Tutorial for Beginners
Angularjs Tutorial for BeginnersAngularjs Tutorial for Beginners
Angularjs Tutorial for Beginnersrajkamaltibacademy
 
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJS
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJSKarlsruher Entwicklertag 2013 - Webanwendungen mit AngularJS
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJSPhilipp Burgmer
 

Similar to Testdrive AngularJS with Spring 4 (20)

A gently introduction to AngularJS
A gently introduction to AngularJSA gently introduction to AngularJS
A gently introduction to AngularJS
 
Mean stack Magics
Mean stack MagicsMean stack Magics
Mean stack Magics
 
Isomorphic JavaScript: #DevBeat Master Class
Isomorphic JavaScript: #DevBeat Master ClassIsomorphic JavaScript: #DevBeat Master Class
Isomorphic JavaScript: #DevBeat Master Class
 
Tutorial: Develop Mobile Applications with AngularJS
Tutorial: Develop Mobile Applications with AngularJSTutorial: Develop Mobile Applications with AngularJS
Tutorial: Develop Mobile Applications with AngularJS
 
IOT strategy
IOT strategyIOT strategy
IOT strategy
 
SF Cordova Meetup
SF Cordova MeetupSF Cordova Meetup
SF Cordova Meetup
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJS
 
Developing a Demo Application with Angular 4 - J2I
Developing a Demo Application with Angular 4 - J2IDeveloping a Demo Application with Angular 4 - J2I
Developing a Demo Application with Angular 4 - J2I
 
WJAX 2012 - Web Apps With AngularJS
WJAX 2012 - Web Apps With AngularJSWJAX 2012 - Web Apps With AngularJS
WJAX 2012 - Web Apps With AngularJS
 
Sst hackathon express
Sst hackathon expressSst hackathon express
Sst hackathon express
 
Refactoring JavaScript Applications
Refactoring JavaScript ApplicationsRefactoring JavaScript Applications
Refactoring JavaScript Applications
 
AngularJS 101
AngularJS 101AngularJS 101
AngularJS 101
 
Introduction to angular js for .net developers
Introduction to angular js  for .net developersIntroduction to angular js  for .net developers
Introduction to angular js for .net developers
 
Training On Angular Js
Training On Angular JsTraining On Angular Js
Training On Angular Js
 
Android Development : (Android Studio, PHP, XML, MySQL)
Android Development : (Android Studio, PHP, XML, MySQL)Android Development : (Android Studio, PHP, XML, MySQL)
Android Development : (Android Studio, PHP, XML, MySQL)
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
 
ParisJS #10 : RequireJS
ParisJS #10 : RequireJSParisJS #10 : RequireJS
ParisJS #10 : RequireJS
 
Akash Damniya
Akash DamniyaAkash Damniya
Akash Damniya
 
Angularjs Tutorial for Beginners
Angularjs Tutorial for BeginnersAngularjs Tutorial for Beginners
Angularjs Tutorial for Beginners
 
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJS
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJSKarlsruher Entwicklertag 2013 - Webanwendungen mit AngularJS
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJS
 

Recently uploaded

Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsSafe Software
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxAndreas Kunz
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZABSYZ Inc
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 

Recently uploaded (20)

Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data Streams
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZ
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 

Testdrive AngularJS with Spring 4

  • 1. Testdrive AngularJS with Spring 4 Dr. Oliver Wahlen oliver.wahlen@infinit-group.de ! September 2014 © 2014 INFINIT GmbH 1
  • 2. Motivation INFINIT creates software products for customers Specialized on Java server and mobile technology Hardware & Software are constantly improving at all levels Market success of fixed price projects = Efficiency + Quality We are constantly improving our processes and tools It’s Fun!!! © 2014 INFINIT GmbH 2
  • 3. Challenges of JavaEE projects using EJB and JSF… fixed component set (xxxFaces) is difficult to customize slow due to JSF lifecycle / application state hard to integrate with pure Javascript does not scale because sessions are huge no integrated testing concept: views, unit, integration, function variety of IoC frameworks with different constraints (JSF, EJB, CDI) slow development roundtrips (no hot reloading, monolithic App Server) © 2014 INFINIT GmbH 3
  • 4. Challenges of JavaScript projects pure jQuery is no good idea: no structure by convention: how to stay clean? no test support what events are bound to what components? maintaining high quality with many developers is difficult Javascript is becoming more important in mobile apps © 2014 INFINIT GmbH 4
  • 5. Motivation for AngularJS UI experience of Single Page Applications Elegant programmers model based on JavaScript: Model View Whatever pattern Dependency Injection Modularization using modules, directives Testing support Popularity and community support © 2014 INFINIT GmbH 5
  • 6. What is new in Spring 4 New project Spring Boot: Convention over Configuration Integrates with Spring Loaded: reloading classes and resources Approved, consistent and complete tool chain: Spring Core: Dependency Injection, Transaction Mgmt, testing, etc. Spring Data: Consistent approach to access data stores, Querydsl Spring Security … many more © 2014 INFINIT GmbH 6
  • 7. The CV Database Application Source Code: https://bitbucket.org/infinit-group/cvdb Demo App: http://cvdb.elasticbeanstalk.com/ Application is as responsive as a desktop app CV Database is just complex enough for real-world template © 2014 INFINIT GmbH 7
  • 8. Software Architecture © 2014 INFINIT GmbH 8
  • 9. Client Tooling: JavaScript npm Node Packet Manager installs NodeJS packages Yeoman Code Generator generates AngularJS project skeleton from shell Grunt build tool executes tasks defined in JSON file (similar to ant) Bower dependency resolver fetches dependent JS components from Repos (similar to ivy) Karma test driver runs JS tests in JS engine (e.g. phantomjs, Browser with plugin) Jasmine testing Framework tests are written in Jasmine format (similar to Spock) JSHint JavaScript validator ensures good JavaScript code style (IDE integration) JavaScript uses its own optimized toolchain! -> Bad idea: use java tools like maven, junit, … © 2014 INFINIT GmbH 9
  • 10. Server Tooling: Java gradle build tool incl. dependency resolver, test driver gradle grunt plugin maps grunt tasks onto gradle tasks spring-boot gradle plugin adds Spring Boot specific tasks Spring Boot Convention over Configuration Framework Embedded Tomcat servlet container managed by Spring Boot Gradle is used as master build system: orchestrates grunt and builds Java © 2014 INFINIT GmbH 10
  • 11. Overall Project Structure cvdb-client separate project for AngularJS client cvdb-server Spring based sever code that includes client WAR docker optionally packaging for Elastic Beanstalk slides these slides © 2014 INFINIT GmbH 11
  • 12. Client Side - AngularJS Part views html fragments with AngularJS tags controllers two way binding view elements, actions, routing services singletons for business logic, DAO layer interceptors for request&responses (e.g. Security) directives componentization, encapsulation of DOM manipulations tests techniques to test all components other images, css, fonts, etc. © 2014 INFINIT GmbH 12
  • 13. Enough Theory! Where is the Code? Note: For education the following code examples are simplifications taken from https://bitbucket.org/infinit-group/cvdb © 2014 INFINIT GmbH 13
  • 14. The entry page: index.html <!doctype html>! <!-- Link body tag with AngularJS module (see app.js) -->! <body ng-app="cvdbClientApp">! ! <!-- include html fragments -->! <div ng-include="'views/header.html'"></div>! © 2014 INFINIT GmbH 14 ! <!-- define main view used by routing (usage of $routeProvider)-->! <div class="container" ng-view=""></div>! ! <!-- build:js script tags generated by grunt -->! <!-- external scripts retrieved by bower -->! <script src="bower_components/angular/angular.js"></script>! <!-- script files of the application -->! <script src="scripts/app.js"></script>! <script src="scripts/controllers/headercontroller.js"></script>! <!-- endbuild -->! </body>! </html> Using AngularJS to build a single page application
  • 15. Central AngularJS Configuration: app.js // Definition of dependant modules! angular.module('cvdbClientApp', [! 'ngRoute', // makes $routeProvider injectable! 'ui.bootstrap'! ])! .config(['$httpProvider', '$routeProvider', function ($httpProvider, $routeProvider) {! // Configuration phase - only providers injectable! © 2014 INFINIT GmbH 15 ! // Spring security will respond with a "WWW-Authenticate" header! // if the "X-Request-With" header is not sent in the request.! // This will in turn trigger a login popup in the browser.! $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';! ! $routeProvider! .otherwise({! // default view to be used if no other URL matcher fits! redirectTo: '/resume/list'! });! }])! .run(function () {! // bootstrap the application - only instances are injectable! /* global FastClick: false */! FastClick.attach(document.body);! });
  • 16. AngularJS Controller: ResumeController.js angular.module('cvdbClientApp')! .config(['$routeProvider', function ($routeProvider) {! © 2014 INFINIT GmbH 16 $routeProvider! .when('/resume/list', {! templateUrl: '/views/resume/list.html',! controller: 'ResumeListController'! })! }])! .controller('ResumeListController', ['$scope', '$location', 'ResumeService', function ($scope, $location, ResumeService) {! ! // Actions live in the $scope hierarchy: one $scope per Controller! $scope.onRowClicked = function (row) {! // change browser URL, active Controller and view! $location.path('/resume/show/' + row.id);! };! ! // ResumeService is used to load rows asynchronously! ResumeService.list().$promise.then(! // 'then' is called back when received response! function (result) {! // 'mode' is bindable from view! $scope.model = result;! });! };! }]); Routing URLs to Controllers
  • 17. Associated HTML template: list.html <h2>Resumes</h2>! <p>! <!-- binding a button to a create action -->! <button class="btn btn-primary" ng-click="create()">! <i class="fa fa-plus fa-lg"></i> Add Resume! </button>! </p>! ! <!-- table is rendered by custom directive -->! <!-- 'content' is a JSON element from the server response -->! <my-table rows="model.content" on-row-clicked="onRowClicked(row)">! </my-table> © 2014 INFINIT GmbH 17
  • 18. Custom Directive for tables: mytable.js angular.module('cvdbClientApp')! .directive('myTable', function () {! return {! templateUrl: '/views/directives/mytable.html',! restrict: 'E', // directive applies to a html element! scope: {! rows: '=', // bind row attribute to directive's $scope! onRowClicked: '&' // bind attribute to function reference! },! controller: ['$scope', function ($scope) {! // called on click in row passing the row as parameter! $scope._onRowClicked = function (row) {! $scope.onRowClicked({row: row});! };! }]! };! }); © 2014 INFINIT GmbH 18
  • 19. Directive’s HTML template: mytable.html <table>! <!-- iterate over rows and colums of directive's scope -->! <tr ng-repeat="row in rows" ng-click="_onRowClicked(row)">! <td ng-repeat="column in [0,1]">! {{row[column]}}! </td>! </tr>! </table> © 2014 INFINIT GmbH 19
  • 20. Consuming Server Data: resumeservice.js angular.module('cvdbClientApp')! .service('ResumeService', ['$resource', function ($resource) {! this._apiUrl = '/api/resume'; // define the REST URL! this._apiUrlId = this._apiUrl + '/:id';! © 2014 INFINIT GmbH 20 ! this.list = function () {! // $resource encapsulates asynchronous REST calls! var resource = $resource(this._apiUrl);! return resource.get({page: 0, size: 1000});! };! ! this.get = function (id) {! return $resource(this._apiUrlId).get({id: id});! };! ! this.remove = function (id) {! return $resource(this._apiUrlId).delete({id: id});! };! ! this.save = function (resume) {! return $resource(this._apiUrl).save(resume);! };! }]);
  • 21. Authentication: responseinterceptor.js angular.module('cvdbClientApp')! .factory('responseInterceptor', ['$q', '$location', function($q, $location) {! return {! responseError: function (rejection) {! if (rejection.status === 401) {! $location.path('/auth/login');! } else {! console.log('Error processing request: '! + rejection.statusText! + ' [' + rejection.status + ']');! }! return $q.reject(rejection);! }! };! }])! .config(['$httpProvider', function ($httpProvider) {! $httpProvider.interceptors.push('responseInterceptor');! }]); © 2014 INFINIT GmbH 21
  • 22. Server Side - Spring Part config Config Beans with Spring Configurers controller Spring MVC controllers domain folder for JPA-Entities repositories Spring Data repositories services Spring Beans with business logic utils.security Utility classes for Spring Security © 2014 INFINIT GmbH 22
  • 23. Spring Configuration without XML @Configuration // annotation for configuration Bean! public class MyBeanDefinitions {! @Bean // annotation for bean definition! public PasswordEncoder passwordEncoder() {! // Method name = Bean name! // Method type = Bean type! // Spring calls the method to create the bean! return new StandardPasswordEncoder();! }! };! ! @Component // annotation for a Spring Bean! public class MyBean {! @Autowired // Inject a Spring Bean! private PasswordEncoder passwordEncoder;! } © 2014 INFINIT GmbH 23
  • 24. Spring Boot Configurations @EnableAutoConfiguration // Enable Magic! @Controller // Define MVC Controller! public class SampleController {! @RequestMapping("/")! @ResponseBody! String home() {! return "Hello World!";! }! © 2014 INFINIT GmbH 24 ! public static void main(String[] args) throws Exception {! SpringApplication.run(SampleController.class, args);! }! } An extreme simple but working Spring MVC application!
  • 25. @EnableAutoConfiguration /**! Enable auto-configuration of the Spring Application Context,! attempting to guess and configure beans that you are likely to need.! Auto-configuration classes are usually applied based on your! classpath and what beans you have defined.! **/ Our Experience: Using Convention over Configuration you can create applications efficiently. But you have to know the Conventions! © 2014 INFINIT GmbH 25
  • 26. Spring’s Convention Implementation [1] @Configuration! // ...! public class WebMvcAutoConfiguration {! // ...! @Bean! @ConditionalOnMissingBean(RequestContextListener.class)! public RequestContextListener requestContextListener() {! return new RequestContextListener();! }! // ...! } Conditional configurations: Sprint Boot Beans are only used if Bean with that class is not yet contained in BeanFactory. © 2014 INFINIT GmbH 26
  • 27. Spring’s Convention Implementation [2] @Configuration! public class Security extends WebSecurityConfigurerAdapter {! // ...! @Override // Override standard configurations! protected void configure(final HttpSecurity http)! throws Exception {! http! .httpBasic() // basic authentication shall be used! http! .rememberMe(); // rememberMe cookies shall be honoured! http! .csrf().disable() // disable XSS checks with static pages! .authorizeRequests() // define request authorization! // admins can monitor! .antMatchers("/monitoring/**").hasRole("ADMIN")! // API calls must be authenticated! .antMatchers("/api/**").authenticated()! // static content is allowed for anyone - use a CDN!! .anyRequest().permitAll()! }! // ...! } Security Configurers based on @Override © 2014 INFINIT GmbH 27
  • 28. Spring Data "Makes it easy to use new data access technologies, such as non-relational databases" Spring Data JPA: part of the larger Spring Data family […] makes it easy to implement JPA based repositories. © 2014 INFINIT GmbH 28
  • 29. JPA Repositories © 2014 INFINIT GmbH 29 public interface UserRepository! extends PagingAndSortingRepository<User, Long> {! ! User findByUsername(String username);! }! ! // Spring Code below this line:! public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {! ! Iterable<T> findAll(Sort sort);! ! Page<T> findAll(Pageable pageable);! }! ! public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {! <S extends T> S save(S entity); // save the entity! T findOne(ID id); // lookup the entity! void delete(T entity); // delete the entity! // and many other methods...! } Define a custom interface and Spring creates the DAO implementation
  • 30. Implementing Custom DAO Methods // create a custom interface for the custom DAO method! public interface ResumeRepositoryCustom {! // custom DAO method! Page<Resume> search(String search, Pageable pageable);! }! ! // create an implementation class ending with "Impl"! public class ResumeRepositoryImpl! implements ResumeRepositoryCustom {! @Override! public Page<Resume> search(String search, Pageable pageable) {! // perform custom query and return result page! // removed for simplicity! }! }! ! // extend Spring Repository and custom implementation! public interface ResumeRepository! extends PagingAndSortingRepository<Resume, Long>,! ResumeRepositoryCustom {! } © 2014 INFINIT GmbH 30
  • 31. QueryDSL for SQL Queries Motivation: JPA has some significant disadvantages: JPQL String concatenation leads to mess: no Compiler or IDE-Support CriteriaBuilder is unreadable for queries of relevant size Native queries are way more powerful than JPA queries QueryDSL is a DB-Query Technology that is: Type Safe (in contrast to String concatenation) Readable (in contrast to CriteriaBuilder API) Supports for JPA queries and native queries © 2014 INFINIT GmbH 31
  • 32. QueryDSL Example // Query using JPA EntityManager! JPQLQuery query = new JPAQuery (entityManager);! cats = query.from(cat)! .innerJoin(cat.mate, mate)! .orderBy(cat.name.asc())! .list(cat);! ! // Query and project into DTO! query = new JPASQLQuery(entityManager, templates);! List<CatDTO> catDTOs = query.from(cat)! .orderBy(cat.name.asc())! .list(EConstructor.create(CatDTO.class, cat.id, cat.name));! ! // Query in SQL, but project as entity! query = new JPASQLQuery(entityManager, templates);! cats = query.from(cat)! .innerJoin(mate).on(cat.mateId.eq(mate.id))! .where(cat.dtype.eq("Cat"), mate.dtype.eq("Cat"))! .list(catEntity); QueryDSL allows: type save queries complex subselects returning entities or DTOs © 2014 INFINIT GmbH 32
  • 33. QueryDSL Drawback Sourcecode Generator is Needed: generated Java Source Code contains Entity metadata QueryDSL uses the Java-Compiler with an JPAAnnotationProcessor to perform this cvdb contains a querdsl.gradle file to illustrate the usage. © 2014 INFINIT GmbH 33
  • 34. QueryDSL Integration with Spring // Implement Custom Query! public interface ResumeRepositoryCustom {! Page<Resume> search(String search, Pageable pageable);! }! ! // Use QueryDsl! public class ResumeRepositoryImpl implements ResumeRepositoryCustom {! @Autowired! © 2014 INFINIT GmbH 34 private ResumeRepository resumeRepository;! ! @Override! public Page<Resume> search(String search, Pageable pageable) {! QResume resume = QResume.resume;! Predicate predicate =! resume.firstName.containsIgnoreCase(search).! or(resume.lastName.containsIgnoreCase(search));! return resumeRepository.findAll(predicate, pageable);! }! }! ! // Spring generates an Implementation for the ResumeRepository! public interface ResumeRepository extends! PagingAndSortingRepository<Resume, Long>,! QueryDslPredicateExecutor<Resume>,! ResumeRepositoryCustom {! }
  • 35. Hot Code Replacement also known as Hot Swapping Allows exchanging of classes and/or resources in a running application or debugging session. © 2014 INFINIT GmbH ! ! ! ! ! Spring-Loaded can reload class definitions with changed method signatures Similar to JRebel but less powerfull Integrated in gradle bootRun 35 Hot Code Replacement
  • 36. Testing with Spring IoC is available in tests Profiles allow custom test injection setup Database can be used for integration tests MockServlet available © 2014 INFINIT GmbH 36
  • 37. Profiles and Properties @ContextConfiguration(classes = TestApplication,! loader = SpringApplicationContextLoader)! @ActiveProfiles("test") // activate test profile! @Transactional // rollback after each test method! abstract class TestSpec extends Specification {! } Test Baseclass spring.datasource.driverClassName=org.h2.Driver! spring.datasource.password=! spring.datasource.url=jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000! spring.datasource.username=sa! spring.jpa.database-platform=org.hibernate.dialect.H2Dialect! spring.jpa.hibernate.ddl-auto=create! spring.jpa.show-sql=false application-test.properties © 2014 INFINIT GmbH 37
  • 38. Testing Controllers def "get resume should get 20 results"() {! when:! ResultActions result = mockMvc.perform(get('/api/resume')! .contentType(MediaType.APPLICATION_JSON)! )! © 2014 INFINIT GmbH 38 ! then:! result.andExpect(status().isOk())! result.andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8))! result.andExpect(jsonPath('$.content', hasSize(20)))! }
  • 39. Conclusion AngularJS removes server state enables native application experience puts view logic into Javascript requires new skill profiles and processes ! Spring 4 introduces Convention over Configuration with Spring Boot comes with ecosystem of sub projects allows for efficient development © 2014 INFINIT GmbH 39
  • 40. Thank Your For Your Attention Visit Us Van-der-Smissen-Straße 3 22767 Hamburg ! Tel: +49 (0)40 38 65 18 80 Fax: +49 (0)40 38 65 18 81 ! Web: www.infinit-group.de E-Mail: info@infinit-group.de © 2014 INFINIT GmbH 40