Slide 1

Slide 1 text

Six Polite Way s to Design a RESTful AP I for your Domino Application! Serdar Basegmez Developi Informa ti on Systems @serdar_basegmez

Slide 2

Slide 2 text

About… Serdar Basegmez •Developi Information Systems, London •Notes/Domino developer, half-blooded admin, errand-boy… •OpenNTF Board, HCL Ambassador, IBM Champion Alumni •Blog: LotusNotus.com / Twitter: @serdar_basegmez •Also tweets/blogs/speaks/podcasts on scientific skepticism 2

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Agenda •Why should you care? •RESTful APIs •Practical Implications of RESTful Architectures •Designing an API •Ways to Provide REST Services for HCL Domino •Tools •Wrap-up 4

Slide 5

Slide 5 text

Why Should You Care? •New Front-ends and Enhanced UX –Facelifting, but keeping data and business logic in NSF. –JS Frameworks (e.g. Angular, React), Mobile Apps, etc. –Richer experiences with chatbots, AI, etc. •Integration for third party sites/applications –IT becomes a huge jungle, we can’t walk alone! –Financial Systems, AI Systems, CRM, S/M Automation –Collaborative Apps, Office 365 •Automating processes using APIs –Domino Apps not independent from Business Processes –Accounting/Sales/Marketing/ERP Processes 5 User Experience Business Processes Integration

Slide 6

Slide 6 text

RESTful Web Services Representational state transfer (REST) is a software architectural style that was created to guide the design and development of the architecture for the World Wide Web. REST defines a set of constraints for how the architecture of an Internet-scale distributed hypermedia system, such as the Web, should behave. The REST architectural style emphasises the scalability of interactions between components, uniform interfaces, independent deployment of components, and the creation of a layered architecture to facilitate caching components to reduce user-perceived latency, enforce security, and encapsulate legacy systems… 6 Source: https://en.wikipedia.org/wiki/Representational_state_transfer

Slide 7

Slide 7 text

The simplicity: Data conventions! 7 GET /twink/contacts/DLEY-ACLH6Y HTTP/1.1 Host: homer.developi.info Cache-Control: no-cache { "zip": "13202", "state": "NY", "lastName": "Abbate", "middle": "J", "country": "US", "emailAddress": "Jessica.J.Abbate@trashymail.com", "number": "DLEY-ACLH6Y", "city": "Syracuse", "firstName": "Jessica" }

Slide 8

Slide 8 text

The Conversation Makes Sense! 8 http://appserver.company.com/apps/contacts.nsf/ GiveMeTheContactWeNeedPleaseAgent?OpenAgent&id=1522 ⤋ http://appserver.company.com/api/contacts/1522

Slide 9

Slide 9 text

URL Conventions: Verb + Resource •GET http://appserver.company.com/api/contacts •GET http://appserver.company.com/api/contacts/UK/London •GET http://appserver.company.com/api/contacts/1522 •POST http://appserver.company.com/api/contacts •PUT http://appserver.company.com/api/contacts/1522 •DELETE http://appserver.company.com/api/contacts/1522 •Simple CRUD actions for Contact resource… 9

Slide 10

Slide 10 text

Stateless / Cacheable / Layered 10 Every request processed independentl y Everything cacheabl e Client does not care who cooked the meal in the kitche n ⇣ Scalable, Robust, Resilient

Slide 11

Slide 11 text

Back-end User Interface Business Logic Datastore Mobile Applications Front-end External Apps Microservice Microservice Microservice Integration Architectures Evolving! 11 User Interface Business Logic Datastore Front-end Back-end

Slide 12

Slide 12 text

RESTful, Everywhere! •Solid Architecture •Well-defined practices •Widespread use •Intuitive Design •Easily consumable •Scalable 12 Source: https://openclipart.org/detail/221722/cloud-network

Slide 13

Slide 13 text

Designing RESTful APIs… Design-first vs Code-first?

Slide 14

Slide 14 text

Example: Collaboration Today API •Collaboration Today API –Alternative front-end –Integrate to different consumers –Keep the data in NSF –Reuse current implementation •Three Sections: –Presentation (Reading News) –Curation (Adding/Publishing News) –RSS Feeding (DOTS FeedMonster) 14

Slide 15

Slide 15 text

CollaborationToday API 15 Recent Stories Stories By Author Story fi elds needed List Tags/Categories Stories By Tag

Slide 16

Slide 16 text

CollaborationToday API 16

Slide 17

Slide 17 text

