{"id":2498,"date":"2016-12-09T10:22:20","date_gmt":"2016-12-08T22:22:20","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=2498"},"modified":"2016-12-09T11:14:06","modified_gmt":"2016-12-08T23:14:06","slug":"retrofit-handling-different-responses","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/2498\/","title":{"rendered":"Retrofit &#8211; Handling Different Responses"},"content":{"rendered":"<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\"> 3<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>In my <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/2479\">previous post<\/a> I provided a simple example of how to use <a href=\"https:\/\/square.github.io\/retrofit\/\">Retrofit<\/a> 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 not conform to the strongly typed response we expected (or hoped for).  Here&#8217;s how we deal with that, in a strongly typed way.<\/p>\n<p><!--more--><\/p>\n<p>You may recall from my <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/2479\">previous post<\/a> that we defined a POPO type for the &#8220;happy&#8221; response to a request to the token end-point for logging in with the resource owner password flow.<\/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      &#x5B;SerializedName('as:client_id')]\r\n      client_id: String;\r\n\r\n      &#x5B;SerializedName('.issued')]\r\n      issuedUTC: String;\r\n\r\n      &#x5B;SerializedName('.expires')]\r\n      expiresUTC: String;\r\n    end;\r\n\r\n<\/pre>\n<p>This POPO represents the response to a successful login.<\/p>\n<p>In the handler for our response, we could access the response body in a strongly typed fashion using exactly this POPO class:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\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      \/\/ response.body is a TokenResponse.  i.e. an instance of the POPO we expected\r\n\r\n      var greeting := &quot;Hello &quot; + response.body.username;\r\n    end \r\n    else\r\n    ...\r\n  end;\r\n\r\n<\/pre>\n<p>But what if our request was unsuccessful ?  By which I mean we provided an invalid username or password or an incorrect client id or secret etc ?<\/p>\n<p>My back-end is an ASP.NET MVC WebApi in which I have implemented an OAuth 2.0 token provider.  A response to an invalid request is made by simply setting some error details on the OAuth Client Authentication context.  Here&#8217;s an excerpt to illustrate:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n\r\n  method AuthorizationServerProvider.GrantResourceOwnerCredentials(context: OAuthGrantResourceOwnerCredentialsContext): Task;\r\n  begin\r\n    \/\/ ... details omitted for brevity ...\r\n\r\n    if user = nil then\r\n    begin\r\n      context.SetError('invalid_grant', 'The user name or password is invalid');\r\n      exit;\r\n    end;\r\n\r\n    \/\/ ... details omitted for brevity ...\r\n  end;\r\n\r\n<\/pre>\n<p>All similar errors are set in the same way.  In the event of a request completing in an error state, the .NET Oauth implementation will produce a JSON response similar to:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\r\n   {\r\n      &quot;error&quot;: &quot;invalid_grant&quot;,\r\n      &quot;error_description&quot;: &quot;The user name or password is invalid',\r\n      &quot;error_uri&quot;: null\r\n   } \r\n\r\n<\/pre>\n<p>So, in addition to the <strong>TokenResponse<\/strong>, I need another POPO.  Let&#8217;s call it <strong>TokenErrorResponse<\/strong>:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n\r\n    TokenErrorResponse = public class\r\n    public\r\n      error: String;\r\n      error_description: String;\r\n      error_uri: String;\r\n    end;\r\n\r\n<\/pre>\n<p>So far so straightforward.  No need for any serialized name overrides.  The tricky bit comes next, although it&#8217;s not really <em>that<\/em> tricky.<\/p>\n<p>In the <strong>onResponse<\/strong> handler for the request, the <em>declared<\/em> response type (<strong>TokenResponse<\/strong>) is automatically represented on the response <strong>body<\/strong> property, in the case of a successful request.  But for <em>unsuccessful<\/em> requests we have not told the <strong>Retrofit<\/strong> what to expect (if anything).<\/p>\n<p>In that event <strong>Retrofit<\/strong> still provides access to any response body it may have received, and we access it in that case via the <strong>errorBody<\/strong> property of the response object in our handler.<\/p>\n<p>In the case of this particular client method, we know that the response will be one of those JSON error objects so we can get that in the form of a string:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\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      \/\/ ..\r\n    end \r\n    else\r\n    begin\r\n      var errorBody := response.errorBody.string;\r\n\r\n      \/\/ ...\r\n    end;\r\n  end;\r\n\r\n<\/pre>\n<p>In reality you probably wouldn&#8217;t simply assume that the response is a valid string and would do some additional checks before trying to work with the error body, but for the purposes of this exercise&#8230; Great!<\/p>\n<p>But now what do we do with it ?<\/p>\n<p>Simple:  We have declared a POPO to represent that error.  All we need to do is transform the JSON into an instance of that POPO, which is precisely what <strong>Gson<\/strong> is for.  All we need to do is get ourselves a suitable <strong>Gson<\/strong> instance and use it to transform the JSON string to an instance of <strong>TokenErrorResponse<\/strong> for us:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n\r\n      var errorBody := response.errorBody.string;\r\n      var gson      := (new GsonBuilder).setLenient.create;\r\n\r\n      var errorResponse := gson.fromJson(errorBody, typeOf(TokenErrorResponse));\r\n\r\n      \/\/ Now we can use the POPO to work with the error response\r\n\r\n      var message := &quot;Error: &quot; + errorResponse.error_description;\r\n\r\n<\/pre>\n<p>Similar techniques would obviously also work in the case of requests where even successful requests might return different responses under different circumstances.  In those cases you would implement a <strong>Retrofit<\/strong> with a method declared as returning a suitably general purpose response body type (e.g. String) and use <strong>Gson<\/strong> again as above, or some other object mapping technology as appropriate in the circumstances.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\"> 3<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span>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 not conform to the strongly [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[205,4,180],"tags":[310,181,308],"class_list":["post-2498","post","type-post","status-publish","format-standard","hentry","category-cooper","category-delphi","category-oxygene","tag-gson","tag-oxygene-2","tag-retrofit"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-Ei","jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2498","targetHints":{"allow":["GET"]}}],"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=2498"}],"version-history":[{"count":6,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2498\/revisions"}],"predecessor-version":[{"id":2504,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/2498\/revisions\/2504"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=2498"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=2498"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=2498"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}