Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Going fullstack React(ive)

Going fullstack React(ive)

What if someone told you that you could use the full capacity of your server? That you could have the same performance on the backend as your react frontend? Don't you believe it? That you could choose the best language/tool for the task and you were not limited by what you already know? In this talk, I'll show you that you can use the full power of React on the frontend and Vert.x on the backend. You will see a fast full stack development workflow with Webpack + Babel + React. How you can mix JavaScript with any other language. Build microservice applications in minutes.

Paulo Lopes

May 16, 2017
Tweet

More Decks by Paulo Lopes

Other Decks in Programming

Transcript

  1. TYPICAL JAVA APP... final String PID = ManagementFactory.getRuntimeMXBean().getName(); @RequestMapping(value =

    "/work", method = RequestMethod.GET) public @ResponseBody String work(HttpServletResponse resp) { resp.setContentType("text/plain"); resp.setCharacterEncoding("UTF-8"); return "Pi is: " + Pi.calculate(100_000_000); } @RequestMapping(value = "/", method = RequestMethod.GET) public @ResponseBody String home(HttpServletResponse resp) { resp.setContentType("text/plain"); resp.setCharacterEncoding("UTF-8"); return "Current PID: " + PID; }
  2. TYPICAL NODE APP... var process = require('process'); var app =

    require('express')(); var pi = require('./pi'); app.get('/', function (req, res) { res.send('Request served by ' + process.pid); }); app.get('/work', function (req, res) { res.send('Pi = (' + process.pid + ') ' + pi(100000000)); }); app.listen(8080, function () { console.log('Pi server listening on port 8080!') });
  3. TYPICAL VERT.X APP... // Initial Setup // final String PID

    = ManagementFactory .getRuntimeMXBean().getName(); final Router app = Router.router(vertx); // Reactive Trait: RESPONSIVE // // responsive, even under high load this handler // can respond to requests app.get("/").handler(ctx -> { ctx.response() .putHeader("content-type", "text/plain") // Reactive Trait: RESILIENT // // resilient, in case of failure the system // recovers .end("Current PID: " + PID); }); // Reactive Trait: MESSAGE DRIVEN // app.get("/work").handler(ctx -> { // message driven, events can cross boundaries // using a message driven architecture vertx.eventBus().send( "pi", null, reply -> { if (reply.failed()) { ctx.fail(reply.cause()); } else { ctx.response() .putHeader("content-type", "text/plain") .end("Pi = " + reply.result().body()); } }); }); // Reactive Trait: ELASTIC // // elastic we can deploy several consumers to // scale the application vertx.eventBus().consumer( "pi", m -> { // can mix blocking and non-blocking code vertx.executeBlocking( fut -> fut.complete(Pi.calculate( 100000000)), false, fut -> m.reply(PID + ": " + fut.result())); });
  4. REACT.JS Simplicity Component Based Approach Performance and Virtual DOM Awesome

    for SEO Testability/Developers tools Bonus: Mobile apps with react native
  5. REACT.JS Simplicity Component Based Approach Performance and Virtual DOM Awesome

    for SEO Testability/Developers tools Bonus: Mobile apps with react native
  6. WITH VERT.X YOU CAN... Run JS with your Java,Scala,Kotlin,Groovy,Ruby,etc... Mix

    CPU intensive tasks with non CPU intensive Call EventBus remote services as if they were local drop Node.JS
  7. VERT.X UNIVERSAL APP // Initial Setup // const Router =

    require("vertx-web-js/router") const StaticHandler = require("vertx-web-js/static_handler" ) import React from 'react' import {renderToString} from 'react-dom/server' import {match, RouterContext} from 'react-router' import routes from '../shared/components/routes' const app = Router.router(vertx) // Rest API (Similar to Express.JS) // app.get('/api/post').handler((ctx) => { ctx.response() .putHeader("content-type", "application/json") .end(JSON.stringify(posts)) }) app.get('/api/post/:id').handler((ctx) => { const id = ctx.request().getParam( 'id') const post = posts.filter(p => p.id == id) if (post) { ctx.response() .putHeader( "content-type", "application/json") .end(JSON.stringify(post[0])) } else { ctx.fail(404) } }) // Mix React.JS with Vert.x // app.get().handler((ctx) => { match({ routes: routes, location: ctx.request().uri() }, (err, redirect, props) => { if (err) { ctx.fail(err.message); } else if (redirect) { ctx.response() .putHeader("Location", redirect.pathname + redirect.search) .setStatusCode( 302) .end(); } else if (props) { const routerContextWithData = ( <RouterContext {...props} createElement={(Component, props) => { return <Component posts={posts} {...props} /> }} />)
  8. VERT.X UNIVERSAL APP // Mix React.JS with Vert.x // app.get().handler((ctx)

    => { match({ routes: routes, location: ctx.request().uri() }, (err, redirect, props) => { if (err) { ctx.fail(err.message); } else if (redirect) { ctx.response() .putHeader("Location", redirect.pathname + redirect.search) .setStatusCode( 302) .end(); } else if (props) { const routerContextWithData = ( <RouterContext {...props} createElement={(Component, props) => { return <Component posts={posts} {...props} /> }} />) // Render React.js without Node // const appHtml = renderToString(routerContextWithData) ctx.response() .putHeader("content-type", "text/html") .end(`<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Universal Blog</title> </head> <body> <div id="app"> ${appHtml}</div> <script src="/bundle.js"></script> </body> </html>` ) } else { ctx.next() } }) }) // Serve resources and start // app.get().handler(StaticHandler.create().handle) vertx.createHttpServer() .requestHandler(app.accept).listen( 8080)
  9. IN YOUR VERT.X APP... final Router router = Router.router(vertx); //

    Allow events for the designated addresses BridgeOptions sockjsConfig = new BridgeOptions() .addInboundPermitted(new PermittedOptions().setAddress("greetings")) .addOutboundPermitted(new PermittedOptions().setAddress("greetings")); // Create the event bus bridge and add it to the router. router .route("/eventbus/*") .handler(SockJSHandler.create(vertx).bridge(sockjsConfig)); router.route().handler(StaticHandler.create()); vertx.createHttpServer().requestHandler(router::accept).listen(8080);
  10. IN YOUR VERT.X APP (2)... ... router.route().handler(StaticHandler.create()); vertx.createHttpServer().requestHandler(router::accept).listen(8080); EventBus eb

    = vertx.eventBus(); vertx.setPeriodic(500, t -> eb.send("greetings", new JsonObject().put("msg", "Greetings from Vert.x!")));
  11. IN YOUR REACT APP... import EventBus from 'vertx3-eventbus-client' const eb

    = new EventBus(`//${window.location.host}/eventbus`) class App extends React.Component { constructor(props) { super(props) this.state = { messages: [] } } render() { let listItems = this.state.messages.map(message => { return ( <li>{ `${message}` }</li> ) }) return ( <div><ul>{listItems}</ul></div> ) }
  12. IN YOUR REACT APP (2)... ... class App extends React.Component

    { ... componentWillMount() { Rx.Observable .create((observer) => { eb.registerHandler('greetings', (err, msg) => { observer.next(msg.body.msg); }); }) .subscribe(message => { this.state.messages.unshift(message); this.setState({ messages: this.state.messages }); }); }
  13. IN YOUR NODE APP... var EventBus = require('vertx3-eventbus-client'); var eb

    = new EventBus('http://localhost:8080/eventbus'); eb.onerror = function (err) { console.error(err); }; eb.onopen = function () { setInterval(function () { eb.send('greetings', {msg: 'Hello from Node.js!'}); }, 500); };
  14. IN YOUR REACT APP (3)... ... class App extends React.Component

    { ... static sayHello(e) { e.preventDefault(); eb.send('greetings', {msg: 'Hello from React.js!'}) } render() { return ( ... <button onClick={App.sayHello}>Say Hello!</button>
  15. ASYNC CODE: route().handler(ctx -> { ctx.user().isAuthorized("READ", res -> { db.getConnection(conn

    -> { conn.query("select * from test", rs -> { conn.close( v -> { ctx.response.end(rs.encode()); }); }); }); }); });
  16. RX TO THE RESCUE route().handler(ctx -> { ctx.user().rxIsAuthorized("READ") .flatMap(r ->

    db.rxGetConnection(conn)) .flatMap(c -> c.rxQuery("select * from test")) .doAfterTerminate(c::close) .subscribe(rs -> ctx.response.end(rs.encode())); });
  17. OR WITH (JS) VERT.X APP... route().handler(async (ctx) -> { if

    (await ctx.user().isAuthorized("READ")) { try { let c = await db.getConnection() let rs = await c.query("select * from test") ctx.response.end(rs.encode()) } finally { c.close() } } });
  18. OR WITH (VERT.X SYNC) VERT.X APP... route().handler(fiberHandler(ctx -> { if

    (awaitResult(h -> ctx.user().isAuthorized("READ", h))) { try (SQLConnection conn = awaitResult(jdbc::getConnection)) { ResultSet res = awaitResult(h -> conn.query("select * from test", h)); ctx.response.end(rs.encode()); } } }));
  19. HOW DO I START? Github Twitter Youtube Book http://vertx.io https://groups.google.com/forum/#!forum/vertx

    https://github.com/vert-x3 @vertx_project https://www.youtube.com/vertx_project https://t.co/m2w7puPba8
  20. THE END Thanks you! Follow me on twitter Visit my

    blog Start your project @jetdrone http://jetdrone.xyz http://jetdrone.xyz/vertx-starter