Isomorphic Templating with Spring Boot, Nashorn and React
-
Upload
spring-by-pivotal -
Category
Technology
-
view
4.073 -
download
1
Transcript of Isomorphic Templating with Spring Boot, Nashorn and React
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
SPRINGONE2GXWASHINGTON, DC
Isomorphic templating withSpring Boot, Nashorn and React
Sébastien Deleuze
@sdeleuze
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Agenda
• Isomorphic?
• Script based templating support in Spring
• Handlebars support
• What is React?
• Isomorphic application with Spring and React
• Demo
• What’s next?
2
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Isomorphic?
3
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Isomorphic
4
Shared code that runs on both the client & server
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Use cases
• Templating - User interface
• I18n
• Application logic
• Routing
• Model validation
5
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Why?
1. Performance
• Initial pageload speed
• Huge impact on mobile
2. Maintainability
• Share more code between client and server
• A single technology to learn
3. SEO - Accessibility
• Make your site more crawlable and accessible
6
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Principle
7
Server Client
! "#
Content + UIContent + UI +
DOM event listeners
$ $
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Your website is …
8
Applicationcentric
Contentcentric
%&
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
GitHub as an example
9
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Script based templatingsupport in Spring
10
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Support JSR 223 script engines
11
https://jira.spring.io/browse/SPR-12266: Support JavaScript Templating
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Nashorn
• Bundled with JRE 8+
• Evolve fast
• Min. requirement: Java 8u60
• Wait Java 8u66 if using React
12
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Nashorn code sample
13
ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("nashorn"); Invocable invocable = (Invocable)engine; String result = (String)invocable.invokeFunction("hello", "Brian");
function hello(name) { return "Hello " + name; }
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Available in Spring Framework 4.2
14
And in the upcoming Spring Boot 1.3 GA
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Javascript based template engines
15
Mustache
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Handlebars templates
16
<html> <head> <title>{{title}}</title> </head> <body> <ul> {{#each comments}} <li>{{author}} {{content}}</li> {{/each}} </ul> </body></html>
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Spring MVC controller
17
@Controllerpublic class HandlebarsController { @RequestMapping(path = "/home", method = RequestMethod.GET) String home(Model model) { model.addAttribute("title", "Title example"); List comments = Arrays.asList( new Comment("author1", "content1"), new Comment("author2", "content2"), new Comment("author3", "content3")); model.addAttribute("comments", comments); return "home"; }}
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Spring MVC controller revisited
18
@Controllerpublic class HandlebarsController { @RequestMapping(path = "/home", method = RequestMethod.GET) Map<String, ?> home() { return hash(title -> "Title example", comments -> asList( new Comment("author1", "content1"), new Comment("author2", "content2"), new Comment("author3", "content3")) ); }}
View name guessed from the URLthanks to RequestToViewNameTranslator
Hash literal using java 8u60 with -parameters and lambda type references
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Spring MVC controller re-revisited
19
@Controllerpublic class HandlebarsController { @Get("/home") Map<String, ?> home() { return hash(title -> "Title example", comments -> asList( new Comment("author1", "content1"), new Comment("author2", "content2"), new Comment("author3", "content3")) ); }}
spring-composed annotation based on @AliasFor
https://github.com/sbrannen/spring-composed
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Dependency Management
20
<dependency> <groupId>org.webjars</groupId> <artifactId>handlebars</artifactId> <version>3.0.0-1</version></dependency>
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Script based templating configuration
21
@BeanViewResolver viewResolver() { ScriptTemplateViewResolver viewResolver = new ScriptTemplateViewResolver(); viewResolver.setPrefix("/static/templates/"); viewResolver.setSuffix(".html"); return viewResolver;}
View resolver
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Script based templating configuration
22
@BeanScriptTemplateConfigurer configurer() {ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer(); configurer.setEngineName("nashorn"); configurer.setScripts("/static/polyfill.js", "/META-INF/resources/webjars/handlebars/3.0.0-1/handlebars.js", "/static/render.js"); configurer.setRenderFunction("render"); configurer.setSharedEngine(false); return configurer;}
Configurer
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Concurrency with Nashorn
23
• In web browsers, no simultaneous execution of your code
• Nashorn itself is NOT thread-safe by design
• The behavior depends of your Javascript code
• Worth to read Nashorn Multithreading and MT-safety
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
The sharedEngine property
24
• When sharedEngine is set to false, Spring uses ThreadLocal<ScriptEngine>
• Handlebars and React need sharedEngine=false
• Mustache works perfectly a single ScriptEngine (defaults)
• Be careful on memory consumption
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
polyfill.js
25
var window = {};
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
render.js
26
/** String template: the template content Map model: the view model String url: the template url (since 4.2.2) **/ function render(template, model, url) { // ...}// Since url is optional, you can also declare: function render(template, model) { // ...}
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Handlebars render() implementation
27
var templates = {}; function render(template, model, url) { var compiledTemplate; if (templates[url] === undefined) { compiledTemplate = Handlebars.compile(template); templates[url] = compiledTemplate; } else { compiledTemplate = templates[url]; } return compiledTemplate(toJsonObject(model));}// Create a real JSON object from the model Map function toJsonObject(model) { … }
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Model to JSON Object conversion
28
// Create a real JSON object from the model Mapfunction toJsonObject(model) { var o = {}; for (var k in model) { // Convert Iterable like List to real JSON array if (model[k] instanceof Java.type("java.lang.Iterable")) { o[k] = Java.from(model[k]); } else { o[k] = model[k]; } } return o;}
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Is it fast?
29
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Yes :-)
30
6000 page/s on my laptop
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Spring MVC + Handlebars production ready ?
31
• Nice to use
• handlebars-layouts
• Easy to customize
• Quite fast
• Young stack
• Latest Java 8 needed
• Load partials from classpath
nashorn.eval(new InputStreamReader(getClass().getResourceAsStream("file.js")));
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Experiment, contribute!
32
https://github.com/sdeleuze/spring-boot-sample-web-handlebars'
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
What is React?
33
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 34
• A Javascript library for building user interfaces
• Component oriented
• Not a full-stack framework
• Virtual DOM diffing/updating
• Server side rendering
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
DOM diffing
35
http://techblog.constantcontact.com/software-development/reactive-component-based-uis/
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
It’s Like Source Control for the DOM
36
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Before showing you JSX code …
37
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
React component: comment.js
38
var Comment = React.createClass({ handleClick: function(event) { alert(this.props.content); }, render: function () { return ( <div className="col-md-4"> <h2>{ this.props.author }</h2> <p>{ this.props.content } </p> <p><a className="btn btn-default » href="#" role=« button" onClick={ this.handleClick }>View details » </a> </p> </div> ) }});
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
JSX transformer
39
<div className="col-md-4"> <h2>{ this.props.author }</h2> <p>{ this.props.content } </p> <p><a className="btn btn-default" href="#" role=« button" onClick={ this.handleClick }>View details »</a></p></div>
React.createElement("div", {className: "col-md-4"}, React.createElement("h2", null, this.props.author), React.createElement("p", null, this.props.content, " "), React.createElement("p", null, React.createElement("a", {className: "btn btn-default", href: "#", role: "button", onClick: this.handleClick}, "View details") ) )
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
The most interesting man in the world about JSX …
40
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
React component: comment-list.js
41
var CommentList = React.createClass({ getInitialState: function () { return this.props; }, render: function () { var commentNodes = this.state.comments.map(function (comment) { return <Comment author={ comment.author } content={ comment.content } key={ comment.id } /> }); return ( <div className="comment-list"> { commentNodes } </div>)}});React.render(<CommentList comments={ data }/>, document.getElementById("comments"));
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Isomorphic applicationwith Spring and React
42
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Gradle configuration
43
apply plugin: 'java' apply plugin: 'spring-boot' plugins { id 'net.eikehirsch.react' version '0.3.1'}sourceCompatibility = 1.8 targetCompatibility = 1.8 dependencies { compile('org.springframework.boot:spring-boot-starter-web') compile('org.webjars:react:0.13.1') testCompile('org.springframework.boot:spring-boot-starter-test')}jsx { sourcesDir = 'src/main/resources/static/jsx' destDir = 'src/main/resources/static/output'} processResources.dependsOn('jsx')
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Page composition
44
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Controller
45
@Controllerpublic class CommentController { private CommentRepository commentRepository; @Autowired CommentController(CommentRepository commentRepository) { this.commentRepository = commentRepository; } @RequestMapping("/") String render(Model model) { model.addAttribute("title", "Layout example"); model.addAttribute("comments", this.commentRepository.findAll()); return "index"; }}
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
index.ejs
46
<!DOCTYPE html><html lang="en"> <head><!-- ... --></head> <body> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div id="navbar" class="navbar-collapse collapse"> <%= React.renderToString(React.createElement(CommentForm)) %> </div> </div> </nav> <div class="container"> <div id="comments" class="row"> <%= React.renderToString(React.createElement(CommentList, { comments: comments} )) %> </div> </div> <script src="lib/js/jquery.min.js"></script> <script src="lib/js/bootstrap.min.js"></script> <script src="webjars/react/0.13.1/react.js"></script> <script src="output/comment.js"></script> <<!-- ... --> </body></html>
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Server side rendering
47
<div id="navbar" class="navbar-collapse collapse"> <%= React.renderToString(React.createElement(CommentForm)) %></div>
<div id="navbar" class="navbar-collapse collapse"> <form class="navbar-form navbar-right" data-reactid=".1ptxdrtnx2v" data-react-checksum="382509970"> <div class="form-group" data-reactid=".1ptxdrtnx2v.0"> <input placeholder="Your name" class="form-control" data-reactid=".1ptxdrtnx2v.0.0"></div> <div class="form-group" data-reactid=".1ptxdrtnx2v.1"> <input placeholder="Say something..." class="form-control " data-reactid=".1ptxdrtnx2v.1.0"> </div> <button type="submit" class="btn btn-success" data-reactid=".1ptxdrtnx2v.2">Post comment</button> </form></div>
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
client.js (client side rendering)
48
React.render( <CommentForm onCommentSubmit={ function(comment) { $.post('/', comment, null, ‘json'); }}/>, document.getElementById("navbar"));$.getJSON('/', function( data ) { React.render(<CommentList comments={ data }/>, document.getElementById("comments"));});
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Server and client side = same output
49
React re-render everything BUT: - No flickering thanks to Virtual DOM diff - React just attach the DOM listeners
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
polyfill.js
50
var global = this;var console = {};console.debug = print;console.warn = print;console.log = print;
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
render.js
51
function render(template, model) { var data = toJsonObject(model); return new EJS({text: template}).render(data);}
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Issue: script duplication
52
<script src="lib/js/jquery.min.js"></script><script src="lib/js/bootstrap.min.js"></script><script src="webjars/react/0.13.1/react.js"></script><script src="output/comment.js"></script><script src="output/comment-list.js"></script><script src="output/comment-form.js"></script><script src="output/client.js"></script>
configurer.setScripts("static/polyfill.js", "static/lib/js/ejs.min.js", "/META-INF/resources/webjars/react/0.13.1/react.js", "static/render.js", "static/output/comment.js", "static/output/comment-form.js", "static/output/comment-list.js");
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 53
Develop a Javascript module loader server extension that loads resources from the classpath
nashorn.eval(new InputStreamReader(getClass().getResourceAsStream("file.js")));
(
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
SSE (server)
54
@Controllerpublic class CommentController { private final List<SseEmitter> sseEmitters = new ArrayList<>(); @RequestMapping(path = "/", method = RequestMethod.POST, produces = "application/json") @ResponseBody Comment jsonCreate(Comment comment) throws IOException { Comment newComment = this.commentRepository.save(comment); for (SseEmitter sseEmitter : this.sseEmitters) { sseEmitter.send(newComment, MediaType.APPLICATION_JSON); } return comment; } @RequestMapping("/sse/updates") SseEmitter subscribeUpdates() { SseEmitter sseEmitter = new SseEmitter(); this.sseEmitters.add(sseEmitter); sseEmitter.onCompletion(() -> { this.sseEmitters.remove(sseEmitter); }); return sseEmitter; }}
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
SSE (client)
55
var CommentList = React.createClass({ componentDidMount: function() { var eventSource = new EventSource("/sse/updates"); var self = this; eventSource.onmessage = function(e) { var comment = JSON.parse(e.data); var comments = self.state.comments; var newComments = comments.concat([comment]); self.setState({comments: newComments}); }; }, // ...});
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Demo
56
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
What’s next?
57
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 58
EcmaScript 6
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 59
TypeScript
TypeScript = EcmaScript 6+ types + decorators (annotations) + …
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 60
Ember 2
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 61
Angular 2
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 62
Angular 2
@Component({selector: 'my-app'})@View({template: '<h1>Hi {{ name }}</h1>'})// Component controllerclass MyAppComponent { constructor() { this.name = 'Ali'; }}
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 63
Routing
Need to build a bridge between server side and client side routing …
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 64
Experiments and contributions welcomed!
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/ 65
Conclusion
• Javascript evolves: ES6 - TypeScript
• Javascript frameworks are becoming more mature: React - EmberJS 2 - Angular 2
• Isomorphic applications provide a nice balance between server side rendering and Javascript based RIA
• Develop your front-end skills and try by yourself!
• The choice of the client side technology/software design is key differentiator for your project/product!
Unless otherwise indicated, these s l ides are © 2013-2015 Pivotal Software, Inc. and l icensed under a Creat ive Commons Attr ibut ion-NonCommercial l icense: ht tp: / /creat ivecommons.org/ l icenses/by-nc/3.0/
Thanks!
66
https://github.com/sdeleuze/spring-boot-sample-web-handlebars'https://github.com/sdeleuze/spring-react-isomorphic'
@sdeleuze