Great Single Page Apps Need Great Backends
description
Transcript of Great Single Page Apps Need Great Backends
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Great Single Page Apps Need Great
Backends
Adib Saikali - @asaikali
https://bitbucket.org/asaikali/springone-2014
About me
• Sr. Field Engineer at Pivotal
• Long time Spring user
• Passionate about technology and entrepreneurship
2
Where did this talk come from?
• My most recent production web application featured
• 100+ views
• Complex stateful client side application
• 160 database tables
• 100K lines of Java Code
• 20K of JavaScript
• Built by 2 developers over 18 months 8 weeks to first production release
• A few false starts especially with the JavaScript
• A lot of lessons learned about building stateful JavaScript
applications with Spring technologies
3
Disclaimer
• This presentation is focused on server side design patterns for
stateful JavaScript heavy front ends
• Lots of discussions of server side issues with a focus on Spring projects
• Very little coverage of client side JavaScript design patterns and frameworks
• We cover implementations of the patterns using
4
SpringOne 2GX Videos to Watch
• Spring 4 Web Applications
• Spring Boot for the Web Tier
• Resource Handling in Spring MVC 4.1
• The Quest for the Holy Integration Test
• Creating Modular Test Driven SPAS with Spring and AngularJS
• Inside spring.io: A Production Spring Reference Application
5
Traditional Web Application
6
Mostly stateless
client
Mostly stateful
server
HTML
Modern Web Application Architecture
7
Mostly stateful
JavaScript client
Nearly stateless
server
JSON
JavaScript Heavy Stateful Accounting Application
8
JavaScript Heavy Stateful Accounting Application
9
Dashboard Transactions Receipts
Single Page Application
• One HTML page
• No page reloads
• Lots of state stored in
JavaScript
Stateful JavaScript Heavy App
• Multiple HTML pages
• A single use case does not require a reload
• Lots of state stored in each page
• Some state is needed on multiple pages
10
We are talking about stateful JS heavy applications
Common Problems
• How to handle errors in a consistent way on the server and
client?
• What to do when http sessions expires?
• How to manage the URL space used by the application?
• How to manage shared state across page reloads?
• How to allow developer specialization frontend vs. backend?
11
Consistent Error Handling
12
Consistent Error Handling Problem
• With hundreds of REST end points how do we generalize error
handling in such a way that
• JavaScript client knows exactly what to expect from the server when there is
an error
• Server side developers know exactly how to generate an error that the client
side code and developers can consume
13
Benefits of a consistent error handling strategy
• Server side APIs are easier to consume
• Server side APIs are easier to code
• Server side APIs are easier to design
• It is easier to log and run analytics on API errors
14
Solution
• Three part solution
• Use HTTP status codes correctly
• Define a standard data structure for representing errors
• Make sure that no matter what happens API’s calls always return the
standard data structure when an error occurs
15
Define a subset of HTTP status codes
• Wikipedia lists 83 HTTP status codes
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
• Use a subset of HTTP status codes to reduce confusion
• There are 3 possible types of codes
• Everything worked
• Blame the API
• Blame the client
16
Recommended HTTP Status Codes
• 200 – if the request is processed successfully
• 500 – if the problem is the server’s fault
• 400 – if the request is the client’s fault
• 401 – if the user needs to log in
• 403 – if the user is logged in but does not have permission
• 404 – If the resource does not exist
How do we provide the client with more details about the
nature of the problem?
17
Use a secondary API specific error code
• Complement the http status code with an optional API specific
code
• The API specific error code should be globally unique so that it is
easy to search for the code.
• Use a UUID for the API specific error code
18
Five Part Standard Error Response
• HTTP status code • Required and must be one of 200, 500, 400, 401, 403, 404
• API specific error code • Optional must be a UUID so that is globally unique and searchable
• User message • Optional plain text message that the UI can display to the user if it wants
• Developer message • Optional plain text message aimed at developers to explain why the request
failed
• Validation messages • Optional array of field validation messages
19
Example Standard Error Message
20
Error Handling Code Walk Through
21
Error Handling Implementation Summary
• Define a RestApiError Pojo
• Use Spring @ControllerAdvice to centrally
• catch all exceptions that are thrown by rest controllers
• convert exceptions to the standard error message
• Define runtime exceptions to make generating standard errors
easy
22
Handling Expired Sessions
23
The problems of expired sessions
• An expired session logs the user out • Will loose current page state if redirected to a login page
• Expired session results in a redirect to the login page • AJAX API calls fail and the response is an HTML login form that the client
side JavaScript can’t parse
• Violate the consistent error handling axiom that an API call will always return an API resource (actual result or a standard error structure)
How to make sure that an expired session does not break the app?
24
Problems of the default spring security config
• When using from login with Spring security the default configuration conflicts with our goal for consistent error handling
• On login failure Spring Security redirects back to the form login page, great for humans bad for XHR processing
• On login success Spring Security redirects to the default success URL or the url you were tying to reach originally good for humans bad for XHR processing
• If the session is expired and an XHR request is made spring security redirect the request to the login from
25
Human User
• On successful login go to
home page
• On failed login stay on
login page
• On expired session
redirect to login page
API User
• On successful login return
a JSON response
indicating success
• On failed login return a
standard error message
• On expired session return
a standard error message
26
Desired Spring Security Configuration
Spring Security Configuration
• Configure an AuthenticationSuccessHandler
• Configure an AuthenticationFailureHandler
• Configure an AuthenticationEntryPoint
27
Spring Security Login Configuration Code Walk
Through
28
Managing The URL Space
29
URL Space Problem
• For each REST end point you typically implement a spring
@RestController with methods for GET, POST, PUT, DELETE
• A application with a hundred end points would have about 400
methods annotated with @RequestMapping and a URL pattern
for the resource
• In a large code based with multiple modules and multiple
packages it can be very hard to locate where are all the end
points, which Java files are they in … etc.
Is there a tool friendly way to organize and find all
the URL’s of the end points?
30
URL Space Code Walkthrough
31
Managing Shared State Across Pages
32
JavaScript Heavy Stateful Accounting Application
33
JavaScript Heavy Stateful Accounting Application
34
Dashboard Transactions Receipts
Solution Requirements
• Simple
• Fast
• Horizontally Scalable
35
Solution
• Don’t store state in the HTTP session only the id of the current
logged in user
• Use Immutable objects to represent server side page state
• Ensure the immutable objects can be reconstructed from
database state
• Cache the immutable objects in memory using Spring
@Cacheable or Google Guava Loading Cache
• The Google Guava Cache is very fast and very simple
36
Three types of controllers
• HTML controllers use a view to render HTML
• UI controllers aggregate all the initial data you need to bootstrap
a SPA page
• API controllers are used by SPA once it is loaded
37
Sharing State Across Pages Code Walk Through
38
Allow Developer Specialization
39
Developer Specialization Problem
• It is easier to find developers who specialize in front end
development or backend development than to find a full stack
developer
• How can we organize the system in such a way that a front end
developer who is not familiar with Java can productively write
front end code without getting stuck waiting for Java dev to do
something for them.
40
Solution
• Organize the source code for the project so that all the client
code is in one single project that the front end dev works on
• Incorporate the JavaScript tools such an NPM, Module Loaders,
SASS, LESS, grunt, bower … etc the workflow
• Follow the examples in the following SpringOne 2GX 2014
videos
• Spring Boot for the Web Tier
• Resource Handling in Spring MVC 4.1
• Use an echo mocking service
41
Echo Service Demo
42
Questions?
43