CollaborationToday API 17

Slide 18

Slide 18 text

Designing RESTful API •Contract Design –URLs (Resources + Verbs) –Data formats –Rules, Success and Error Responses •Tip: –Start with the end product. –Write a documentation first, before coding. –No “correct way”, only “best practices” –Follow Conventions 18 * Icons made by Flat Icons from www. fl aticon.com

Slide 19

Slide 19 text

Designing RESTful API •Security Design –Authentication / Authorization –Administration Lifecycle –Application Security •Tips –The scope of the implementation is the key. –Managing security is often overlooked. –Security starts with the design phase. 19 * Icons made by Flat Icons from www. fl aticon.com

Slide 20

Slide 20 text

Designing RESTful API •Versioning –Enumeration, Lifecycle •Documentation –OpenAPI Specs (a.k.a. Swagger) –Generate Server stubs, client libraries –Interactive documentation •Testing –Automated testing 20 * Icons made by Flat Icons from www. fl aticon.com /v1/api/xyz /v2/api/xyz /api1/xyz /api2/xyz

Slide 21

Slide 21 text

RESTful Services fo r HCL Domino Applications Review of our options…

Slide 22

Slide 22 text

6 Polite Ways of RESTful Domino 1. HCL Domino Keep (a.k.a HCL Domino REST API) 2. HCL Domino AppDev Pack (Node.js) 3. XPages Extension Library Components 4. Hardcoded Services (Web Agents, XAgents, Servlets) 5. JAX-RS (OSGi Plugin, Jakarta, etc.) 6. Hybrid approaches 22

Slide 23

Slide 23 text

HCL Domino Keep (Domino REST API) 1

Slide 24

Slide 24 text

Domino Keep (HCL Domino REST API) •Provides REST API access for Domino servers and databases •Broader approach for RESTful access to Domino •Currently on Early Access –GA on Domino 12.0.1 •Makes Domino Access Services obsolete. 24

Slide 25

Slide 25 text

Domino Keep (HCL Domino REST API) •Access definitions for Domino apps –Form/view/agent access –DQL Support –Tweaking what to expose –Additional security •Design access •PIM access •OData access (Salesforce, Excel, SAP, etc.) •Server administration 25

Slide 26

Slide 26 text

Domino Keep - Capabilities •Security –Authentication with JWT / External IdP / Domino login –Opt-in security: Access denied by default •Agent Processing –Run or Queue agents by API –Provide parameters / document context •Extensibility 26

Slide 27

Slide 27 text

Domino Keep Architecture •Keep task •EventBus to worker verticles •New verticles can be added •DominoJNX –Brand new Java API for Domino 27 Source: https://opensource.hcltechsw.com/domino-keep-docs/

Slide 28

Slide 28 text

Domino Keep: Summary – Exciting Project – Effective replacement for Domino Access Services – Go to https://opensource.hcltechsw.com/domino-keep-docs – Start using today and provide feedback! – What not to expect: – Mostly Data, not the business logic – Not production ready yet, getting there 28

Slide 29

Slide 29 text

HCL Domino AppDev Pack (Node.js) 2

Slide 30

Slide 30 text

HCL Domino AppDev Pack •DQL + Domino AppDev Pack: –Domino Query Language –AppDev Pack: Proton Task / domino-db.js / com.hcl.domino.db •Countless opportunities in the most popular framework •Different possibilities for the architecture •Wide range of options for tooling 30 https://insights.stackoverflow.com/survey/2019

Slide 31

Slide 31 text

Node.js Support for Domino Apps 31 HCL Domino Server Proton Node.js Layer domino-db.js GRPC Application ……… Application REST New Add-o n Domino v10 Routers for the RESTful service Might be on the same box or not MyRoutes.js NSF

Slide 32

Slide 32 text

Node.js Support for Domino Apps 32 Node.js Layer domino-db.js Routers for the RESTful service MyRoutes.js https://github.com/sbasegmez/Engage19Demo/

Slide 33

Slide 33 text

DQL: Domino Query Language •Available since Domino V10 •Optimized query access to NSF data •Server extracts and optimizes data for DQL access •Evolving fast! 33 John Curtis, “Factory Tour DQL Performance Explanation”, https://jdcurtis.blog/2019/07/17/factory-tour-dql-performance-explanation/

Slide 34

Slide 34 text

IAM: Identity and Access Management 34 * IAM Setup documentation - https://doc.cwpcollaboration.com/appdevpack/docs/en/iam_setup.html

Slide 35

