{"id":2479,"date":"2016-12-07T21:43:08","date_gmt":"2016-12-07T09:43:08","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=2479"},"modified":"2016-12-08T07:09:04","modified_gmt":"2016-12-07T19:09:04","slug":"using-retrofit-with-oxygene","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/2479\/","title":{"rendered":"Using Retrofit with Oxygene"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">5<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>I&#8217;ve recently been working on a new project involving an Azure hosted ASP.NET MVC WebApi application (actually a pair of them) and native mobile and web applications.  Everything is &#8211; of course &#8211; built using <strong>Oxygene<\/strong>.  For the <strong>Android<\/strong> mobile app I was looking for a REST API client library and have settled upon <strong><a href=\"https:\/\/square.github.io\/retrofit\/\">Retrofit<\/a><\/strong> and thought I would share the experience.<\/p>\n<p><!--more--><\/p>\n<p>Retrofit is a Java library that generates REST API Clients dynamically.  It doesn&#8217;t create swathes of code to be compiled into your app, but generates client classes at runtime.  The classes produced implement interfaces which both describe the REST API service they access and also then provide the client API for consumption by the client application.<\/p>\n<p>Perhaps the easiest way to explain is with an example.<\/p>\n<h2> Creating and Configuring a Retrofit <\/h2>\n<p>First of all, we need an instance of <strong>Retrofit<\/strong> for use in the application.<\/p>\n<p><strong>Retrofit<\/strong> uses a fluent builder pattern so to get one we new up a builder and use that to configure and ultimately build the <strong>Retrofit<\/strong> object itself:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n    var retrofit := (new Retrofit.Builder)\r\n        .baseUrl('http:\/\/myauthservice.azurewebsites.net')\r\n        .addConverterFactory(GsonConverterFactory.create(gson))\r\n        .client(httpClient)\r\n        .build;\r\n<\/pre>\n<p>To configure the <strong>Retrofit<\/strong> object we use the builder to specify a base url from which all our API endpoints extend.  Since my REST services communicate using JSON, I am also specifying the use of <strong>GsonConverter<\/strong> to manage the mapping of response and request objects between JSON and POJO&#8217;s (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Plain_Old_Java_Object\">Plain Ol&#8217; Java Objects<\/a>).<\/p>\n<p>Of course, as we shall see, those <strong>POJO<\/strong>&#8216;s in the world of <strong>Oxygene<\/strong> are <strong>POPO<\/strong>&#8216;s: Plain Ol&#8217; <em>Pascal<\/em> Objects (it&#8217;s OK, the Java world they inhabit &#8211; in this case &#8211; will never know).<\/p>\n<p>Eventually these POPO&#8217;s will be shared between all of the client applications (Android, iOS as well as .NET, macOS and possibly Win32\/Linux clients).<\/p>\n<p><strong>GsonConverter<\/strong> is a <strong>Retrofit<\/strong> plugin based in turn on the <a href=\"https:\/\/github.com\/google\/gson\">Google Gson library<\/a>.  The <strong>GsonConverterFactory<\/strong> takes a <strong>Gson<\/strong> configuration which is also initialised using a fluent builder pattern.<\/p>\n<p>Before showing that, I&#8217;ll also mention that <strong>Retrofit<\/strong> can employ pluggable HTTP client libraries.  I am using <a href=\"http:\/\/square.github.io\/okhttp\/\">OkHttpClient<\/a>, from the same developers as <strong>Retrofit<\/strong> itself.  This too uses a fluent builder.<\/p>\n<p>So let&#8217;s see the complete initialization required for <strong>Retrofit<\/strong>:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n    var gson := (new GsonBuilder)\r\n        .setLenient\r\n        .create;\r\n\r\n    var httpClient := (new OkHttpClient.Builder)\r\n        .connectTimeout(240, TimeUnit.SECONDS)\r\n        .readTimeout(240, TimeUnit.SECONDS)\r\n        .build;\r\n\r\n    var retrofit := (new Retrofit.Builder)\r\n        .baseUrl('http:\/\/myauthservice.azurewebsites.net')\r\n        .addConverterFactory(GsonConverterFactory.create(gson))\r\n        .client(httpClient)\r\n        .build;\r\n<\/pre>\n<p>The <strong>setLenient()<\/strong> configuration on <strong>Gson<\/strong> makes sure that deserialization of JSON is not adversely affected by JSON which is not &#8216;strictly&#8217; compliant, although <a href=\"https:\/\/futurestud.io\/tutorials\/gson-builder-relax-gson-with-lenient\">only certain deviations are accepted<\/a>.<\/p>\n<p>Leniency is required, for example, if you have REST API methods which return simple JSON values.  i.e. uncontained (that is, not part of any object or array) strings, integers etc.<\/p>\n<p>The only configuration required on the <strong>OkHttpClient<\/strong> was to increase the timeouts.  The timeouts required are pretty extreme at the moment &#8211; my fledgling Azure services are currently hosted in the 100% free performance tiers currently and performance is &#8230; what you&#8217;d expect for nothing.<\/p>\n<h2> A REST API ?  Well, well, I Do Declare <\/h2>\n<p>As mentioned above, <strong>Retrofit<\/strong> needs an interface that describes the REST API you wish to access.  I&#8217;ll show a simple interface providing just one of my API methods, for logging in with <a href=\"http:\/\/oauthlib.readthedocs.io\/en\/latest\/oauth2\/grants\/password.html\">OAuth resource owner password<\/a> flow.<\/p>\n<p>Here&#8217;s the interface:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n    AuthTokenApi = public interface\r\n      [POST('\/api\/token')]\r\n      [Headers('Accept: application\/json')]\r\n      [FormUrlEncoded]\r\n      method loginWithPassword([Field('grant_type')] grant: String; \r\n                               [Field('username')] username: String; \r\n                               [Field('password')] password: String; \r\n                               [Field('client_id')] client_id: String; \r\n                               [Field('client_secret')] client_secret: String): Call&lt;TokenResponse&gt;;\r\n    end;\r\n<\/pre>\n<p>Retrofit reflects on the annotations (like attributes in .NET and syntactically identical in Oxygene) in the interface to determine the implementation required to satisfy that interface.  There can of course be multiple methods in the interface.  I am using only one here for simplicity.<\/p>\n<p>First are the annotations on the methods of the interface.  These identify the HTTP method involved and the URL to be appended to the base URL of the <strong>Retrofit<\/strong> which is used to eventually generate the client.<\/p>\n<p>Method annotations can also specify headers to be included in any request and the manner in which any request content is to be supplied.  In this case <strong>FormUrlEncoded<\/strong> (application\/x-www-form-urlencoded).<\/p>\n<p>In the case of an encoded form request, annotations on the method parameters identify the names of the values to be provided in the request body.<\/p>\n<p>Finally, a <strong>Retrofit<\/strong> REST client API method returns a generic <strong>Call&lt;T&gt;<\/strong> result.  The type <strong>T<\/strong> indicates the type of the result value.  This can be a simple type (string, integer etc) or &#8211; as in this case &#8211; a class type (i.e. a POJO).<\/p>\n<p>Here&#8217;s my POJO class for that result:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n    TokenResponse = public class\r\n    public\r\n      access_token: String;\r\n      refresh_token: String;\r\n      token_type: String;\r\n      expires_in: Integer;\r\n      username: String;\r\n\r\n      [SerializedName('as:client_id')]\r\n      client_id: String;\r\n\r\n      [SerializedName('.issued')]\r\n      issuedUTC: String;\r\n\r\n      [SerializedName('.expires')]\r\n      expiresUTC: String;\r\n    end;\r\n<\/pre>\n<p><strong>Gson<\/strong> mapping of JSON values to members is by name, but if the names involved do not map directly we can use annotation to provide the serialized name for specific members.  In this case, this is required for three members since the JSON names involved are not legal member identifiers.<\/p>\n<h2> Pulling It All Together: Making the Call <\/h2>\n<p>To call the REST API, we use the <strong>Retrofit<\/strong> object we configured to create a class instance providing an implementation of our REST API interface.<\/p>\n<p>We also provide implementations of response and failure handlers for an interface corresponding to a <strong>CallBack&lt;T&gt;<\/strong> for the expected <strong>T<\/strong> return type.  With one slight change to the previous initialization code, to employ a member variable to hold the <strong>Retrofit<\/strong> we configure in our activity, here&#8217;s a very basic login activity:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n  type\r\n    LoginActivity = public class(Activity, Callback&lt;TokenResponse&gt;)\r\n    private\r\n      _retrofit: Retrofit;\r\n    public\r\n      method onCreate(savedInstanceState: Bundle); override;\r\n      begin\r\n        inherited;\r\n\r\n        ContentView := R.layout.login;\r\n\r\n        var gson := (new GsonBuilder)\r\n            .setLenient\r\n            .create;\r\n\r\n        var httpClient := (new OkHttpClient.Builder)\r\n            .connectTimeout(240, TimeUnit.SECONDS)\r\n            .readTimeout(240, TimeUnit.SECONDS)\r\n            .build;\r\n\r\n        _retrofit := (new Retrofit.Builder)\r\n            .baseUrl('http:\/\/myauthservice.azurewebsites.net')\r\n            .addConverterFactory(GsonConverterFactory.create(gson))\r\n            .client(httpClient)\r\n            .build;\r\n      end;\r\n\r\n      method onLoginClick(view: View);\r\n      method onResponse(request: Call&lt;TokenResponse&gt;; response: Response&lt;TokenResponse&gt;);\r\n      method onFailure(request: Call&lt;TokenResponse&gt;; error: Throwable);\r\n    end;\r\n\r\n\r\nimplementation\r\n\r\n  method LoginActivity.onLoginClick(view: View);\r\n  begin\r\n    var tokenApi: AuthTokenApi := _retrofit.create(typeOf(AuthTokenApi));\r\n\r\n    var request := tokenApi.loginWithPassword('password',   \/\/ The grant type\r\n                                              'someusername',\r\n                                              'supersecretpassword',\r\n                                              'org.myorg.myapp',\r\n                                              'myapp.client.secret.goes.here');\r\n\r\n    request.enqueue(self);\r\n  end;\r\n\r\n\r\n\r\n  method LoginActivity.onResponse(request: Call&lt;TokenResponse&gt;; response: Response&lt;TokenResponse&gt;);\r\n  begin\r\n    if response.code = 200 then\r\n    begin\r\n      \/\/ Successfully logged in.  We can access the response POJO directly, \r\n      \/\/  via the body of the response. e.g:\r\n      \/\/\r\n      \/\/  var token := response.body.access_token;\r\n    end\r\n    else\r\n    begin\r\n      \/\/ Login failed - 401 response etc...\r\n    end;\r\n  end;\r\n\r\n  \r\n  method LoginActivity.onFailure(request: Call&lt;TokenResponse&gt;; error: Throwable);\r\n  begin\r\n    \/\/ Request failed entirely (e.g. network error)\r\n  end;\r\n<\/pre>\n<p>For now let&#8217;s look at the <strong>onLoginClick<\/strong> method which actually makes the request to the REST server.<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n    var tokenApi: AuthTokenApi := _retrofit.create(typeOf(AuthTokenApi));\r\n\r\n    var request := tokenApi.loginWithPassword('password',   \/\/ The grant type\r\n                                              'someusername',\r\n                                              'supersecretpassword',\r\n                                              'org.myorg.myapp',\r\n                                              'myapp.client.secret.goes.here');\r\n\r\n    request.enqueue(self);\r\n<\/pre>\n<p>Now let&#8217;s break things down a little:<\/p>\n<p>To get an object we can use to call the server, we pass the required interface to the <strong>Retrofit.create<\/strong> method.<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n    var tokenApi: AuthTokenApi := _retrofit.create(typeOf(AuthTokenApi));\r\n<\/pre>\n<p>This returns a reference to a class now <em>implementing<\/em> that interface.  With that object we can <em>obtain<\/em> (not <em>make<\/em>) a call to a specific method:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n    var request := tokenApi.loginWithPassword('password',   \/\/ The grant type\r\n                                              'someusername',\r\n                                              'supersecretpassword',\r\n                                              'org.myorg.myapp',\r\n                                              'myapp.client.secret.goes.here');\r\n<\/pre>\n<p>To repeat:  This does <strong>not<\/strong> <em>call<\/em> the server.  This method returns a <strong>Call&lt;TokenResponse&gt;<\/strong> object.  Once we have that we can use it (once!) to either <strong>execute<\/strong> a call (synchronously) or &#8211; as in this case &#8211; <strong>enqueue<\/strong> an async call, with a reference to a context to handle the response.<\/p>\n<p>With an async call, <strong>Retrofit<\/strong> takes care of making all network related calls in a background thread.  The response (or failure) handling is then performed in the <em>main<\/em> thread so that the handlers can update the UI if\/as required.<\/p>\n<p>And that&#8217;s it.<\/p>\n<p>I&#8217;ll follow this up with a closer look at the response and failure handling, in particular the failure handler, to demonstrate how to handle response content that may vary from that declared in the interface.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">5<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> I&#8217;ve recently been working on a new project involving an Azure hosted ASP.NET MVC WebApi application (actually a pair of them) and native mobile and web applications. Everything is &#8211; of course &#8211; built using Oxygene. For the Android mobile app I was looking for a REST API client library and have settled upon Retrofit [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[212,205,4,180],"tags":[153,310,260,181,309,308],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-DZ","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":2498,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2498\/","url_meta":{"origin":2479,"position":0},"title":"Retrofit &#8211; Handling Different Responses","date":"09 Dec 2016","format":false,"excerpt":"In my previous post I provided a simple example of how to use Retrofit to define, create and use a REST API client. Even in that simple example the issue of how to deal with different responses to a request came up. That is, where the response we receive does\u2026","rel":"","context":"In &quot;Cooper&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2511,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2511\/","url_meta":{"origin":2479,"position":1},"title":"Anonymous Classes: Implementing Interfaces","date":"11 Feb 2017","format":false,"excerpt":"A few years ago (2011 to be precise) someone asked a question on StackOverflow about support for anonymous classes in Delphi. The reason for the question was that the poster was trying to use Delphi to develop for Android and on that platform the widespread use of callback interfaces makes\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2523,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2523\/","url_meta":{"origin":2479,"position":2},"title":"Anonymous Classes: Anonymous POCO&#8217;s","date":"14 Feb 2017","format":false,"excerpt":"There is another use case for anonymous classes, even simpler than that of providing implementations of interfaces: Anonymous POCO's. We're all familiar with the idea of declaring a class that identifies the members that all instances (objects) of that class have, and then creating instances of that class. Anonymous classes,\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/code-completion-java.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2252,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2252\/","url_meta":{"origin":2479,"position":3},"title":"Making a Noise About on a Thread","date":"13 Aug 2014","format":false,"excerpt":"I'm working on an Android app at the moment, and for a bit of fun I decided to add a startup sound to brighten the day of every user that launches it. Which gives me another opportunity to present some of the advanced language features in Oxygene that make threading\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Audio-Resource.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2202,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/2202\/","url_meta":{"origin":2479,"position":4},"title":"What is Hydrogene ?  Asked and Answered","date":"03 Dec 2013","format":false,"excerpt":"Over the past few weeks there has been some speculation as to what the mysterious \"Hydrogene\" that RemObjects have been working on may or may not be. Well, that particular feline has slipped it's captors and escaped the bag. I'm not aware of any official announcement and I hope that\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1503,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1503\/","url_meta":{"origin":2479,"position":5},"title":"Sharing Code Across Platforms in Oxygene","date":"22 Aug 2013","format":false,"excerpt":"There seems to be a perception among some people that Delphi is in the unique position of allowing developers to share and re-use code across the various platforms that it's compiler can now (and will soon) target. But this is not the case. Oxygene has had this capability right from\u2026","rel":"","context":"In &quot;Cooper&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2479"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=2479"}],"version-history":[{"count":3,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2479\/revisions"}],"predecessor-version":[{"id":2497,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2479\/revisions\/2497"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=2479"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=2479"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=2479"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}