BaaS with Kinvey and Delphi 10.1 Berlin

时间:2021-07-23 05:49:40
In this article I will show you how to connect yourdesktop and mobile applications to a mobile backend as a service (mBaaS) with Delphi 10.1 Berlin. I normally use Parse.com as a backend but as they announce that they will close their mBaaS service I will use Kinvey instead.
If you are interested in Parse.com you can read my previous articles about creating your own self-hosted Parse server and deploying a Parse server to Herokuwhich achieves similar result to what I want to explain you today (basically having your data hosted anywhere in the cloud either using Kinvey as an mBaaSor Parse + Heroku as a PaaS).
 There are plenty of articles online about these topics and I just want to give you my input and how I dealt with some of the challenges I faced during development.
 
Join Kinvey and create your App environment
First step is to join Kinvey and create your application environment. Kinvey offers a Free plan for developers that it is ideal to test your applications. It includes the core mBaaS features and 1GB of data storage. Once you move your solution into production you can switch over one of the other plans available.
Once you are in the console management, press "New App" and enter the name of your backend:
BaaS with Kinvey and Delphi 10.1 Berlin
Now you should see your enviromnent created:
BaaS with Kinvey and Delphi 10.1 Berlin
Click on the Development label and the dashboard will be shown:
BaaS with Kinvey and Delphi 10.1 Berlin
At this moment in time, you should know what data you are going to store. In this example I have created a simple collection that includes several fields for a sample application that I'm building and that the source code can be found here:
 
Here is my collection of values:
BaaS with Kinvey and Delphi 10.1 Berlin
*Note that if you POST data to a non-existing collection, this will be created automatically.
Handling collections
Now it's time to start using the collection and querying/adding data via Http REST. For this task you will have to identify the required headers that are needed for your GET/POST requests. You can see one example here for Parse.
 
Kinvey follows a different approach than Parse in terms of security. Kinvey offers basic and session authentiation. Basic authentication uses the HTTP header "Authorization" with the components "Basic" andBase64Encode(AppId:MasterSecret). Session authentication sends a login request to collct an auth token from Kinvey backend and then this token is used in subsequent REST requests.
 
I will focus on Basic authentication as Session authentication is as simple but with more steps.
The first example is by using REST via IdHttp so you can see how GET/POST are handled manually and the second example is just by using the Kinvey provider component available with our Delphi 10.1 Berlin that will make our life easier.

Here it's my Win64 example that uses Kinvey BaaS:

BaaS with Kinvey and Delphi 10.1 Berlin

Add action, adds data into the collection and reload just brings the data back from the cloud and displays it in a listview component.

