{"id":1,"date":"2019-10-11T12:51:54","date_gmt":"2019-10-11T10:51:54","guid":{"rendered":"https:\/\/jonathanpapa.com\/blog\/?p=1"},"modified":"2022-05-11T22:25:26","modified_gmt":"2022-05-11T20:25:26","slug":"sapb1-mssql-webclient","status":"publish","type":"post","link":"https:\/\/jonathanpapa.com\/blog\/2019\/10\/11\/sapb1-mssql-webclient\/","title":{"rendered":"Homemade SAP B1 Web Client using MSSQL"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"1\" class=\"elementor elementor-1\">\n\t\t\t\t\t\t<div class=\"elementor-inner\">\n\t\t\t\t<div class=\"elementor-section-wrap\">\n\t\t\t\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-693cde9 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"693cde9\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0785c48\" data-id=\"0785c48\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-baa569a elementor-widget elementor-widget-text-editor\" data-id=\"baa569a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<h4>SAP B1, MariaDb, Node.JS express and OpenUI5 walk into a bar&#8230;<\/h4>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-d0034c6 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"d0034c6\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-85e8cf5\" data-id=\"85e8cf5\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-e01b2b6 elementor-widget elementor-widget-heading\" data-id=\"e01b2b6\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Introduction<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-e9c2d11 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"e9c2d11\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-7f5e222\" data-id=\"7f5e222\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-6154a7e elementor-widget elementor-widget-text-editor\" data-id=\"6154a7e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-11ba678 elementor-widget elementor-widget-text-editor\" data-id=\"11ba678\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Lately, my attention has been drawn to javascript technologies and I thought it&rsquo;d be good fun (that&rsquo;s how funny I am), to learn some of them.\u00a0<\/p>\n<p>Since I&rsquo;ve been working on SAP Business One for several years now, my idea was to hit two birds with one stone and build a simple web application that would eventually communicate with the ERP, breaking the codes of the traditional B1 applications you may find out there. In other words: I didn&rsquo;t want to build a .NET API nor the Entity Framework to fetch data from the database (we&rsquo;ll talk about the writing a few paragraphs below).<\/p>\n<p>For this project, I used SAP B1 9.3 PL11 for MSSQL and the french demo database.<\/p>\n<p>They say a picture is worth a thousand words so here&rsquo;s what this is about (the orders you see in the gif all come from SAP B1):<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8233a7c elementor-widget elementor-widget-image\" data-id=\"8233a7c\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/animatedApp.gif\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"animatedApp\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTc0LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL2FuaW1hdGVkQXBwLmdpZiJ9\">\n\t\t\t\t\t\t\t<img width=\"1076\" height=\"660\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/animatedApp.gif\" class=\"attachment-full size-full\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">A glimpse of the application (click to zoom)<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-93b4250 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"93b4250\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-2f35a75\" data-id=\"2f35a75\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-e209f6b elementor-widget elementor-widget-text-editor\" data-id=\"e209f6b\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p style=\"margin-bottom: 1.4em; font-size: 17px; font-style: normal; font-weight: 400; text-align: justify;\"><span style=\"font-weight: bold;\">Disclaimer<\/span>: this is\u00a0<span style=\"font-weight: bold;\">not<\/span>\u00a0a tutorial, but rather a description of my approach at a Business One web UI.\u00a0<\/p>\n<p style=\"margin-bottom: 1.4em; font-size: 17px; font-style: normal; font-weight: 400; text-align: justify;\">With the upcoming web version of B1 (version 10), now than ever it is more important to understand how Business One can interract with the open world.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-53c046c elementor-widget__width-inherit elementor-widget elementor-widget-image\" data-id=\"53c046c\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t<img width=\"1\" height=\"1\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/sapb1logo.svg\" class=\"attachment-medium size-medium\" alt=\"\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">Our mighty friend<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-289de9d6 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"289de9d6\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-76d7501a\" data-id=\"76d7501a\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-24406b6e elementor-widget elementor-widget-text-editor\" data-id=\"24406b6e\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p><!-- wp:paragraph --><\/p>\n<p><span style=\"font-style: inherit; font-weight: inherit;\">Historically, people would customize B1 by building Add-Ons that would directly plug into the fat client and enhance the solution using both DI-API (to add\/update\/delete business objects) and UI-API (to build custom screens). <\/span><\/p>\n<p><span style=\"font-style: inherit; font-weight: inherit;\">This approach is definitely an option if the users don&rsquo;t want to leave the B1 client to perform custom tasks.\u00a0<\/span><\/p>\n<p><!-- \/wp:paragraph --><\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8f2ef00 elementor-widget elementor-widget-image\" data-id=\"8f2ef00\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359B1.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"Order359B1\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjMyLCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL09yZGVyMzU5QjEucG5nIn0%3D\">\n\t\t\t\t\t\t\t<img width=\"812\" height=\"588\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359B1.png\" class=\"attachment-large size-large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359B1.png 890w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359B1-300x217.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359B1-768x556.png 768w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">SAP B1 may not have the most user-friendly interface, but we'll change that in this article.<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-8d169ba elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"8d169ba\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4c185c1\" data-id=\"4c185c1\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2aab77d elementor-widget elementor-widget-text-editor\" data-id=\"2aab77d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p><span style=\"font-style: inherit; font-weight: inherit;\">In this article, we will build a Sales Order screen using SAPUI5.<\/span><\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-b2fbd6f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"b2fbd6f\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f903a23\" data-id=\"f903a23\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-919031b elementor-widget elementor-widget-image\" data-id=\"919031b\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359WebAppV2.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"Order359WebAppV2\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjM0LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL09yZGVyMzU5V2ViQXBwVjIucG5nIn0%3D\">\n\t\t\t\t\t\t\t<img width=\"812\" height=\"569\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359WebAppV2-1024x717.png\" class=\"attachment-large size-large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359WebAppV2-1024x717.png 1024w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359WebAppV2-300x210.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359WebAppV2-768x538.png 768w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/Order359WebAppV2.png 1065w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">What we can do with a little bit of UI5<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-a3ff4a4 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a3ff4a4\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-88ac38b\" data-id=\"88ac38b\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-64e5eba elementor-widget elementor-widget-text-editor\" data-id=\"64e5eba\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>You may already know some of the most popular javascript front-end frameworks on the market, a non exhaustive list would be: React, Angular and Vue.JS. Even if you&rsquo;ve never used them, there&rsquo;s a great chance you&rsquo;ve, at least, heard about them. Applications built on top of these frameworks are also called\u00a0<strong>SPA\u00a0<\/strong>for <strong>S<\/strong>ingle\u00a0<strong>P<\/strong>age\u00a0<strong>A<\/strong>pplications because you usually only request one page to the server, and that page is re-rendered with javascript as you navigate through the app.<\/p>\n<p>However, people that work around SAP may know another JS framework that is (of course), far less used that the ones I mentionned above. Indeed, I&rsquo;m talking about:<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fb6815a elementor-widget elementor-widget-image\" data-id=\"fb6815a\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t<figure class=\"wp-caption\">\n\t\t\t\t\t\t\t\t\t\t<img width=\"300\" height=\"156\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/ui5logo-e1571123530789-300x156.png\" class=\"attachment-medium size-medium\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/ui5logo-e1571123530789-300x156.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/ui5logo-e1571123530789-768x400.png 768w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/ui5logo-e1571123530789.png 789w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/>\t\t\t\t\t\t\t\t\t\t\t<figcaption class=\"widget-image-caption wp-caption-text\">SAPUI5, OpenUI5, Fiori... Wait, how is it called? \ud83e\udd14<\/figcaption>\n\t\t\t\t\t\t\t\t\t\t<\/figure>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-69509ab elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"69509ab\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c14b062\" data-id=\"c14b062\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-c05d92d elementor-widget elementor-widget-text-editor\" data-id=\"c05d92d\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>When working with UI5, you may hear a lot of different names for it: SAPUI5, OPENUI5, Fiori App etc&#8230;\u00a0<\/p>\n<p>There&rsquo;s a lot of confusion as to what is what. I am not going to go into the details but let&rsquo;s just see it this way: <strong>OpenUI5<\/strong> is the base framework, it contains all the controls you need to build your application and is free to use. <strong>SapUI5<\/strong> adds another layer on top of OpenUI5 with more controls (for instance, you can use charts that aren&rsquo;t available in OpenUI5) and requires a license to use. Then, <strong>Fiori<\/strong> refers to the UX guidelines defined by SAP. Finally, <em><strong>SAP Fiori Elements<\/strong><\/em> which is a framework on top of UI5 to automate the creation of page based on custom OData annotations provided by SAP.<\/p>\n<p>If you want to dig deeper into this, just check the demo kits of the two versions (OpenUI5 &amp; SapUI5), you will see the difference:<\/p>\n<ul>\n<li><a href=\"https:\/\/openui5.hana.ondemand.com\/#\/controls\" target=\"_blank\" rel=\"noopener\">OpenUI5 Demo Kit<\/a><\/li>\n<li><a href=\"https:\/\/sapui5.hana.ondemand.com\/#\/controls\" target=\"_blank\" rel=\"noopener\">SapUI5 Demo Kit<\/a><\/li>\n<\/ul>\n<div>I decided to use OpenUI5 since I wanted to stick to the SAP look and feel and I didn&rsquo;t need the additional controls for my small project. In either case, don&rsquo;t get confused about OpenUI5\/SapUI5 difference. Just know that you can develop for free on OpenUI5. If you&rsquo;re involved in a SAP project using UI5, there&rsquo;s a greater chance you&rsquo;ll use SapUI5 and enjoy the additional features.<\/div>\n<div>\u00a0<\/div>\n<div>Also, one side note is that you can switch from OpenUI5 to SapUI5 without any issues, however, you may face trouble if, for some reason, you decide to switch from SapUI5 to OpenUI5 (since some components will be missing).<\/div>\n<div>\u00a0<\/div>\n<div>The main benefit about using UI5 (whether it is Open\/Sap) is that you only need to provide the data to the framework (as JSON for instance), and it takes care of rendering it into nice pages and controls. This saves you a tremendous amount of time because you don&rsquo;t have to pay attention to the look-and-feel (that&rsquo;s the idea).<\/div>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-1b108be elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"1b108be\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-bfca219\" data-id=\"bfca219\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-fd04aab elementor-widget elementor-widget-heading\" data-id=\"fd04aab\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">So... This is all about HANA right... ? \ud83e\udd28<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7d5c329 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7d5c329\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-37ed00d\" data-id=\"37ed00d\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-c17f9d1 elementor-widget elementor-widget-text-editor\" data-id=\"c17f9d1\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p><strong>No.<\/strong><\/p>\n<p>HANA adds a lot of extensibility features, and one of them is holy grail for SAP B1 developers. I&rsquo;m talking about the <strong>Service Layer<\/strong>.<\/p>\n<p>The Service Layer is an out-of-the-box and simple REST API you can use to <strong>C<\/strong>reate, <strong>R<\/strong>ead, <strong>U<\/strong>pdate and\u00a0<strong>D<\/strong>elete entities in SAP Business One. It is only available on HANA for the moment (for production purpose) <strong>but you can try it out for the MSSQL version for testing purposes.\u00a0<\/strong>And I must have read somewhere that it will be available for MSSQL on version 10 (along with the Web UI). <img class=\"_1ift _1ifu img\" src=\"https:\/\/static.xx.fbcdn.net\/images\/emoji.php\/v9\/t27\/1\/32\/1f973.png\" alt=\"\ud83e\udd73\" \/><\/p>\n<p><span style=\"text-decoration: underline;\"><strong>UPDATE 2022<\/strong><\/span>: Service Layer is now available for SAP B1 version for MSSQL.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6229f11 elementor-widget elementor-widget-image\" data-id=\"6229f11\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/expSLv2.png\" data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-title=\"expSLv2\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTY5LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL2V4cFNMdjIucG5nIn0%3D\">\n\t\t\t\t\t\t\t<img width=\"812\" height=\"496\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/expSLv2-1024x626.png\" class=\"attachment-large size-large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/expSLv2-1024x626.png 1024w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/expSLv2-300x183.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/expSLv2-768x469.png 768w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/expSLv2.png 1422w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cccfc25 elementor-widget elementor-widget-text-editor\" data-id=\"cccfc25\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>I can&rsquo;t even stress how much I love the Service Layer <em><strong>#BFF<\/strong><\/em>, I wish it would have been available on the MSSQL version from the start because <strong>it just makes building apps for Business One so much easier<\/strong>.<\/p>\n<p>Anyway, the point is, you can now have a cheap test environnement to play around with.<\/p>\n<p><strong>For this application, I am using a MSSQL B1 with the \u00ab\u00a0experimental\u00a0\u00bb service layer.<\/strong><\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c16b686 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c16b686\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-758ecc3\" data-id=\"758ecc3\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-8975be7 elementor-widget elementor-widget-heading\" data-id=\"8975be7\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Technologie stack<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4adbe6b elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"4adbe6b\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-29c777e\" data-id=\"29c777e\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-4652e4f elementor-widget elementor-widget-text-editor\" data-id=\"4652e4f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Alright, enough of the introduction blabla, let&rsquo;s see exactly what types of bricks I used to build that house.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1d8de12 elementor-widget elementor-widget-heading\" data-id=\"1d8de12\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">Back-End<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7f4870c elementor-widget elementor-widget-text-editor\" data-id=\"7f4870c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>SAP Business One (version for MSSQL) 9.3 PL11<\/p>\n<p>Service Layer to Create, Read, Update and Delete data in B1<\/p>\n<p>MariaDb to store my application users<\/p>\n<p>Node.JS + Express to build a custom API (think of it as a middleware between B1 and our web application)<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-40ec1e3 elementor-widget elementor-widget-heading\" data-id=\"40ec1e3\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">Front-End<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7b6737f elementor-widget elementor-widget-text-editor\" data-id=\"7b6737f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>OpenUI5 (Javascript front-end framework to build our UI)<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f171e19 elementor-widget elementor-widget-heading\" data-id=\"f171e19\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">How do they work together?<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cf7d3b8 elementor-widget elementor-widget-image\" data-id=\"cf7d3b8\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t<img width=\"812\" height=\"585\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/architecture.png\" class=\"attachment-large size-large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/architecture.png 914w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/architecture-300x216.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/architecture-768x554.png 768w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3c6d1b6 elementor-widget elementor-widget-text-editor\" data-id=\"3c6d1b6\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p style=\"text-align: justify;\">Let&rsquo;s focus on the back-end because this is where the interesting part is. See that box on the bottom left \u00ab\u00a0<strong>ExpressJS + node JS<\/strong>\u00a0\u00bb ? It is\u00a0the keystone of everything: it authenticates user, and then, allows him to perform a <span style=\"font-style: inherit; font-weight: inherit;\">specific set of actions based on his roles and permissions. It is also the only entry point for every request sent by our web application, which <strong>cannot<\/strong> sends requests directly to the databases nor the service layer.<\/span><\/p>\n<ul style=\"text-align: justify;\">\n<li style=\"text-align: justify;\">I chose to store my users in a separate database and use a JWT authentication mechanism.\n<ul>\n<li>User logs in and get a JWT token that he must send in every subsequent request.<\/li>\n<li>Based on the token, the API knows which user it is talking to and can then check the authorizations and permissions for that user.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<div style=\"text-align: justify;\"><em>If you want to learn more about JWT, you can simply check the website by clicking <a href=\"https:\/\/jwt.io\/\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><\/div>\n<div>\u00a0<\/div>\n<ul>\n<li style=\"text-align: justify;\">I am using TypeORM to query the MariaDb data which allows me to easily handle all my entites (such as Users, Roles and Permissions). Why TypeORM? Simply because it was compatible with MariaDb and available in Typescript. Remember that I started this project to learn technologies I&rsquo;ve never really used. And I must admit I was totally amazed by the ease of use of <em><strong>TypeORM<\/strong><\/em>!<\/li>\n<li style=\"text-align: left;\">As mentionned earlier, calling the Service Layer is also done through the Node.JS Express API. The user never queries directly the Service Layer.\u00a0<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">How do you make sure of it? By setting the \u00ab\u00a0<strong><em>Access-Control-Allow-Origin<\/em><\/strong>\u00a0\u00bb header in the Service Layer configuration and setting the API IP address. Basically, the web application calls the API which checks if the user has the right to use the Service Layer, and then calls the Service Layer which performs actions with a pre-defined technical user.<\/p>\n<p style=\"text-align: justify;\">And of course, since we&rsquo;re using the Service Layer, that means our application is able to <strong>C<\/strong>reate, <strong>R<\/strong>ead, <strong>U<\/strong>pdate and <strong>D<\/strong>elete (aka CRUD) SAP B1 Data.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-69a6a73 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"69a6a73\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-49772b4\" data-id=\"49772b4\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-92f1216 elementor-widget elementor-widget-heading\" data-id=\"92f1216\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Handling the authorizations<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f5a929e elementor-widget elementor-widget-image\" data-id=\"f5a929e\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t<img width=\"770\" height=\"600\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/balroggandalfapi.png\" class=\"attachment-large size-large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/balroggandalfapi.png 770w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/balroggandalfapi-300x234.png 300w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/balroggandalfapi-768x598.png 768w\" sizes=\"(max-width: 770px) 100vw, 770px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3d8505f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"3d8505f\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-ec08e70\" data-id=\"ec08e70\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-f6b6984 elementor-widget elementor-widget-text-editor\" data-id=\"f6b6984\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p class=\"text-align:justify\">Some words about the authentication mechanism, the first step is to login to the application, which grants you a token should the login and password match a database user. The <em><strong>\/Auth\/Login<\/strong><\/em> endpoint is public and can be accessed by anyone.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3f6ab65 elementor-widget elementor-widget-image\" data-id=\"3f6ab65\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t<img width=\"548\" height=\"325\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/loginRequest.png\" class=\"attachment-large size-large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/loginRequest.png 548w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/loginRequest-300x178.png 300w\" sizes=\"(max-width: 548px) 100vw, 548px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-660a9a2 elementor-widget elementor-widget-text-editor\" data-id=\"660a9a2\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Once the user is authenticated, he can then call the other routes which are protected, meaning that the user must send a valid JWT token. (remember, it&rsquo;s in the cookie!)<\/p>\n<p>If the JWT is not valid for some reason, either expired or altered, the request fails and returns an HTTP Status <strong>401 <em>Unauthorized<\/em><\/strong>.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8d71f45 elementor-widget elementor-widget-image\" data-id=\"8d71f45\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-image\">\n\t\t\t\t\t\t\t\t\t\t\t\t<img width=\"548\" height=\"446\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/otherrquests.png\" class=\"attachment-large size-large\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/otherrquests.png 548w, https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/otherrquests-300x244.png 300w\" sizes=\"(max-width: 548px) 100vw, 548px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-029a956 elementor-widget elementor-widget-text-editor\" data-id=\"029a956\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>Each subsequent call performs its own verifications, for instance:<\/p>\n<ul>\n<li>Is the user active?<\/li>\n<li>Does the user have access to that particular resource?\n<ul>\n<li>Example: The user is authenticated, active and tries to call the \u00ab\u00a0api\/B1\u00a0\u00bb endpoint but he doesn&rsquo;t have the \u00ab\u00a0<em><strong>CALL_B1<\/strong><\/em>\u00a0\u00bb permission.<\/li>\n<\/ul>\n<\/li>\n<li><del>Does he listen to Drake?<\/del> (alright, I didn&rsquo;t implement that one)<\/li>\n<\/ul>\n<p>All of these permissions are stored in MariaDb and checked against if needed when the user calls an endpoint.<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4354138 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"4354138\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-1da1a8b\" data-id=\"1da1a8b\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-55f9321 elementor-widget elementor-widget-heading\" data-id=\"55f9321\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Developement Environnement<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-358e4b8 elementor-widget elementor-widget-text-editor\" data-id=\"358e4b8\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>To develop both the API and the web application, I simply used&#8230; Visual Studio Code.<\/p>\n<p>The OpenUI5 application is handled via the OpenUI5 CLI which helps you kickstart and run your application. (More information <a href=\"https:\/\/github.com\/SAP\/ui5-cli\" target=\"_blank\" rel=\"noopener\">here<\/a>)<\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-d2b7ee4 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"d2b7ee4\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-d131964\" data-id=\"d131964\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-13c6782 elementor-widget elementor-widget-heading\" data-id=\"13c6782\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Conclusion<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f82bf7f elementor-widget elementor-widget-text-editor\" data-id=\"f82bf7f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-text-editor elementor-clearfix\">\n\t\t\t\t<p>So, that was my attempt at a Business One client using JS technologies. And yes, l<span style=\"font-style: inherit; font-weight: inherit;\">ots of things can be improved\/changed, like the authentication that could be performed using Auth0, the front-end framework that can be switched and so on&#8230;\u00a0<\/span><\/p>\n<p>With the upcoming web version of SAP B1 now more than ever it is the time to keep up with all of these web technologies!\u00a0<\/p>\n<p><span style=\"font-style: inherit; font-weight: inherit;\">Hope you liked the article!\u00a0<\/span>\ud83e\udd19\ud83c\udffc<\/p>\n<p><span style=\"font-style: inherit; font-weight: inherit;\">Check out the gallery below for some more screenshots of the app!<\/span><\/p>\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-ca95ecc elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"ca95ecc\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t\t\t<div class=\"elementor-row\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-aa0ee77\" data-id=\"aa0ee77\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-column-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-aa18710 elementor-widget elementor-widget-heading\" data-id=\"aa18710\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Gallery<\/h2>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5de0f87 elementor-arrows-position-inside elementor-pagination-position-outside elementor-widget elementor-widget-image-carousel\" data-id=\"5de0f87\" data-element_type=\"widget\" data-settings=\"{&quot;slides_to_show&quot;:&quot;1&quot;,&quot;navigation&quot;:&quot;both&quot;,&quot;autoplay&quot;:&quot;yes&quot;,&quot;pause_on_hover&quot;:&quot;yes&quot;,&quot;pause_on_interaction&quot;:&quot;yes&quot;,&quot;autoplay_speed&quot;:5000,&quot;infinite&quot;:&quot;yes&quot;,&quot;effect&quot;:&quot;slide&quot;,&quot;speed&quot;:500}\" data-widget_type=\"image-carousel.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"elementor-image-carousel-wrapper swiper-container\" dir=\"ltr\">\n\t\t\t<div class=\"elementor-image-carousel swiper-wrapper swiper-image-stretch\">\n\t\t\t\t\t\t\t\t<div class=\"swiper-slide\"><a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"5de0f87\" data-elementor-lightbox-title=\"homePage\" data-elementor-lightbox-description=\"I didn&#039;t know there were 359 orders shipped with the SBODemoFR database, did you?\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTg3LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL2hvbWVQYWdlLnBuZyIsInNsaWRlc2hvdyI6IjVkZTBmODcifQ%3D%3D\" href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/homePage.png\"><figure class=\"swiper-slide-inner\"><img class=\"swiper-slide-image\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/homePage-1024x628.png\" alt=\"Home page\" \/><figcaption class=\"elementor-image-carousel-caption\">I didn't know there were 359 orders shipped with the SBODemoFR database, did you?<\/figcaption><\/figure><\/a><\/div><div class=\"swiper-slide\"><a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"5de0f87\" data-elementor-lightbox-title=\"salesOrder1\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTkxLCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL3NhbGVzT3JkZXIxLnBuZyIsInNsaWRlc2hvdyI6IjVkZTBmODcifQ%3D%3D\" href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/salesOrder1.png\"><figure class=\"swiper-slide-inner\"><img class=\"swiper-slide-image\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/salesOrder1-1024x628.png\" alt=\"List of Sales Orders\" \/><\/figure><\/a><\/div><div class=\"swiper-slide\"><a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"5de0f87\" data-elementor-lightbox-title=\"expanded\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTg4LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL2V4cGFuZGVkLnBuZyIsInNsaWRlc2hvdyI6IjVkZTBmODcifQ%3D%3D\" href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/expanded.png\"><figure class=\"swiper-slide-inner\"><img class=\"swiper-slide-image\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/expanded-1024x451.png\" alt=\"Order with two columns\" \/><\/figure><\/a><\/div><div class=\"swiper-slide\"><a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"5de0f87\" data-elementor-lightbox-title=\"salesOrder2\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTkyLCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL3NhbGVzT3JkZXIyLnBuZyIsInNsaWRlc2hvdyI6IjVkZTBmODcifQ%3D%3D\" href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/salesOrder2.png\"><figure class=\"swiper-slide-inner\"><img class=\"swiper-slide-image\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/salesOrder2-1024x628.png\" alt=\"Order details\" \/><\/figure><\/a><\/div><div class=\"swiper-slide\"><a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"5de0f87\" data-elementor-lightbox-title=\"roleManager\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTg5LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL3JvbGVNYW5hZ2VyLnBuZyIsInNsaWRlc2hvdyI6IjVkZTBmODcifQ%3D%3D\" href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/roleManager.png\"><figure class=\"swiper-slide-inner\"><img class=\"swiper-slide-image\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/roleManager-1024x628.png\" alt=\"Role management\" \/><\/figure><\/a><\/div><div class=\"swiper-slide\"><a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"5de0f87\" data-elementor-lightbox-title=\"createNewUser\" e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjI4LCJ1cmwiOiJodHRwczpcL1wvam9uYXRoYW5wYXBhLmNvbVwvYmxvZ1wvd3AtY29udGVudFwvdXBsb2Fkc1wvMjAxOVwvMTBcL2NyZWF0ZU5ld1VzZXIucG5nIiwic2xpZGVzaG93IjoiNWRlMGY4NyJ9\" href=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/createNewUser.png\"><figure class=\"swiper-slide-inner\"><img class=\"swiper-slide-image\" src=\"https:\/\/jonathanpapa.com\/blog\/wp-content\/uploads\/2019\/10\/createNewUser-1024x659.png\" alt=\"createNewUser\" \/><\/figure><\/a><\/div>\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"swiper-pagination\"><\/div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"elementor-swiper-button elementor-swiper-button-prev\">\n\t\t\t\t\t\t<i aria-hidden=\"true\" class=\"eicon-chevron-left\"><\/i>\t\t\t\t\t\t<span class=\"elementor-screen-only\">Pr\u00e9c\u00e9dent<\/span>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t<div class=\"elementor-swiper-button elementor-swiper-button-next\">\n\t\t\t\t\t\t<i aria-hidden=\"true\" class=\"eicon-chevron-right\"><\/i>\t\t\t\t\t\t<span class=\"elementor-screen-only\">Suivant<\/span>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>SAP B1, MariaDb, Node.JS express and OpenUI5 walk into a bar&#8230; Introduction Lately, my attention has been drawn to javascript technologies and I thought it&rsquo;d be good fun (that&rsquo;s how funny I am), to learn some of them.\u00a0 Since I&rsquo;ve been working on SAP Business One for several years now, my idea was to hit [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":218,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[10,11],"tags":[9,7,8],"_links":{"self":[{"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/posts\/1"}],"collection":[{"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/comments?post=1"}],"version-history":[{"count":10,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/posts\/1\/revisions"}],"predecessor-version":[{"id":900,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/posts\/1\/revisions\/900"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/media\/218"}],"wp:attachment":[{"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/media?parent=1"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/categories?post=1"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jonathanpapa.com\/blog\/wp-json\/wp\/v2\/tags?post=1"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}