{"id":1367,"date":"2010-06-02T22:12:17","date_gmt":"2010-06-03T07:12:17","guid":{"rendered":"https:\/\/www.kellyrob99.com\/blog\/?p=1367"},"modified":"2010-06-02T22:12:17","modified_gmt":"2010-06-03T07:12:17","slug":"a-grails-app-demoing-the-stackexchange-api","status":"publish","type":"post","link":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/","title":{"rendered":"A Grails App Demoing the StackExchange API"},"content":{"rendered":"<p>So I was making an attempt to catch up on my <a class=\"zem_slink\" href=\"http:\/\/www.google.com\/reader\" title=\"Google Reader\" rel=\"homepage\">Google Reader<\/a>&#8216;ing this weekend and I came across <a href=\"http:\/\/blog.stackoverflow.com\/2010\/05\/stack-exchange-api-contest\/\">this post on StackOverflow<\/a> regarding the shiny new <a class=\"zem_slink\" href=\"http:\/\/www.stackexchange.com\" title=\"StackExchange\" rel=\"homepage\">StackExchange<\/a> <a class=\"zem_slink\" href=\"http:\/\/en.wikipedia.org\/wiki\/Application_programming_interface\" title=\"Application programming interface\" rel=\"wikipedia\">API<\/a>. That and a fresh 1.3.1 drop of <a class=\"zem_slink\" href=\"http:\/\/grails.org\" title=\"Grails (framework)\" rel=\"homepage\">Grails<\/a> seemed like as good a reason as any to hack together a little app suitable for seeing what you can do with said API.<br \/>\nTurns out it&#8217;s not a whole lot, at least not yet. The minor detraction of having  read-only access and limited connects without an API key are more than offset by seeing such a minimal, clean and easy to use interface. According to the grails stats script, it took about this much effort to implement calls to each and every one of the API endpoints for all of the supported domains:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n    +----------------------+-------+-------+\r\n    | Name                 | Files |  LOC  |\r\n    +----------------------+-------+-------+\r\n    | Controllers          |     1 |    42 | \r\n    | Groovy Helpers       |     1 |    47 | \r\n    +----------------------+-------+-------+\r\n    | Totals               |     2 |    89 | \r\n    +----------------------+-------+-------+\r\n<\/pre>\n<p>\nPlease note that this is about as minimal as you could reasonably get away with(and kinda ugly to boot), but nevertheless it does manage to implement a UI and backend for exercising the entire API in a total of 2 gsp files and 1 controller action.  What&#8217;s noticeably missing are some tailored views for each of the different <a class=\"zem_slink\" href=\"http:\/\/json.org\/\" title=\"JSON\" rel=\"homepage\">JSON<\/a> responses and the implementation of additional query parameters on the calls.<\/p>\n<p><\/p>\n<h2>StackExchange API<\/h2>\n<p>This is really <a href=\"http:\/\/api.stackoverflow.com\/0.8\/help\">pretty well documented<\/a> and &#8220;consistent&#8221;. Calls in some cases require an {id} in the url and that&#8217;s about it. Each of the individual calls has its own help page that describes the options, like the <a href=\"http:\/\/api.stackoverflow.com\/0.8\/help\/method?method=badges\">badges page<\/a> for instance. To make things a little more helpful while exploring the API, each of the implemented endpoints in this app are also hyper-linked to the corresponding manual page on api.stackoverflow.com.<\/p>\n<p><\/p>\n<h2><a class=\"zem_slink\" href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_State_Transfer\" title=\"Representational State Transfer\" rel=\"wikipedia\">RESTful<\/a> Access<\/h2>\n<p>Couldn&#8217;t be a whole lot easier than using <a href=\"http:\/\/groovy.codehaus.org\/modules\/http-builder\/\">HttpBuilder<\/a>, which provides nice and concise ways to execute the GET request, inspect the response and deal with success\/failure of the request. Aside from assigning the root domain and method using variables, this is little different from the <a href=\"http:\/\/groovy.codehaus.org\/HTTP+Builder\">canonical example on codehaus<\/a>.<\/p>\n<pre class=\"brush: groovy; title: ; notranslate\" title=\"\">\r\ndef http = new HTTPBuilder(&quot;http:\/\/api.$domain&quot;)\r\nhttp.request(GET, JSON) {\r\n    uri.path = &quot;\/${VERSION}$method&quot;\r\n    headers.'User-Agent' = 'Mozilla\/5.0 Ubuntu\/8.10 Firefox\/3.0.4'\r\n     response.success = { resp, json -&gt;\r\n        answer = json\r\n    }\r\n     response.failure = { resp -&gt;\r\n        answer = &quot;Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}&quot;\r\n    }\r\n}\r\n<\/pre>\n<p>The syntax here could probably get even Groovier using the <a href=\"http:\/\/www.grails.org\/plugin\/rest\">Grails REST client plugin<\/a> wrappers, and indeed incorporating that plugin is how the HttpBuilder dependency is being provided in this app, but I hit on a working implementation first time out so we&#8217;ll leave that for another day, shall we?<\/p>\n<p><\/p>\n<h2>What&#8217;s it Look Like?<\/h2>\n<p><img data-recalc-dims=\"1\" src=\"https:\/\/i0.wp.com\/www.kellyrob99.com\/blog\/wp-content\/gallery\/stackoverflow-api-grails\/stackapps-demo_1275451039026.png?resize=860%2C480&#038;ssl=1\" alt='stackapps-demo' class='ngg-singlepic ngg-none'  width=\"860\" height=\"480\"\/><br \/>\nDid I mention it was ugly?  Where the API call requires a parameter, you get a text field. Each domain gets its own submit button, officially representing my first attempted usage of g:actionSubmit in Grails. Doesn&#8217;t work quite the way I expected, but it does certainly work. Click a button and you&#8217;re shown the raw JSON result, along with the call you made. In an ugly fashion, or did I say that already? Still, for a couple of hours of hacking, I&#8217;m not unhappy with the result.<\/p>\n<p><\/p>\n<h2>StackApps<\/h2>\n<p>This is where the apps in the contest get shown off and, in a wonderful display of <a href=\"http:\/\/en.wikipedia.org\/wiki\/Eating_your_own_dog_food\">dogfooding<\/a>, it&#8217;s guess what &#8211; another StackOverflow clone! The page for this application <a href=\"http:\/\/stackapps.com\/questions\/491\/a-grails-app-demoing-the-stackexchange-api\">can be found here<\/a>. And the <a href=\"http:\/\/github.com\/kellyrob99\/stackoverflow-api-grails\">source code is up on github<\/a> if you&#8217;d like to take a look.<\/p>\n<p><\/p>\n<h2>Next Steps?<\/h2>\n<p>Toying with the idea of porting this to appengine, which would unfortunately mean replacing HttpBuilder and the underlying Apache HttpClient in favor of something that didn&#8217;t use a threaded approach, most likely using <a href=\"http:\/\/code.google.com\/appengine\/docs\/java\/urlfetch\/\">URL fetch<\/a>. That and some slightly less ugly tabular and\/or tree views of the JSON responses would be kinda nice to have.<br \/>\n\ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So I was making an attempt to catch up on my Google Reader&#8216;ing this weekend and I came across this post on StackOverflow regarding the shiny new StackExchange API. That and a fresh 1.3.1 drop of Grails seemed like as good a reason as any to hack together a little app suitable for seeing what [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_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":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[6],"tags":[209,81,60,128,259,257,211,138,112,205,148,210,208,206,113],"class_list":["post-1367","post","type-post","status-publish","format-standard","hentry","category-dev","tag-api","tag-application-programming-interface","tag-google","tag-google-reader","tag-grails","tag-groovy","tag-http","tag-json","tag-kellyrob99","tag-representational-state-transfer","tag-source-code","tag-stack-overflow","tag-stackapps","tag-stackexchange","tag-thekaptain"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"A quick and dirty demo of the StackExchange API using a minimal Grails application.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"TheKaptain\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"The Kaptain on ... stuff | Tales of development, life and the folly that goes along with both\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"A Grails App Demoing the StackExchange API | The Kaptain on ... stuff\" \/>\n\t\t<meta property=\"og:description\" content=\"A quick and dirty demo of the StackExchange API using a minimal Grails application.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2010-06-03T07:12:17+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2010-06-03T07:12:17+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"A Grails App Demoing the StackExchange API | The Kaptain on ... stuff\" \/>\n\t\t<meta name=\"twitter:description\" content=\"A quick and dirty demo of the StackExchange API using a minimal Grails application.\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/#article\",\"name\":\"A Grails App Demoing the StackExchange API | The Kaptain on ... stuff\",\"headline\":\"A Grails App Demoing the StackExchange API\",\"author\":{\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/author\\\/admin\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/#organization\"},\"datePublished\":\"2010-06-02T22:12:17-09:00\",\"dateModified\":\"2010-06-02T22:12:17-09:00\",\"inLanguage\":\"en-US\",\"commentCount\":3,\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/#webpage\"},\"articleSection\":\"Development, API, Application programming interface, Google, Google Reader, Grails, Groovy, HTTP, JSON, kellyrob99, Representational State Transfer, Source code, Stack Overflow, StackApps, StackExchange, theKaptain\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/category\\\/dev\\\/#listItem\",\"name\":\"Development\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/category\\\/dev\\\/#listItem\",\"position\":2,\"name\":\"Development\",\"item\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/category\\\/dev\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/#listItem\",\"name\":\"A Grails App Demoing the StackExchange API\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/#listItem\",\"position\":3,\"name\":\"A Grails App Demoing the StackExchange API\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/category\\\/dev\\\/#listItem\",\"name\":\"Development\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/#organization\",\"name\":\"The Kaptain on ... stuff\",\"description\":\"Tales of development, life and the folly that goes along with both\",\"url\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/author\\\/admin\\\/#author\",\"url\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/author\\\/admin\\\/\",\"name\":\"TheKaptain\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e41f09f3548f065fe6967ac904d3ea2a638614c16d879cac47cfad64e5b1426a?s=96&d=monsterid&r=g\",\"width\":96,\"height\":96,\"caption\":\"TheKaptain\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/#webpage\",\"url\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/\",\"name\":\"A Grails App Demoing the StackExchange API | The Kaptain on ... stuff\",\"description\":\"A quick and dirty demo of the StackExchange API using a minimal Grails application.\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/2010\\\/06\\\/02\\\/a-grails-app-demoing-the-stackexchange-api\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/author\\\/admin\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/author\\\/admin\\\/#author\"},\"datePublished\":\"2010-06-02T22:12:17-09:00\",\"dateModified\":\"2010-06-02T22:12:17-09:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/\",\"name\":\"The Kaptain on ... stuff\",\"description\":\"Tales of development, life and the folly that goes along with both\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.kellyrob99.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"A Grails App Demoing the StackExchange API | The Kaptain on ... stuff","description":"A quick and dirty demo of the StackExchange API using a minimal Grails application.","canonical_url":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/#article","name":"A Grails App Demoing the StackExchange API | The Kaptain on ... stuff","headline":"A Grails App Demoing the StackExchange API","author":{"@id":"https:\/\/www.kellyrob99.com\/blog\/author\/admin\/#author"},"publisher":{"@id":"https:\/\/www.kellyrob99.com\/blog\/#organization"},"datePublished":"2010-06-02T22:12:17-09:00","dateModified":"2010-06-02T22:12:17-09:00","inLanguage":"en-US","commentCount":3,"mainEntityOfPage":{"@id":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/#webpage"},"isPartOf":{"@id":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/#webpage"},"articleSection":"Development, API, Application programming interface, Google, Google Reader, Grails, Groovy, HTTP, JSON, kellyrob99, Representational State Transfer, Source code, Stack Overflow, StackApps, StackExchange, theKaptain"},{"@type":"BreadcrumbList","@id":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.kellyrob99.com\/blog#listItem","position":1,"name":"Home","item":"https:\/\/www.kellyrob99.com\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kellyrob99.com\/blog\/category\/dev\/#listItem","name":"Development"}},{"@type":"ListItem","@id":"https:\/\/www.kellyrob99.com\/blog\/category\/dev\/#listItem","position":2,"name":"Development","item":"https:\/\/www.kellyrob99.com\/blog\/category\/dev\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/#listItem","name":"A Grails App Demoing the StackExchange API"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.kellyrob99.com\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/#listItem","position":3,"name":"A Grails App Demoing the StackExchange API","previousItem":{"@type":"ListItem","@id":"https:\/\/www.kellyrob99.com\/blog\/category\/dev\/#listItem","name":"Development"}}]},{"@type":"Organization","@id":"https:\/\/www.kellyrob99.com\/blog\/#organization","name":"The Kaptain on ... stuff","description":"Tales of development, life and the folly that goes along with both","url":"https:\/\/www.kellyrob99.com\/blog\/"},{"@type":"Person","@id":"https:\/\/www.kellyrob99.com\/blog\/author\/admin\/#author","url":"https:\/\/www.kellyrob99.com\/blog\/author\/admin\/","name":"TheKaptain","image":{"@type":"ImageObject","@id":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/e41f09f3548f065fe6967ac904d3ea2a638614c16d879cac47cfad64e5b1426a?s=96&d=monsterid&r=g","width":96,"height":96,"caption":"TheKaptain"}},{"@type":"WebPage","@id":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/#webpage","url":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/","name":"A Grails App Demoing the StackExchange API | The Kaptain on ... stuff","description":"A quick and dirty demo of the StackExchange API using a minimal Grails application.","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/www.kellyrob99.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/#breadcrumblist"},"author":{"@id":"https:\/\/www.kellyrob99.com\/blog\/author\/admin\/#author"},"creator":{"@id":"https:\/\/www.kellyrob99.com\/blog\/author\/admin\/#author"},"datePublished":"2010-06-02T22:12:17-09:00","dateModified":"2010-06-02T22:12:17-09:00"},{"@type":"WebSite","@id":"https:\/\/www.kellyrob99.com\/blog\/#website","url":"https:\/\/www.kellyrob99.com\/blog\/","name":"The Kaptain on ... stuff","description":"Tales of development, life and the folly that goes along with both","inLanguage":"en-US","publisher":{"@id":"https:\/\/www.kellyrob99.com\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"The Kaptain on ... stuff | Tales of development, life and the folly that goes along with both","og:type":"article","og:title":"A Grails App Demoing the StackExchange API | The Kaptain on ... stuff","og:description":"A quick and dirty demo of the StackExchange API using a minimal Grails application.","og:url":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/","article:published_time":"2010-06-03T07:12:17+00:00","article:modified_time":"2010-06-03T07:12:17+00:00","twitter:card":"summary","twitter:title":"A Grails App Demoing the StackExchange API | The Kaptain on ... stuff","twitter:description":"A quick and dirty demo of the StackExchange API using a minimal Grails application."},"aioseo_meta_data":{"post_id":"1367","title":"A Grails App Demoing the StackExchange API | #site_title","description":"A quick and dirty demo of the StackExchange API using a minimal Grails application.","keywords":[{"label":"REST","value":"REST"},{"label":"Representational State Transfer","value":"Representational State Transfer"},{"label":"Google Reader","value":"Google Reader"},{"label":"Application programming interface","value":"Application programming interface"},{"label":"StackExchange","value":"StackExchange"},{"label":"JSON","value":"JSON"},{"label":"Hypertext Transfer Protocol","value":"Hypertext Transfer Protocol"},{"label":"Google","value":"Google"},{"label":"Grails","value":"Grails"},{"label":"Groovy","value":"Groovy"},{"label":"StackApps","value":"StackApps"},{"label":"API","value":"API"},{"label":"TheKaptain","value":"TheKaptain"},{"label":"kellyrob99","value":"kellyrob99"},{"label":"source code","value":"source code"}],"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[],"defaultGraph":"","defaultPostTypeGraph":""},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2021-02-09 05:15:21","updated":"2025-11-29 20:27:59","seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kellyrob99.com\/blog\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kellyrob99.com\/blog\/category\/dev\/\" title=\"Development\">Development<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tA Grails App Demoing the StackExchange API\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.kellyrob99.com\/blog"},{"label":"Development","link":"https:\/\/www.kellyrob99.com\/blog\/category\/dev\/"},{"label":"A Grails App Demoing the StackExchange API","link":"https:\/\/www.kellyrob99.com\/blog\/2010\/06\/02\/a-grails-app-demoing-the-stackexchange-api\/"}],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/prjtg-m3","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/posts\/1367","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/comments?post=1367"}],"version-history":[{"count":52,"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/posts\/1367\/revisions"}],"predecessor-version":[{"id":1419,"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/posts\/1367\/revisions\/1419"}],"wp:attachment":[{"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/media?parent=1367"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/categories?post=1367"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kellyrob99.com\/blog\/wp-json\/wp\/v2\/tags?post=1367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}