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.

REST Web Service? No, GraphQL please!

39 views

Published on

How to implement a GraphQL service in front of an Oracle Database and why developers like that instead of a REST web service.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

REST Web Service? No, GraphQL please!

  1. 1. REST WEB SERVICE? NO, GRAPHQL PLEASE! DIMITRI GIELIS
  2. 2. DIMITRI GIELIS ABOUT ME ▸ Founder & CEO of APEX R&D ▸ 20+ years of Oracle Experience 
 (OCP & APEX Certified) ▸ Oracle ACE Director ▸ “APEX Developer of the year 2009” by Oracle Magazine ▸ “Oracle Developer Choice award (ORDS)” in 2015 ▸ Author Expert Oracle APEX ▸ Presenter at Conferences
  3. 3. www.apexofficeprint.comwww.apexRnD.be
  4. 4. http://dgielis.blogspot.com @dgielis
  5. 5. WAYS TO QUERY THE DATABASE? SQL REST GraphQL
  6. 6. SQL
  7. 7. STRUCTUREDQL
  8. 8. GRAPHQL
  9. 9. REST CREATE API?
  10. 10. REST API /hr/employees/:id GET RESPONSE
  11. 11. REST API CHARACTERISTICS ▸ Server controls the data you get ▸ May need multiple requests to obtain data ▸ Static versions of API
  12. 12. GRAPHQL CREATE API?
  13. 13. GRAPHQL API /hr GET RESPONSE Query
  14. 14. GRAPHQL CHARACTERISTICS ▸ Server defines what is available, 
 but Client controls the data it get ▸ Single request to get all ▸ Evolve API over time 
 (even make fields deprecated) ▸ Auto documented
  15. 15. https://graphql.org
  16. 16. GRAPHQL HISTORY ▸ Facebook's mobile apps have been powered by GraphQL since 2012. ▸ A GraphQL spec was open sourced in 2015 ▸ Many implementations in different languages ▸ Used by many big companies e.g.
  17. 17. DEMO (CONSUMING)
  18. 18. https://graphql.org/swapi-graphql/
  19. 19. https://www.graphqlhub.com
  20. 20. http://join-monster.herokuapp.com
  21. 21. MORE EXAMPLES GRAPHQL APIS ▸ https://github.com/APIs-guru/graphql-apis ▸ https://help.shopify.com/en/api/graphql-admin-api/ graphiql-explorer ▸ https://developer.github.com/v4/ ▸ https://www.yelp.com/developers/graphql/guides/intro
  22. 22. GETTING STARTED GRAPHQL AND THE ORACLE DATABASE
  23. 23. GRAPHQL AND THE ORACLE DATABASE BUILDING BLOCKS ▸ Oracle Database ▸ node.js ▸ oracledb ▸ graphql ▸ apollo-server
  24. 24. MY DEVELOPMENT ENVIRONMENT ▸ Visual Studio Code ▸ Sqlcl ▸ Git ▸ node.js & nvm & npm ▸ Instant Oracle client / Oracle Database
  25. 25. INSTALLATION NODE.JS https://nodejs.org/
  26. 26. GETTING STARTED CREATE A FIRST NODE PROJECT ▸ npm init ▸ npm install apollo-server graphql oracledb
  27. 27. GETTING STARTED CREATE A FIRST NODE PROJECT ▸ npm init ▸ npm install apollo-server graphql oracledb
  28. 28. GETTING STARTED CREATE A FIRST NODE PROJECT ▸ npm init ▸ npm install apollo-server graphql oracledb
  29. 29. GETTING STARTED CREATE A FIRST NODE PROJECT ▸ npm init ▸ npm install apollo-server graphql oracledb
  30. 30. ABOUT APOLLO Apollo Server is the best way to quickly build a production-ready, self-documenting API for GraphQL clients, using data from any source - https://www.apollographql.com/docs/apollo-server/
  31. 31. CREATE AN APOLLO SERVER const { ApolloServer, gql } = require('apollo-server'); // This is a (sample) collection of books const books = [{title: 'Book1'},{title: 'Book2'}]; // Type definitions define the "shape" of your data const typeDefs = gql` type Book {title: String} type Query {books: [Book]} `; // Resolvers define the technique for fetching the types const resolvers = { Query: {books: () => books } }; // The Apollo Server can be started by passing // type definitions and the resolvers const server = new ApolloServer({ typeDefs, resolvers }); // This `listen` method launches a web-server server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); }); https://www.apollographql.com/docs/apollo-server/getting-started/
  32. 32. CREATE AN APOLLO SERVER const { ApolloServer, gql } = require('apollo-server'); // This is a (sample) collection of books const books = [{title: 'Book1'},{title: 'Book2'}]; // Type definitions define the "shape" of your data const typeDefs = gql` type Book {title: String} type Query {books: [Book]} `; // Resolvers define the technique for fetching the types const resolvers = { Query: {books: () => books } }; // The Apollo Server can be started by passing // type definitions and the resolvers const server = new ApolloServer({ typeDefs, resolvers }); // This `listen` method launches a web-server server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); }); https://www.apollographql.com/docs/apollo-server/getting-started/
  33. 33. CREATE AN APOLLO SERVER const { ApolloServer, gql } = require('apollo-server'); // This is a (sample) collection of books const books = [{title: 'Book1'},{title: 'Book2'}]; // Type definitions define the "shape" of your data const typeDefs = gql` type Book {title: String} type Query {books: [Book]} `; // Resolvers define the technique for fetching the types const resolvers = { Query: {books: () => books } }; // The Apollo Server can be started by passing // type definitions and the resolvers const server = new ApolloServer({ typeDefs, resolvers }); // This `listen` method launches a web-server server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); }); https://www.apollographql.com/docs/apollo-server/getting-started/
  34. 34. CREATE AN APOLLO SERVER const { ApolloServer, gql } = require('apollo-server'); // This is a (sample) collection of books const books = [{title: 'Book1'},{title: 'Book2'}]; // Type definitions define the "shape" of your data const typeDefs = gql` type Book {title: String} type Query {books: [Book]} `; // Resolvers define the technique for fetching the types const resolvers = { Query: {books: () => books } }; // The Apollo Server can be started by passing // type definitions and the resolvers const server = new ApolloServer({ typeDefs, resolvers }); // This `listen` method launches a web-server server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); }); https://www.apollographql.com/docs/apollo-server/getting-started/
  35. 35. CREATE AN APOLLO SERVER const { ApolloServer, gql } = require('apollo-server'); // This is a (sample) collection of books const books = [{title: 'Book1'},{title: 'Book2'}]; // Type definitions define the "shape" of your data const typeDefs = gql` type Book {title: String} type Query {books: [Book]} `; // Resolvers define the technique for fetching the types const resolvers = { Query: {books: () => books } }; // The Apollo Server can be started by passing // type definitions and the resolvers const server = new ApolloServer({ typeDefs, resolvers }); // This `listen` method launches a web-server server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); }); https://www.apollographql.com/docs/apollo-server/getting-started/
  36. 36. CREATE AN APOLLO SERVER const { ApolloServer, gql } = require('apollo-server'); // This is a (sample) collection of books const books = [{title: 'Book1'},{title: 'Book2'}]; // Type definitions define the "shape" of your data const typeDefs = gql` type Book {title: String} type Query {books: [Book]} `; // Resolvers define the technique for fetching the types const resolvers = { Query: {books: () => books } }; // The Apollo Server can be started by passing // type definitions and the resolvers const server = new ApolloServer({ typeDefs, resolvers }); // This `listen` method launches a web-server server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); }); https://www.apollographql.com/docs/apollo-server/getting-started/
  37. 37. CREATE AN APOLLO SERVER const { ApolloServer, gql } = require('apollo-server'); // This is a (sample) collection of books const books = [{title: 'Book1'},{title: 'Book2'}]; // Type definitions define the "shape" of your data const typeDefs = gql` type Book {title: String} type Query {books: [Book]} `; // Resolvers define the technique for fetching the types const resolvers = { Query: {books: () => books } }; // The Apollo Server can be started by passing // type definitions and the resolvers const server = new ApolloServer({ typeDefs, resolvers }); // This `listen` method launches a web-server server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); }); https://www.apollographql.com/docs/apollo-server/getting-started/
  38. 38. TEST IN BROWSER: HTTP://LOCALHOST:4000
  39. 39. HOOKING UP ORACLE DB WITH NODE-ORACLEDB
  40. 40. QUERY ORACLE DB var oracledb = require('oracledb'); async function run() { let connection; try { connection = await oracledb.getConnection( { user : "hr", password : "hr", connectString : "localhost/XEPDB1" }); let result = await connection.execute( `SELECT manager_id, department_id, department_name FROM departments WHERE manager_id = :id`, [103], // bind value for :id ); console.log(result.rows); } catch (err) { console.error(err); } finally { if (connection) { try { await connection.close(); } catch (err) { console.error(err); } } } } run(); https://oracle.github.io/node-oracledb/doc/api.html#getstarted
  41. 41. QUERY ORACLE DB var oracledb = require('oracledb'); async function run() { let connection; try { connection = await oracledb.getConnection( { user : "hr", password : "hr", connectString : "localhost/XEPDB1" }); let result = await connection.execute( `SELECT manager_id, department_id, department_name FROM departments WHERE manager_id = :id`, [103], // bind value for :id ); console.log(result.rows); } catch (err) { console.error(err); } finally { if (connection) { try { await connection.close(); } catch (err) { console.error(err); } } } } run(); https://oracle.github.io/node-oracledb/doc/api.html#getstarted
  42. 42. QUERY ORACLE DB var oracledb = require('oracledb'); async function run() { let connection; try { connection = await oracledb.getConnection( { user : "hr", password : "hr", connectString : "localhost/XEPDB1" }); let result = await connection.execute( `SELECT manager_id, department_id, department_name FROM departments WHERE manager_id = :id`, [103], // bind value for :id ); console.log(result.rows); } catch (err) { console.error(err); } finally { if (connection) { try { await connection.close(); } catch (err) { console.error(err); } } } } run(); https://oracle.github.io/node-oracledb/doc/api.html#getstarted
  43. 43. QUERY ORACLE DB var oracledb = require('oracledb'); async function run() { let connection; try { connection = await oracledb.getConnection( { user : "hr", password : "hr", connectString : "localhost/XEPDB1" }); let result = await connection.execute( `SELECT manager_id, department_id, department_name FROM departments WHERE manager_id = :id`, [103], // bind value for :id ); console.log(result.rows); } catch (err) { console.error(err); } finally { if (connection) { try { await connection.close(); } catch (err) { console.error(err); } } } } run(); https://oracle.github.io/node-oracledb/doc/api.html#getstarted
  44. 44. GETTING STARTED COMBINING APOLLO AND ORACLE ▸ Map SQL to Types ▸ TIP: 
 sqlcl to output SQL statement to JSON ▸ convert JSON to GraphQL Types automatically
 https://walmartlabs.github.io/json-to-simple-graphql-schema/
  45. 45. DEMO (PROVIDING) source: https://www.apexofficeprint.com/graphql
  46. 46. MORE ADVANCED SQL & JOINS JOIN MONSTER ▸ A GraphQL to SQL query execution layer for query planning and batch data fetching. https://github.com/acarl005/join-monster
  47. 47. DEMO (PROVIDING) source: Dan McGhan presentation: emp/dept example
  48. 48. DETAILS OF GRAPHQL GRAPHQL CONCEPTS ▸ Schema ▸ Object type (character) ▸ Field ▸ Arguments ▸ Scalar type ▸ Interface
  49. 49. DETAILS OF GRAPHQL HOW TO QUERY A GRAPHQL SERVER ▸ Queries ▸ Fields, Aliases, Fragments ▸ Arguments ▸ Variables ▸ Directives ▸ Operation name ▸ Mutations ▸ Subscriptions
  50. 50. NEXT INTERESTING RESOURCES & PROJECTS ▸ https://graphql.org/learn/best-practices/ ▸ https://blogs.oracle.com/opal/demo:-graphql-with-node-oracledb ▸ https://github.com/sblack4/oracledb-graphql-demo ▸ https://www.prisma.io (no Oracle support yet) ▸ https://github.com/rexxars/sql-to-graphql (unmaintained)

×