Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD application

511 views

Published on

This is part 36 of the EWD 3 Training Course. This presentation explains how your QEWD applications and Web/REST Service APIs can invoke and use external Web / REST services as part of their back-end handler logic

Published in: Software
  • Be the first to comment

EWD 3 Training Course Part 36: Accessing REST and Web Services from a QEWD application

  1. 1. Copyright © 2016 M/Gateway Developments Ltd EWD 3 Training Course Part 36 Accessing REST and Web Services from a QEWD Application Rob Tweed Director, M/Gateway Developments Ltd Twitter: @rtweed
  2. 2. Copyright © 2016 M/Gateway Developments Ltd Interactive v REST Apps • Interactive – QEWD back-end has direct access to database and business logic • Possibly including legacy application logic • REST – Application logic is on a different server, accessed via REST / Web Service calls – QEWD back-end must make REST/HTTP requests to a separate server
  3. 3. Copyright © 2016 M/Gateway Developments Ltd Self-contained Interactive App Browser QEWD socket.io socket.io Caché or GT.Mewd-session ewd-qoper8 queue Custom Worker Module demo1.js Globals Functions ewd-client token Legacy App Logic Express Worker
  4. 4. Copyright © 2016 M/Gateway Developments Ltd Self-contained Interactive App Browser QEWD socket.io socket.io Caché, GT.M or Redis ewd-session ewd-qoper8 queue Custom Worker Module demo1.js Global storage ewd-client token Express Worker
  5. 5. Copyright © 2016 M/Gateway Developments Ltd QEWD REST back-end HTTP Client QEWD Caché or GT.M ewd-qoper8 queue Custom Worker Module testWebService.js Globals Functions Legacy App Logic HTTP Express Worker
  6. 6. Copyright © 2016 M/Gateway Developments Ltd ewd-qoper8-vistarpc back-end HTTP Client ewd-qoper8-vistarpc Caché or GT.M ewd-qoper8 queue Custom Worker Module vista-worker-module-.js Interface Function VistA RPCs HTTP Express Worker
  7. 7. Copyright © 2016 M/Gateway Developments Ltd QEWD accessing REST Service Browser QEWD socket.io socket.io Caché, GT.M or Redis ewd-session ewd-qoper8 queue Custom Worker Module demo1.jsewd-client token Express Separate REST/Web Service HTTP Worker
  8. 8. Copyright © 2016 M/Gateway Developments Ltd QEWD accessing another QEWD- based REST Service Browser QEWD socket.io socket.io Caché, GT.M or Redis ewd-session ewd-qoper8 queue Custom Worker Module demo1.jsewd-client token Express HTTP QEWD Caché, GT.M or Redis ewd-qoper8 queue Custom Worker Module testWebService.js Globals Functions Legacy App Logic Express Worker Worker
  9. 9. Copyright © 2016 M/Gateway Developments Ltd ewd-xpress accessing ewd-qoper8-vistarpc Browser QEWD socket.io socket.io Caché, GT.M or Redis ewd-session ewd-qoper8 queue Custom Worker Module demo1.jsewd-client token Express HTTP ewd-qoper8-vistarpc Caché Or GT.M ewd-qoper8 queue Custom Worker Module vista-worker-module-.js Interface Function VistA RPCs Express Worker Worker
  10. 10. Copyright © 2016 M/Gateway Developments Ltd QEWD accessing a REST Service Browser QEWD socket.io socket.io Caché, GT.M or Redis ewd-session ewd-qoper8 queue Custom Worker Module demo1.jsewd-client token Express Separate REST/Web Service HTTP So what do you have to do in here to make this possible? Worker
  11. 11. Copyright © 2016 M/Gateway Developments Ltd HTTP Client access from Node.js • Your back-end message handler function needs to act as an HTTP client • Node.js provides the libraries for this – But they are very low-level and can be tricky to use
  12. 12. Copyright © 2016 M/Gateway Developments Ltd HTTP Client access from Node.js • Your back-end message handler function needs to act as an HTTP client • Node.js provides the libraries for this – But they are very low-level and can be tricky to use • Better/Easier to use a pre-built module that re-packages the Node.js libraries – request is probably the best / most used
  13. 13. Copyright © 2016 M/Gateway Developments Ltd Install the request module • cd C:qewd (or cd ~/qewd) • npm install request
  14. 14. Copyright © 2016 M/Gateway Developments Ltd Let's try it with a test REST service • jsonplaceholder – A useful mock/test service that you can freely use – https://jsonplaceholder.typicode.com/ • We'll use its GET /posts/1 service – Try it with a browser: – https://jsonplaceholder.typicode.com/posts/1
  15. 15. Copyright © 2016 M/Gateway Developments Ltd Create a QEWD app • Simple web page with a button • When the button is clicked, we'll send a message to the QEWD back end • The handler for the message will invoked the jsonplaceholder service and return the response to the browser
  16. 16. Copyright © 2016 M/Gateway Developments Ltd Ensure you have ewd-client installed • See Parts 5a and 5b of this course for details
  17. 17. Copyright © 2016 M/Gateway Developments Ltd We'll call our app restDemo • Create an application directory for its client-side HTML and JavaScript files: – cd ~/qewd/www – mkdir restDemo – cd restDemo
  18. 18. Copyright © 2016 M/Gateway Developments Ltd Create index.html <html> <head> <title>QEWD REST Demo</title> </head> <body> <script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script> <script src="/socket.io/socket.io.js"></script> <script src="/ewd-client.js"></script> <script src="app.js"></script> <button id="testBtn">Click Me</button> <pre id="content"> Content will go here </pre> </body> </html>
  19. 19. Copyright © 2016 M/Gateway Developments Ltd Create app.js $(document).ready(function() { EWD.log = true; EWD.on('ewd-registered', function() { $('#testBtn').on('click', function(e) { var message = {type: 'testRestService'}; EWD.send(message, function(messageObj) { $('#content').text(JSON.stringify(messageObj.message, null, 2)); }); }); }); EWD.start('restDemo', $, io); });
  20. 20. Copyright © 2016 M/Gateway Developments Ltd Create app.js $(document).ready(function() { EWD.log = true; EWD.on('ewd-registered', function() { $('#testBtn').on('click', function(e) { var message = {type: 'testRestService'}; EWD.send(message, function(messageObj) { $('#content').text(JSON.stringify(messageObj.message, null, 2)); }); }); }); EWD.start('restDemo', $, io); }); Define the click handler for the button
  21. 21. Copyright © 2016 M/Gateway Developments Ltd Create app.js $(document).ready(function() { EWD.log = true; EWD.on('ewd-registered', function() { $('#testBtn').on('click', function(e) { var message = {type: 'testRestService'}; EWD.send(message, function(messageObj) { $('#content').text(JSON.stringify(messageObj.message, null, 2)); }); }); }); EWD.start('restDemo', $, io); }); When clicked, it sends a message of type 'testRestService'
  22. 22. Copyright © 2016 M/Gateway Developments Ltd Create app.js $(document).ready(function() { EWD.log = true; EWD.on('ewd-registered', function() { $('#testBtn').on('click', function(e) { var message = {type: 'testRestService'}; EWD.send(message, function(messageObj) { $('#content').text(JSON.stringify(messageObj.message, null, 2)); }); }); }); EWD.start('restDemo', $, io); }); When response is received from QEWD, display it within the content <pre> tag
  23. 23. Copyright © 2016 M/Gateway Developments Ltd Now create the back-end handler • cd ~/qewd/node_modules • Create a file named restDemo.js
  24. 24. Copyright © 2016 M/Gateway Developments Ltd Contents of restDemo.js var request = require('request'); module.exports = { handlers: { testRestService: function(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } } };
  25. 25. Copyright © 2016 M/Gateway Developments Ltd Create restDemo.js var request = require('request'); module.exports = { handlers: { testRestService: function(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } } }; Load the request module
  26. 26. Copyright © 2016 M/Gateway Developments Ltd Create restDemo.js var request = require('request'); module.exports = { handlers: { testRestService: function(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } } }; Define the handler function for the testRestService message that will be sent when the button is clicked
  27. 27. Copyright © 2016 M/Gateway Developments Ltd Create restDemo.js var request = require('request'); module.exports = { handlers: { testRestService: function(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } } }; Send the GET request to the jsonplaceholder service using the request module
  28. 28. Copyright © 2016 M/Gateway Developments Ltd Create restDemo.js var request = require('request'); module.exports = { handlers: { testRestService: function(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } } }; Return the results by invoking the finished() function.
  29. 29. Copyright © 2016 M/Gateway Developments Ltd Create restDemo.js var request = require('request'); module.exports = { handlers: { testRestService: function(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } } }; Make sure you invoke the finished() function from within request's callback. QEWD must not release the worker until after the REST service response has been received
  30. 30. Copyright © 2016 M/Gateway Developments Ltd Try it out Click the button and this should appear – the response from jsonplaceholder
  31. 31. Copyright © 2016 M/Gateway Developments Ltd Check the JavaScript Console Message sent to QEWD when the button was clicked
  32. 32. Copyright © 2016 M/Gateway Developments Ltd Check the JavaScript Console Response from worker, containing content from jsonplaceholder
  33. 33. Copyright © 2016 M/Gateway Developments Ltd Create a REST proxy • Instead of an interactive QEWD application, let's create a QEWD-based REST API that acts as a proxy to the jsonplaceholder service
  34. 34. Copyright © 2016 M/Gateway Developments Ltd Create a REST proxy • Instead of an interactive QEWD application, let's create a QEWD-based REST API that acts as a proxy to the jsonplaceholder service • We can do this by: – Amending our back-end restDemo.js module – Adding a route to our QEWD startup file • Let's route the URL /api/proxy to a handler in restDemo.js
  35. 35. Copyright © 2016 M/Gateway Developments Ltd Amend node_modules/restDemo.js var request = require('request'); function testRestService(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } module.exports = { restModule: true, handlers: { proxy: function(messageObj, finished) { testRestService(messageObj, null, null, finished); }, testRestService: function(messageObj, session, send, finished) { testRestService(messageObj, session, send, finished); } } };
  36. 36. Copyright © 2016 M/Gateway Developments Ltd Amend node_modules/restDemo.js var request = require('request'); function testRestService(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } module.exports = { restModule: true, handlers: { proxy: function(messageObj, finished) { testRestService(messageObj, null, null, finished); }, testRestService: function(messageObj, session, send, finished) { testRestService(messageObj, session, send, finished); } } }; Separate out the testRestService function
  37. 37. Copyright © 2016 M/Gateway Developments Ltd Amend node_modules/restDemo.js var request = require('request'); function testRestService(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } module.exports = { restModule: true, handlers: { proxy: function(messageObj, finished) { testRestService(messageObj, null, null, finished); }, testRestService: function(messageObj, session, send, finished) { testRestService(messageObj, session, send, finished); } } }; Declare this module to be a REST one. Note: it can also support interactive apps even with this setting
  38. 38. Copyright © 2016 M/Gateway Developments Ltd Amend node_modules/restDemo.js var request = require('request'); function testRestService(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } module.exports = { restModule: true, handlers: { proxy: function(messageObj, finished) { testRestService(messageObj, null, null, finished); }, testRestService: function(messageObj, session, send, finished) { testRestService(messageObj, session, send, finished); } } }; Define a handler for the /api/proxy URL by defining a handler function named proxy
  39. 39. Copyright © 2016 M/Gateway Developments Ltd Amend node_modules/restDemo.js var request = require('request'); function testRestService(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } module.exports = { restModule: true, handlers: { proxy: function(messageObj, finished) { testRestService(messageObj, null, null, finished); }, testRestService: function(messageObj, session, send, finished) { testRestService(messageObj, session, send, finished); } } }; The proxy function invokes the externalised original function which calls out to the jsonplaceholder service
  40. 40. Copyright © 2016 M/Gateway Developments Ltd Amend node_modules/restDemo.js var request = require('request'); function testRestService(messageObj, session, send, finished) { var options = { url: 'https://jsonplaceholder.typicode.com/posts/1', method: 'GET', json: true }; request(options, function(error, response, body) { if (error) { finished({error: error}); } else { finished(body); } }); } module.exports = { restModule: true, handlers: { proxy: function(messageObj, finished) { testRestService(messageObj, null, null, finished); }, testRestService: function(messageObj, session, send, finished) { testRestService(messageObj, session, send, finished); } } }; Edit our original testRestService message handler to also call the now externalised function
  41. 41. Copyright © 2016 M/Gateway Developments Ltd Edit your QEWD startup file var config = { managementPassword: 'keepThisSecret!', serverName: 'QEWD REST Server', port: 8080, poolSize: 2, database: { type: 'redis' } }; var routes = [ {path: '/api', module: 'restDemo'} ]; var qewd = require('qewd').master; qewd.start(config, routes); Add the route for the /api URL prefix We want it to use handler functions in our restDemo.js module
  42. 42. Copyright © 2016 M/Gateway Developments Ltd Edit your QEWD startup file var config = { managementPassword: 'keepThisSecret!', serverName: 'QEWD REST Server', port: 8080, poolSize: 2, database: { type: 'redis' } }; var routes = [ {path: '/api', module: 'restDemo'} ]; var qewd = require('qewd').master; qewd.start(config, routes); Add routes to the QEWD start() function
  43. 43. Copyright © 2016 M/Gateway Developments Ltd Restart QEWD • Try the original interactive application • It should still work
  44. 44. Copyright © 2016 M/Gateway Developments Ltd Restart QEWD • Try the original interactive application • It should still work • Now try the REST proxy…
  45. 45. Copyright © 2016 M/Gateway Developments Ltd Try the REST proxy It also works!

×