Here is the code behind it:
Add item:

  // Copyright (c) 2016, Jordi Corbilla
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are met:
  //
  // - Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  // - Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation
  // and/or other materials provided with the distribution.
  // - Neither the name of this library nor the names of its contributors may be
  // used to endorse or promote products derived from this software without
  // specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  // POSSIBILITY OF SUCH DAMAGE.
   
  function TKinveyRest.Add(jsonString: string) : boolean;
  var
  IdHTTP: TIdHTTP;
  IdIOHandler: TIdSSLIOHandlerSocketOpenSSL;
  response : string;
  JsonToSend: TStringStream;
  encodedHeader : string;
  begin
  JsonToSend := TStringStream.Create(jsonString);
  try
  IdIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  IdIOHandler.ReadTimeout := IdTimeoutInfinite;
  IdIOHandler.ConnectTimeout := IdTimeoutInfinite;
  IdHTTP := TIdHTTP.Create(nil);
  try
  IdHTTP.IOHandler := IdIOHandler;
  IdHTTP.Request.Connection := 'Keep-Alive';
  IdIOHandler.SSLOptions.Method := sslvSSLv23;
  IdHTTP.Request.CustomHeaders.Clear;
  encodedHeader := TIdEncoderMIME.EncodeString(FOptions.AppId + ':' + FOptions.MasterSecret);
  IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Basic ' + encodedHeader;
  IdHTTP.Request.CustomHeaders.Values['X-Kinvey-API-Version'] := '3';
  IdHTTP.Request.ContentType := 'application/json';
  response := IdHTTP.Post('https://baas.kinvey.com/appdata/'+FOptions.AppId+'/'+FOptions.Collection+'/', JsonToSend);
  response := response.Replace(AnsiChar(#10), '');
  result := (response.Contains('creator'));
  finally
  IdHTTP.Free;
  end;
  finally
  IdIOHandler.Free;
  JsonToSend.Free;
  end;
  end;
view rawKinveyAdd.pas hosted with ❤ by GitHub

Load data:

  // Copyright (c) 2016, Jordi Corbilla
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are met:
  //
  // - Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  // - Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation
  // and/or other materials provided with the distribution.
  // - Neither the name of this library nor the names of its contributors may be
  // used to endorse or promote products derived from this software without
  // specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  // POSSIBILITY OF SUCH DAMAGE.
   
  function TKinveyRest.GetCollection: string;
  var
  IdHTTP: TIdHTTP;
  IdIOHandler: TIdSSLIOHandlerSocketOpenSSL;
  response : string;
  encodedHeader : string;
  begin
  try
  IdIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  IdIOHandler.ReadTimeout := IdTimeoutInfinite;
  IdIOHandler.ConnectTimeout := IdTimeoutInfinite;
  IdHTTP := TIdHTTP.Create(nil);
  try
  IdHTTP.IOHandler := IdIOHandler;
  IdHTTP.Request.Connection := 'Keep-Alive';
  IdIOHandler.SSLOptions.Method := sslvSSLv23;
  IdHTTP.Request.CustomHeaders.Clear;
  encodedHeader := TIdEncoderMIME.EncodeString(FOptions.AppId + ':' + FOptions.MasterSecret);
  IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Basic ' + encodedHeader;
  IdHTTP.Request.CustomHeaders.Values['X-Kinvey-API-Version'] := '3';
  IdHTTP.Request.ContentType := 'application/json';
  response := IdHTTP.Get('https://baas.kinvey.com/appdata/'+FOptions.AppId+'/'+FOptions.Collection+'/');
  result := response;
  finally
  IdHTTP.Free;
  end;
  finally
  IdIOHandler.Free;
  end;
  end;
view rawKinveyLoad.pas hosted with ❤ by GitHub

As you can see, each method uses a POST/GET command to baas.kinvey url with some arguments, headers and options. I find this way really useful as you can clearly see what's going on and easily map what you could do via curl:

  #Example posting to Kinvey via curl
  >curl -H 'Content-Type: application/json' --user APPKEY:MASTERSECRET -X PUT -d '{"user":"user","password":"password","url","www.google.co.uk"}' https://baas.kinvey.com/appdata/APPKEY/Websites
   
  #Example reading the content of the collection
  >curl --user APPKEY:MASTERSECRET -X GET https://baas.kinvey.com/appdata/APPKEY/Websites/ -G --data-urlencode 'order={"user"}'
view rawKinveyCurlExample.cmd hosted with ❤ by GitHub

If you want to run this example successfully you'll need to include libeay32.dll and ssleay32.dll from OpenSSL.

You can test this app and its mobile companion app using the source codehere.

Using Kinvey Provider component
Delphi 10.1 Berlin has a KinveyProvider component that we can use directly without having to worry about the request details. You'll see below that to do the same as the code sample above we will need just few lines of code:

 
BaaS with Kinvey and Delphi 10.1 Berlin

The KinveyProvider needs the parameters:

  • AppKey
  • AppSecret
  • MasterSecret

Get those from the Kinvey dashboard and off you go.

Then connect the BackEndStorage component to the KinveyProvider component.

Now, here is the code to Add items to the collection and to load the collection via components:
Load Data:

  // Copyright (c) 2016, Jordi Corbilla
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are met:
  //
  // - Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  // - Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation
  // and/or other materials provided with the distribution.
  // - Neither the name of this library nor the names of its contributors may be
  // used to endorse or promote products derived from this software without
  // specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  // POSSIBILITY OF SUCH DAMAGE.
   
  function TForm2.GetCollection() : TList<TUrls>;
  var
  list: TList<TUrls>;
  url: TUrls;
  begin
  try
  FBackendList := CreateUrlsList(BackendStorage1.Provider.ProviderID, BackendStorage1.Storage);
  list := TList<TUrls>.Create;
  try
  for url in FBackendList do
  list.Add(url);
  except
  list.Free;
  raise;
  end;
  finally
  result := list;
  end;
  end;
   
  function TForm2.CreateUrlsList(const AProviderID: string; const AStorage: TBackendStorageApi): TBackendObjectList<TUrls>;
  var
  LQuery: TArray<string>;
  LContactList: TBackendObjectList<TUrls>;
  begin
  LContactList := TBackendObjectList<TUrls>.Create;
  try
  LQuery := TArray<string>.Create(Format('order=%s', ['user']));
  AStorage.QueryObjects<TUrls>('websites', LQuery, LContactList);
  except
  LContactList.Free;
  raise;
  end;
  Result := LContactList;
  end;

Add Item:

  // Copyright (c) 2016, Jordi Corbilla
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are met:
  //
  // - Redistributions of source code must retain the above copyright notice,
  // this list of conditions and the following disclaimer.
  // - Redistributions in binary form must reproduce the above copyright notice,
  // this list of conditions and the following disclaimer in the documentation
  // and/or other materials provided with the distribution.
  // - Neither the name of this library nor the names of its contributors may be
  // used to endorse or promote products derived from this software without
  // specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  // POSSIBILITY OF SUCH DAMAGE.
   
  procedure TForm2.btnAddClick(Sender: TObject);
  var
  url : TUrls;
  entity: TBackendEntityValue;
  begin
  url := TURls.Create(edit1.Text, edit2.Text, edit3.Text);
  BackendStorage1.Storage.CreateObject<TUrls>('websites', url, entity);
  end;
view rawKinveyComponentAdd.pas hosted with ❤ by GitHub

As you can see now it's way simpler.

And here my android app up and running:

BaaS with Kinvey and Delphi 10.1 Berlin

Now I have a Win64 app and an Android app that share the same back end usingKinvey BaaS.

And the data in Kinvey:

BaaS with Kinvey and Delphi 10.1 Berlin

Although this article it's quite long I'm sure you will find it quite interesting if you still haven't played with these components and the cloud.

Note that this BackEnd service will cease to exist shortly (as the appkey is hardcoded in the android app and the source code is available).

Do not hesitate to contact me if you have any questions.

http://www.delphifeeds.com/go/s/134494

BaaS with Kinvey and Delphi 10.1 Berlin的更多相关文章

  1. Delphi 10&period;1 Berlin UTF8String Test

    Delphi 10.1 Berlin UTF8String Test procedure TForm1.Button1Click(Sender: TObject); var s: UTF8String ...

  2. Delphi 10&period;1 Berlin 官方未列之修正

    Delphi 10.1 Berlin 官方修正列表: Bug fix list for RAD Studio 10.1 Berlin Delphi 10.1 Berlin 官方未列之修正: 修正 iO ...

  3. delphi 10&period;1 berlin最新的开发框架:咏南中间件&plus;咏南开发框架,购买后提供全部的源码

    咏南中间件+咏南开发框架支持最新的delphi 10.1(berlin),老用户提供免费升级. 购买提供:中间件源码 附带福利(赠送): CS开发框架源码BS开发框架源码移动APP源码中间件集群源码二 ...

  4. Delphi 10&period;1 Berlin Starter Edition

    Delphi 10.1 Berlin Starter Edition Embarcadero® Delphi 10.1 Berlin Starter is a great way to get sta ...

  5. Where is the ActiveX Project Type for Delphi 10&period;1 Berlin

    n 10.1 Berlin the ActiveX project types are missing from the New Items Window under Delphi. They are ...

  6. delphi 10&period;1 Berlin 中使用自带的 Base64 编码

    delphi 10.1 berlin版本中,有好几个 base64 编码的单元可以使用,例如 Indy, MessageDigest_5,还有 CnBase64,我现在使用自带的 System.Net ...

  7. delphi 10&period;1 berlin datasnap提交clientdataset&period;delta报:invalid variant type conversion&lpar;类型转换错误&rpar;问题的解决

    delphi 10.1 berlin datasnap提交clientdataset.delta报:invalid variant type conversion(类型转换错误)问题的解决,需要打这个 ...

  8. TNetHttpClient支持异步访问&lpar;Delphi 10&period;1 Berlin,红鱼儿的博客&rpar;

    Delphi 10.1进一步改进自Delphi 10带来的Http访问控件TNetHttpClient,支持异步访问,同时增加ConnectionTimeout及ResponseTimeout两个超时 ...

  9. Delphi 10&period;1 Berlin 与 Delphi 10 Seattle 共存

    以下安装环境是win7 64位 1. 安装Delphi10.1 Berlin 版本. 2.修改C:\Program Files (x86)\Embarcadero\Studio\18.0\cglm.i ...

随机推荐

  1. SQL2008安装提示&quot&semi;Microsoft visual studio 2008早期之前的版本

    打开注册表管理器(运行 --regedit 依次展开如下项目:   HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DevDiv 将devdiv项目导出来保存,倒出来之后可 ...

  2. &lbrack;转&rsqb;简单识别 RESTful 接口

         本文描述了识别一个接口是否真的是 RESTful 接口的基本方法.符合 REST 架构风格的接口,称为 RESTful 接口.本文不打算从架构风格的推导方面描述,而是从 HTTP 标准的方面 ...

  3. python argparse模块解析命令行选项简单使用

    argparse模块的解析命令行选项简单使用 util.py #!/usr/bin/env python # coding=utf-8 import argparse parser = argpars ...

  4. linux环境下tcpdump源代码分析

    Linux 环境下tcpdump 源代码分析 韩大卫@吉林师范大学 tcpdump.c 是tcpdump 工具的main.c, 本文旨对tcpdump的框架有简单了解,只展示linux平台使用的一部分 ...

  5. Oracle&lowbar;where子句

    Oracle_where子句 --1.查询员工名为'SMITH'的信息 select * from emp where ename = 'SMITH';   --2.查询在1980/12/17入职的员 ...

  6. Linux显示进程状态

    Linux显示进程状态 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ top top - 19:16:36 up 45 min, 2 users, load ...

  7. final关键字总结

    参考文章[https://www.cnblogs.com/xrq730/p/4820296.html] 前言:在Java中final作为最常见的一个关键字,平常用到的地方也很多,接下来就来看看什么是f ...

  8. 雷林鹏分享:XML 验证

    XML 验证 拥有正确语法的 XML 被称为"形式良好"的 XML. 通过 DTD 验证的XML是"合法"的 XML. 形式良好的 XML 文档 "形 ...

  9. mybatis中多条件判断---choose when的用法

    <select id="getFunctionByPage" resultMap="FunctionRlt"> SELECT K.FUNCTION_ ...

  10. Mysql分区表及自动创建分区Partition

    Range分区表建表语句如下,其中分区键必须和id构成主键和唯一键 CREATE TABLE `test1` ( `id` char(32) COLLATE utf8mb4_unicode_ci NO ...