Slide 35 text

Bottom line… •Domino Keep vs AppDev Pack •GRPC vs HTTP •Middlewares •Language and framework preference •Bringing new developers •Code to market speed 35

Slide 36

Slide 36 text

XPages Extension Library Components 3

Slide 37

Slide 37 text

REST Components (ExtLib) •Provided and Supported by HCL •Customizable component version of the DAS –Computed/Filtered columns, Custom search, etc. –Event model helps building business logic on top of REST model •Custom REST Service –Write your own SSJS or Java bean •Write your CSJS routines for async access –Remote Service / JSON-RPC –Dojo support for single page model 37

Slide 38

Slide 38 text

REST Components (ExtLib) •Setup REST component(s) on your page. •Minimal coding, no administrator needed. 38 Add to your XPage Add a Service Con fi gure Options

Slide 39

Slide 39 text

REST Components (ExtLib) •Drawbacks: –Easy to slip into a spagetti code! –Not optimized for performance and scalability –Difficult to follow RESTful URL Convention 39 https://someserver.domain.com/database.nsf/somepage.xsp/service/…

Slide 40

Slide 40 text

Hardcoded Services (Web Agents, XAgents, Servlets) 4

Slide 41

Slide 41 text

Hardcoding (Web agents, XAgents, Servlets…) •Old school way; still quite useful for some cases. •Great if you have pre-existing code (e.g. Lotusscript libraries, etc.) •Also, useful to prototype quick ideas. •Customizable, flexible and simple way to create any service. 41

Slide 42

Slide 42 text

Hardcoding (Web agents, XAgents, Servlets…) •Drawbacks: –Hardcode everything… •e.g. Header/parameter extraction –Very easy to slip into a spagetti code! •Error handling / proper testing needed –Difficult to follow RESTful URL Convention 42 https://someserver.domain.com/database.nsf/xagent.xsp?… https://someserver.domain.com/database.nsf/someagent?OpenAgent&…

Slide 43

Slide 43 text

JAX-RS (OSGi Plugin, Jakarta, etc.) 5

Slide 44

Slide 44 text

Java (JAX-RS) way to RESTful Services •JAX-RS: ‘Java-ish’ way to define RESTful services –Create JAX-RS based REST services on top of Java classes. –Complete Java solution, extensible with custom providers •Options –Apache Wink 1.1.2 (DAS uses!) –Jakarta EE (Official Java) –RestEasy, Apache CXF, Jersey, etc. •Code reusability outside HCL Domino world. 44

Slide 45

Slide 45 text

JAX-RS Architecture 45 JAX-RS Runtime Application Code Servle t (Customizable) HTTP/HTTPS Client Datastore(s) Resource Resource Resource Resource Controller s

Slide 46

Slide 46 text

JAX-RS Development 46 @Path("/contacts") public class ContactResource { private DominoAccessor accessor = new DominoAccessor(ContextInfo.getUserSession()); @GET() public Response getContactList( @QueryParam("start") int start, @QueryParam("count") int count) { List contactList = accessor.pullContacts(start, count); String result = ModelUtils.toJson(contactList).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } @Path("/{id}") @GET() public Response getContact(@PathParam("id") String id) { Contact contact = accessor.findContact(id); if(null == contact) { throw new WebApplicationException(Response.Status.NOT_FOUND); } else { String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } } } { "zip": "13202", "state": "NY", "lastName": "Abbate", "middle": "J", "country": "US", "emailAddress": "Jessica.J.Abbate@trashymail.com", "number": "DLEY-ACLH6Y", "city": "Syracuse", "firstName": "Jessica" } Contact Resource Class Contact Resourc e Short JSON Representation

Slide 47

Slide 47 text

@Path("/contacts") public class ContactResource { private DominoAccessor accessor = new DominoAccessor(ContextInfo.getUserSession()); @GET() public Response getContactList( @QueryParam("start") int start, @QueryParam("count") int count) { List contactList = accessor.pullContacts(start, count); String result = ModelUtils.toJson(contactList).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } @Path("/{id}") @GET() public Response getContact(@PathParam("id") String id) { Contact contact = accessor.findContact(id); if(null == contact) { throw new WebApplicationException(Response.Status.NOT_FOUND); } else { String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } } } JAX-RS Development 47 The base URI for the resourc e In the demo, the root path of the plugin is “/twink”. So this class is enabled for requests made to : /twink/contacts/*

Slide 48

Slide 48 text

@Path("/contacts") public class ContactResource { private DominoAccessor accessor = new DominoAccessor(ContextInfo.getUserSession()); @GET() public Response getContactList( @QueryParam("start") int start, @QueryParam("count") int count) { List contactList = accessor.pullContacts(start, count); String result = ModelUtils.toJson(contactList).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } @Path("/{id}") @GET() public Response getContact(@PathParam("id") String id) { Contact contact = accessor.findContact(id); if(null == contact) { throw new WebApplicationException(Response.Status.NOT_FOUND); } else { String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } } } JAX-RS Development 48 This method responds to GET requests . No path de fi ned, so this is the default responder.

Slide 49

Slide 49 text

@Path("/contacts") public class ContactResource { private DominoAccessor accessor = new DominoAccessor(ContextInfo.getUserSession()); @GET() public Response getContactList( @QueryParam("start") int start, @QueryParam("count") int count) { List contactList = accessor.pullContacts(start, count); String result = ModelUtils.toJson(contactList).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } @Path("/{id}") @GET() public Response getContact(@PathParam("id") String id) { Contact contact = accessor.findContact(id); if(null == contact) { throw new WebApplicationException(Response.Status.NOT_FOUND); } else { String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } } } JAX-RS Development 49 This method also responds to GET requests . But it the request path will be elected based on this format.

Slide 50

Slide 50 text

@Path("/contacts") public class ContactResource { private DominoAccessor accessor = new DominoAccessor(ContextInfo.getUserSession()); @GET() public Response getContactList( @QueryParam("start") int start, @QueryParam("count") int count) { List contactList = accessor.pullContacts(start, count); String result = ModelUtils.toJson(contactList).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } @Path("/{id}") @GET() public Response getContact(@PathParam("id") String id) { Contact contact = accessor.findContact(id); if(null == contact) { throw new WebApplicationException(Response.Status.NOT_FOUND); } else { String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } } } JAX-RS Development 50 Parameters will be injected into methods . /contacts?start=X&count=Y /contacts/someId JAX-RS servlet will handle type conversion . It supports ordinary java objects, enums, primitives, etc.

Slide 51

Slide 51 text

@Path("/contacts") public class ContactResource { private DominoAccessor accessor = new DominoAccessor(ContextInfo.getUserSession()); @GET() public Response getContactList( @QueryParam("start") int start, @QueryParam("count") int count) { List contactList = accessor.pullContacts(start, count); String result = ModelUtils.toJson(contactList).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } @Path("/{id}") @GET() public Response getContact(@PathParam("id") String id) { Contact contact = accessor.findContact(id); if(null == contact) { throw new WebApplicationException(Response.Status.NOT_FOUND); } else { String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } } } JAX-RS Development 51 There are lots of options of returning response . ResponseBuilders and some other helpers make it quite easy.

Slide 52

Slide 52 text

@Path("/contacts") public class ContactResource { private DominoAccessor accessor = new DominoAccessor(ContextInfo.getUserSession()); @GET() public Response getContactList( @QueryParam("start") int start, @QueryParam("count") int count) { List contactList = accessor.pullContacts(start, count); String result = ModelUtils.toJson(contactList).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } @Path("/{id}") @GET() public Response getContact(@PathParam("id") String id) { Contact contact = accessor.findContact(id); if(null == contact) { throw new WebApplicationException(Response.Status.NOT_FOUND); } else { String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } } } JAX-RS Development 52 Error handling is handled by the JAX-RS engine as well . You can inject your own errors.

Slide 53

Slide 53 text

@Path("/contacts") public class ContactResource { @POST() @Consumes(MediaType.APPLICATION_JSON) public Response postContactJson(String body) { Contact contact = ModelUtils.buildContactfromJson(body); accessor.saveNewContact(contact); String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } @POST() @Consumes(MediaType.MULTIPART_FORM_DATA) public Response postContactForm(BufferedInMultiPart formData) { Contact contact = ModelUtils.buildContactfromMultipart(formData); accessor.saveNewContact(contact); String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } } JAX-RS Development 53 This methods respond to POST requests . This time the selection depends on the incoming data type . Client marks the request with Content-Type header and Request processor will select the appropriate method here.

Slide 54

Slide 54 text

@Path("/contacts") public class ContactResource { @POST() @Consumes(MediaType.APPLICATION_JSON) public Response postContactJson(String body) { Contact contact = ModelUtils.buildContactfromJson(body); accessor.saveNewContact(contact); String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } @POST() @Consumes(MediaType.MULTIPART_FORM_DATA) public Response postContactForm(BufferedInMultiPart formData) { Contact contact = ModelUtils.buildContactfromMultipart(formData); accessor.saveNewContact(contact); String result = ModelUtils.toJson(contact).toString(); return Response.ok(result, MediaType.APPLICATION_JSON).build(); } } JAX-RS Development 54 Wink injects the incoming data into the method automatically . JAX-RS libraries provide their own implementation to process different data formats (Multipart, Atom, XML, JSON, etc.)

Slide 55

Slide 55 text

JAX-RS Inside / Outside 55 •Develop an OSGi Plugin for Domino –Apache Wink, JakartaEE, etc. –Modern development tools –For large scale implementations •Use Jakarta EE to use JAX-RS inside NSF •Develop J2EE outside of Domino

Slide 56

Slide 56 text

JAX-RS as OSGi Plugin 56 JAX-RS Runtime Application Code Servle t (Customizable) HTTP/HTTPS Client Datastore(s) Resource Resource Resource Resource Controller s

Slide 57

Slide 57 text

JAX-RS Inside NSF 57 JAX-RS Runtime Application Code Servle t (Customizable) HTTP/HTTPS Client Datastore(s) Resource Resource Resource Resource Controller s

Slide 58

Slide 58 text

JAX-RS inside NSF •Initial work: Martin Pradny •Included in Jakarta EE by Jesse Gallagher •JAX-RS 2.1 support (Apache Wink uses 1.1) •No need to deal with OSGi •Directly create annotated classes inside NSF •OpenAPI specs annotations supported! 58 https://www.pradny.com/2019/05/using-jax-rs-inside-nsf-follow-up.html

Slide 59

Slide 59 text

Alternative: Integrate Domino into Open Liberty •Implementation: Jesse Gallagher –Inspired by Sven Hasselbach •Run Java EE server –e.g. Open Liberty •Run Domino HTTP Stack side by side •Deploy Java EE projects connecting to Domino data natively. •HTTP/2, Servlet 4, Websockets, etc. •High performance, scalability 59 https://frostillic.us/blog/posts/2019/1/3/be9501a07279b40d85258377007b0dfd

Slide 60

Slide 60 text

JAX-RS Methods •Plugin-path might be the longest one… –Difficult, if you are not familiar –Overkill? •Not suitable for small projects and simple needs –Tool selection is critical. •Apache Wink is old school •Integrating alternatives might be difficult •Consider alternatives carefully. 60

Slide 61

Slide 61 text

On Apache Wink… h tt ps://speakerdeck.com/sbasegmez/iconuk-2016-rest-assured... On Jakarta EE… (by Jesse Gallagher) h tt ps://github.com/OpenNTF/org.openn tf .xsp.jakartaee For More Detail on JAX-RS… 61

Slide 62

Slide 62 text

Hybrid approaches 6

Slide 63

Slide 63 text

Hybrid Approaches •Wrap services using a suitable middleware –Express, Node-RED, Spring etc. •Wrap missing parts from existing assets •Add some magic –Security, caching, misc. services •Combine best of all worlds •Right tools for the right job •Consistency across the solution •Optimised Implementation 63 Domino Server Node.js ExtLib REST Service JAX-RS Service Domino Keep domino-db.js JavaScript Services Wrapped Services Data / Application Layer Non-Domino Services API Clients API Clients API Clients Proton

Slide 64

Slide 64 text

Tools… Documentation and Testing

Slide 65

Slide 65 text

Tooling - OpenAPI •OpenAPI Specifications / Documentation –Swagger Tools - swagger.io –Stoplight Studio - stoplight.io –Apicurio - apicur.io 65

Slide 66

Slide 66 text

Tooling - Testing •Testing –Postman - postman.com –Paw - paw.cloud [Mac only] –SoapUI - soapui.org 66

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

Thank you! Serdar Basegmez Developi Information Systems, London serdar_basegmez serdar.basegmez@developi.com lotusnotus.com

Slide 69

Slide 69 text

Resources • Serdar Başeğmez: Node.js demo for this session 
 https://github.com/sbasegmez/Engage19Demo • Tom Van Aken: Rest calls and JSON Parsing in LotusScript 
 https://vanakentom.wordpress.com/2019/01/15/rest-calls-and-json-parsing-in-lotusscript/ • Serdar Başeğmez: Demo for IBM Connect 2017 session 
 https://github.com/sbasegmez/IC17RestDemo • Serdar Başeğmez: Apache Wink Template and Demo for Icon UK 2016 
 https://github.com/sbasegmez/RestAssuredDemo • Graham Acres / Serdar Başeğmez: The Journey to Becoming a Social Application Developer (IBM Connect 2014) 
 https://speakerdeck.com/sbasegmez/bp308-the-journey-to-becoming-a-social-application-developer • Stephan H. Wissel: Custom REST service in XPages using a service bean 
 https://wissel.net/blog/d6plinks/SHWL-9Q55QL 69

Slide 70

Slide 70 text

Resources (cont.) •Eric McCormick: Series on JSON Data with Java in XPages 
 https://edm00se.io/json-with-java-in-xpages •Thomas Ladehoff: REST Services with the XPages Extension Library 
 https://www.assono.de/blog/d6plinks/REST-Services-with-the-XPages-Extension-Library •Paul Withers: XPages OSGi Plugins series 
 http://www.intec.co.uk/xpages-osgi-plugins-1-an-introduction/ •John Cooper: Domino OSGI (Part 1) - Configuring Eclipse for XPages OSGI Plugins 
 http://developmentblog.johnmcooper.co.uk/2014/05/configuring-eclipse-for-xpages-osgi-plugins-part1.html •Toby Samples: JAX-RS or THE way to do REST in Domino series 
 https://tobysamples.wordpress.com/2015/04/28/jax-rs-or-the-way-to-do-rest-in-domino-part-1/ •Jesse Gallagher: Eclipse Tutorial for Domino Developers 
 https://github.com/jesse-gallagher/eclipse-tutorial-oct2015/wiki/Java 70

Slide 71

Slide 71 text

Resources (cont.) •Ulrich Krause: NotesJsonNavigator, NotesJsonElement, NotesJsonArray, NotesJsonObject example 
 https://www.eknori.de/2019-01-01/notesjsonnavigator-notesjsonelement-notesjsonarray-notesjsonobject-example/ •John Dalsgaard: REST Services in IBM Domino/XWork 
 https://www.dalsgaard-data.eu/blog/rest-services-in-ibm-dominoxwork •Oliver Busse: First dive into Domino and Node.js 
 http://oliverbusse.notesx.net/hp.nsf/blogpost.xsp?documentId=2E52 •Oliver Busse: Domino, Proton, IAM, OAuth (Series) 
 http://oliverbusse.notesx.net/hp.nsf/blogpost.xsp?documentId=2FEA •Sven Hasselbach: node.js, domino-db & Docker 
 http://hasselba.ch/blog/?p=2670 •Jesse Gallagher: That Java Thing, Part 1: The Java Problem in the Community 
 https://frostillic.us/blog/thread.xsp?thread=That+Java+Thing 71

Slide 72

Slide 72 text

Resources (cont.) •Graham Acres / Heiko Voigt: Engage 2019 Demo of Domino v10, Proton and Node.js session 
 https://github.com/c3ug/engage2019democode •Troy Reimer: OpenNTF Project: LotusScript implementation of a reader and writer for JSON 
 https://openntf.org/main.nsf/project.xsp?r=project/JSON%20LotusScript%20Classes •Bansilal Haudakari: Effective API Design 
 https://www.slideshare.net/BansilalHaudakari/effective-api-design •Heiko Voigt: How to set up the Domino 10 OAUTH2 Provider - IAM Basics 
 https://www.harbour-light.org/2019/02/18/how-to-set-up-the-domino-10-oauth2-provider-iam-basics/ •Martin Pradny: Using JAX-RS inside NSF follow-up - Swagger UI 
 https://www.pradny.com/2019/05/using-jax-rs-inside-nsf-follow-up.html •Cross Canada Collaboration User Group: John Curtis - Domino Query Language with John Curtis Part 1 
 https://www.youtube.com/watch?v=qm_LJ9-6OTE 72

Slide 73

Slide 73 text

Resources (cont.) •Cross Canada Collaboration User Group: Heiko Voight - Demos from the C3UG AppDevPack Roundtable, March 29, 2021 
 https://www.youtube.com/watch?v=M0Cm7oZakKU&t=950s •Cross Canada Collaboration User Group: Education 
 http://www.c3ug.ca/education •HCL: HCL Domino Keep Documentation 
 https://opensource.hcltechsw.com/domino-keep-docs/ •Stephan Wissel / Paul Withers: July OpenNTF Webinar - HCL Presents Keep, a new API for Domino 
 https://www.youtube.com/watch?v=6CydwW7V5MA 73