{"id":8446,"date":"2013-02-12T13:00:54","date_gmt":"2013-02-12T11:00:54","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=8446"},"modified":"2013-02-11T22:38:55","modified_gmt":"2013-02-11T20:38:55","slug":"groovy-and-http","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html","title":{"rendered":"Groovy and HTTP"},"content":{"rendered":"<p><em>This article originally appeared in the December 2012 issue of <a onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/www.groovymag.com']);\" href=\"http:\/\/www.groovymag.com\/\">GroovyMag<\/a>.<\/em><\/p>\n<h2>Some different ways that Groovy makes interacting with the web easier<\/h2>\n<p>One of the major benefits of Groovy is how it simplifies some of the common scenarios we deal with in Java. Complex code with conditionals, error handling and many other concerns can be expressed in a very concise and easily understandable fashion. This article will touch on some convenient Groovy-isms related to interacting with content over HTTP. First we\u2019ll look at some of the syntactic sugar added to the standard Java classes that simplify GET and POST requests, and then we\u2019ll take a look at how the<br \/>\n&nbsp;<br \/>\n<a title=\"HTTPBuilder\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/groovy.codehaus.org']);\" href=\"http:\/\/groovy.codehaus.org\/modules\/http-builder\/\" target=\"_blank\">HTTPBuilder<\/a> module provides a DSL for using the <a title=\"HttpClient\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/hc.apache.org']);\" href=\"http:\/\/hc.apache.org\/httpclient-3.x\/\" target=\"_blank\">HttpClient<\/a> library.<\/p>\n<h2>The test project<\/h2>\n<p>In order to provide an environment for putting up a website and demonstrating various HTTP requests, we\u2019ll be using the Gradle Jetty plugin and some simple <a title=\"Groovlets\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/groovy.codehaus.org']);\" href=\"http:\/\/groovy.codehaus.org\/Groovlets\" target=\"_blank\">Groovlets<\/a>. The full source code is available at <a title=\"https:\/\/github.com\/kellyrob99\/groovy-http\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/github.com']);\" href=\"https:\/\/github.com\/kellyrob99\/groovy-http\" target=\"_blank\">https:\/\/github.com\/kellyrob99\/groovy-http<\/a> and I hope you\u2019ll clone a copy to take a closer look. The simple index page contains the \u2018hello world\u2019 content shown in Listing 1.<\/p>\n<pre class=\" brush:xml\">&lt;!DOCTYPE html&gt;\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n    &lt;title&gt;Groovy HTTP&lt;\/title&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n&lt;p&gt;hello world&lt;\/p&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<h4>Listing 1: Our \u2018hello world\u2019 index page used for testing<\/h4>\n<p>We\u2019ll start with the simplest available methods for interacting with HTTP using Groovy and no additional library support.<\/p>\n<h2>Groovy methods added to String and URL<\/h2>\n<p>The <a title=\"DefaultGroovyMethods\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/groovy.codehaus.org']);\" href=\"http:\/\/groovy.codehaus.org\/api\/org\/codehaus\/groovy\/runtime\/DefaultGroovyMethods.html\" target=\"_blank\">DefaultGroovyMethods<\/a> class provides a couple of very handy methods to enhance the default operation of the String and URL classes. In particular for String we have a new toURL() method and, for URL, the text property. In addition, the URL class is enhanced with convenience methods for working with associated InputStream and OutputStreams.<\/p>\n<h3>String.toURL()<\/h3>\n<p>This is a small gain as all you\u2019re really doing is avoiding a call to new <a title=\"URLConstructor\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/docs.oracle.com']);\" href=\"http:\/\/docs.oracle.com\/javase\/6\/docs\/api\/java\/net\/URL.html#URL%28java.lang.String%29\" target=\"_blank\">URL(String spec)<\/a>. The difference in keystrokes isn\u2019t large but, combined with some other MetaClass benefits of Groovy, it can be very helpful for creating fluent and easily understandable code.<\/p>\n<h3>URL.text()<\/h3>\n<p>This seemingly small addition to the API of the URL class abstracts away a lot of the usual boilerplate involved in streaming content over a <a title=\"URLConnection\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/docs.oracle.com']);\" href=\"http:\/\/docs.oracle.com\/javase\/6\/docs\/api\/java\/net\/URLConnection.html\" target=\"_blank\">URLConnection<\/a>. Underneath the hood is a very sensible implementation that buffers the underlying connection and automatically handles the closing of all resources for you. For most use cases the default behaviour is likely to be sufficient but, if not, there are overloaded URL.text(String charset) and URL.text(Map parameters, String charset) methods that allow for modification and handle more specifics of the connection configuration.<br \/>\nThe one line invocation in Listing 2 demonstrates how to load an html page, returning the raw html as a String.<\/p>\n<pre class=\" brush:java\">String html = 'http:\/\/localhost:8081\/groovy-http'.toURL().text<\/pre>\n<h4>Listing 2: One liner to initiate an HTTP GET request for an html page<\/h4>\n<p>There\u2019s still a lot that could go wrong using this shorthand syntax for an HTTP request, as several exceptions might be thrown depending on whether or not the url is correctly formatted, or if the content specified doesn\u2019t exist. The <a title=\"Spock\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/code.google.com']);\" href=\"http:\/\/code.google.com\/p\/spock\/\" target=\"_blank\">Spock<\/a> test shown in Listing 3 exercises both of these conditions. Note that a 404 response will result in a FileNotFoundException.<\/p>\n<pre class=\" brush:java\">@Unroll('The url #url should throw an exception of type #exception')\r\ndef 'exceptions can be thrown converting a String to URL and accessing the text'() {\r\n    when:\r\n    String html = url.toURL().text\r\n\r\n    then:\r\n    def e = thrown(exception)\r\n\r\n    where:\r\n    url                          | exception\r\n    'htp:\/\/foo.com'              | MalformedURLException\r\n    'http:\/\/google.com\/notThere' | FileNotFoundException\r\n}<\/pre>\n<h4>Listing 3: Spock test showing some possible failure conditions for our GET request<\/h4>\n<p>For comparison let\u2019s take a look at what the same GET request looks like using a URL in Java, shown in Listing 4.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\" brush:java\">URL html = new URL('http:\/\/localhost:8081\/groovy-http\/index.html');\r\nURLConnection urlConnection = html.openConnection();\r\nBufferedReader reader = new BufferedReader(\r\n\tnew InputStreamReader(urlConnection.getInputStream()));\r\nStringBuffer response = new StringBuffer();\r\nString inputLine;\r\nwhile ((inputLine = reader.readLine()) != null)\r\n{\r\n\tresponse.append(inputLine)\r\n}\r\nreader.close();<\/pre>\n<h4>Listing 4: The Java version of reading from a URLConnection (based on the canonical example from Oracle.com)<\/h4>\n<p>There\u2019s still no error handling in place in the Java version which is obviously a much more verbose way to load the same data.<\/p>\n<h2>POST with URL streams<\/h2>\n<p>Similarly to simplifying GET requests, executing a POST using Groovy can take advantage of some of the enhancements to common Java classes. In particular, simplified stream handling allows for tight, correct and expressive coding. Listing 5 shows a Spock test configuring the URLConnection, POSTing some data and reading back the result from the connection.<\/p>\n<pre class=\" brush:java\">private static final String POST_RESPONSE = 'Successfully posted [arg:[foo]] with method POST'    \r\n\r\ndef 'POST from a URLConnection'() {\r\n    when:\r\n    final HttpURLConnection connection = makeURL('post.groovy').toURL().openConnection()\r\n    connection.setDoOutput(true)\r\n    connection.outputStream.withWriter { Writer writer -&gt;\r\n        writer &lt;&lt; 'arg=foo'\r\n    }\r\n\r\n    String response = connection.inputStream.withReader { Reader reader -&gt; reader.text }\r\n\r\n    then:\r\n    connection.responseCode == HttpServletResponse.SC_OK\r\n    response == POST_RESPONSE\r\n}<\/pre>\n<h4>Listing 5: POST request using Groovy and a URLConnection<\/h4>\n<p>Notice that we don\u2019t have to explicitly cast the connection to <a title=\"HttpUrlConnection\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/docs.oracle.com']);\" href=\"http:\/\/docs.oracle.com\/javase\/6\/docs\/api\/java\/net\/HttpURLConnection.html\" target=\"_blank\">HttpUrlConnection<\/a> in order to get the responseCode back, and that we don\u2019t have to explicitly close any of the streams used. Also, we don\u2019t need to create local variables for the Reader\/Writer object as we would have to in Java; similarly no calls to \u2018new\u2019 are required, as Object creation is all hidden behind the convenience methods. The equivalent Java code requires four calls to new and two to close(), as well as much more involved code for extracting the result. The canonical example of how to do this in Java can be seen on <a title=\"http:\/\/docs.oracle.com\/javase\/tutorial\/networking\/urls\/readingWriting.html\" href=\"http:\/\/docs.oracle.com\/javase\/tutorial\/networking\/urls\/readingWriting.html\" target=\"_blank\">http:\/\/docs.oracle.com\/javase\/tutorial\/networking\/urls\/readingWriting.html<br \/>\n<\/a><br \/>\nNote that you can also parse response content very easily using the <a title=\"XmlSlurper\" href=\" onclick=\" target=\"_blank\">XmlSlurper<\/a> \/ <a title=\"XmlParser\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/groovy.codehaus.org']);\" href=\"http:\/\/groovy.codehaus.org\/api\/groovy\/util\/XmlParser.html\" target=\"_blank\">XmlParser<\/a> and <a title=\"JsonSlurper\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/groovy.codehaus.org']);\" href=\"http:\/\/groovy.codehaus.org\/gapi\/groovy\/json\/JsonSlurper.html\" target=\"_blank\">JsonSlurper<\/a> classes included in the standard Groovy distribution.<\/p>\n<h2>HttpClient and HTTPBuilder make things even easier<\/h2>\n<p>The reality is that in most modern Java applications developers have some nice alternatives to directly working with URL and URLConnection objects for working with HTTP. One of the more popular libraries available is HttpClient and its successor <a title=\"HttpComponents\" onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/hc.apache.org']);\" href=\"http:\/\/hc.apache.org\/\" target=\"_blank\">HttpComponents<\/a>. Wrappers for all of the HTTP verbs are provided which simplifies configuration, execution and consumption of responses. Listing 6 shows a Spock test using HttpClient and mirroring our prior GET examples.<\/p>\n<pre class=\" brush:java\">def 'HttpClient example in Java'() {\r\n    when:\r\n    HttpClient httpclient = new DefaultHttpClient();\r\n    HttpGet httpget = new HttpGet(makeURL('helloWorld.groovy'));\r\n    ResponseHandler&lt;String&gt; responseHandler = new BasicResponseHandler();\r\n    String responseBody = httpclient.execute(httpget, responseHandler);\r\n\r\n    then:\r\n    responseBody == HELLO_WORLD_HTML\r\n}<\/pre>\n<h4>Listing 6: HttpClient GET example<\/h4>\n<p>This can be further reduced if there is no need for keeping the intermediate variables around. In fact, we can get it down to the single line shown in Listing 7.<\/p>\n<pre class=\" brush:java\">String response = new DefaultHttpClient().execute(new HttpGet(makeURL('helloWorld.groovy')), new BasicResponseHandler())<\/pre>\n<h4>Listing 7: HttpClient GET one-liner<\/h4>\n<p>This is obviously a lot easier on the eyes and very clear in intent. The HttpClient library also has convenience mechanisms for declaring common behaviour across connections, an API for providing custom response parsing implementations and automatic handling for (most of) the underlying resource streams and connections. For those of us using Groovy, there\u2019s a nice wrapper for HttpClient called HTTPBuilder that adds a DSL-style configuration mechanism and some very nice features in terms of error handling and content parsing. Listing 8 shows our standard GET example again, this time working against an object called http assigned from <em>new HTTPBuilder(Object uri)<\/em>. Note that we\u2019re using Groovy\u2019s multiple assignment feature to return and assign multiple values from our Closure.<\/p>\n<pre class=\" brush:java\">def 'GET with HTTPBuilder'() {\r\n    when:\r\n    def (html, responseStatus) = http.get(path: 'helloWorld.groovy', contentType: TEXT) { resp, reader -&gt;\r\n        [reader.text, resp.status]\r\n    }\r\n\r\n    then:\r\n    responseStatus == HttpServletResponse.SC_OK\r\n    html == HELLO_WORLD_HTML\r\n}<\/pre>\n<h4>Listing 8: Spock test showing Groovy HTTPBuilder GET support<\/h4>\n<p>If you noticed in Listing 8 I explicitly set the request with <em>contentType: TEXT<\/em>, it\u2019s because HTTPBuilder by default provides automatic response content type detection and parsing. Since I\u2019m requesting an xml document, HTTPBuilder can automatically parse the result with Groovy\u2019s XmlSlurper. HTTPBuilder can also detect that it is an html page and pass the response through NekoHTML first to ensure that you\u2019re working with a well-formed document. Listing 9 shows the slight difference in how we could interact with the parsed response content and the reader in our Closure from Listing 8 is quietly replaced with a GPathResult referring to the parsed content.<\/p>\n<pre class=\" brush:java\">def 'GET with HTTPBuilder and automatic parsing'() {\r\n    when:\r\n    def (html, responseStatus) = http.get(path: 'helloWorld.groovy') { resp, reader -&gt;\r\n        [reader, resp.status]\r\n    }\r\n\r\n    then:\r\n    responseStatus == HttpServletResponse.SC_OK\r\n    html instanceof GPathResult\r\n    html.BODY.P.text() == 'hello world'\r\n}<\/pre>\n<h4>Listing 9: automatic detection and parsing of xml <\/h4>\n<p>It\u2019s unlikely that you\u2019re going to be parsing a lot of html this way but with the abundance of xml services available nowadays automated parsing can be very helpful. The same applies for JSON and if we give a hint as to the contentType we can get back a parsed JSONObject when interacting with such services as shown in Listing 10.<\/p>\n<pre class=\" brush:java\">def 'GET with HTTPBuilder and automatic JSON parsing'() {\r\n    when:\r\n    def (json, responseStatus) = http.get(path: 'indexJson.groovy', contentType: JSON) { resp, reader -&gt;\r\n        [reader, resp.status]\r\n    }\r\n\r\n    then:\r\n    responseStatus == HttpServletResponse.SC_OK\r\n    json instanceof JSONObject\r\n    json.html.body.p == 'hello world'\r\n}<\/pre>\n<h4>Listing 10: automatic parsing of JSON responses<\/h4>\n<p>The HTTPBuilder module also has some convenience methods for handling failure conditions. By allowing for specifying both default failure handlers and specific behaviour for individual requests you\u2019ve got lots of options at your disposal. Listing 11 shows how to define a default failure handler that simply traps the response code. Note that the Closure used for hading GET response is never run since in this case the page we\u2019re requesting results in an HTTP 404 Not Found response code.<\/p>\n<pre class=\" brush:java\">def 'GET with HTTPBuilder and error handling'() {\r\n    when:\r\n    int responseStatus\r\n    http.handler.failure = { resp -&gt;\r\n        responseStatus = resp.status\r\n    }\r\n    http.get(path: 'notThere.groovy', contentType: TEXT) { resp, reader -&gt;\r\n        throw new IllegalStateException('should not be executed')\r\n    }\r\n\r\n    then:\r\n    responseStatus == HttpServletResponse.SC_NOT_FOUND\r\n}<\/pre>\n<h4>Listing 11: Defining a failure handler with HTTPBuilder<\/h4>\n<p>POSTing data with HTTPBuilder is also very straightforward, requiring only an additional body parameter as shown in Listing 12.<\/p>\n<pre class=\" brush:java\">def 'POST with HTTPBuilder'() {\r\n    when:\r\n    def (response, responseStatus) = http.post(path: 'post.groovy', body: [arg: 'foo']) { resp, reader -&gt;\r\n        [reader.text(),resp.status]\r\n    }\r\n\r\n    then:\r\n    responseStatus == HttpServletResponse.SC_OK\r\n    response == POST_RESPONSE\r\n}<\/pre>\n<h4>Listing 12: POST using HTTPBuilder<\/h4>\n<p>HTTPBuilder also provides some more specific abstractions for dealing with certain scenarios. There\u2019s RESTClient for dealing with RESTful webservices in a simplified manner, there\u2019s AsyncHTTPBuilder for asynchronously executing requests and for the Google App Engine, which doesn\u2019t allow socket based connections, there\u2019s the HttpURLClient which wraps HttpUrlConnection usage.<\/p>\n<h2>Conclusion<\/h2>\n<p>Hopefully this has given you a taste for what Groovy can do to help you with HTTP interactions and gives you some ideas for making your own HTTP client applications a bit Groovier.<\/p>\n<h2>More reading<\/h2>\n<ul>\n<li><a onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/docs.oracle.com']);\" href=\"http:\/\/docs.oracle.com\/javase\/tutorial\/networking\/urls\/readingWriting.html\" target=\"_blank\">http:\/\/docs.oracle.com\/javase\/tutorial\/networking\/urls\/readingWriting.html<\/a><\/li>\n<li><a onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/docs.oracle.com']);\" href=\"http:\/\/docs.oracle.com\/javase\/tutorial\/networking\/urls\/readingWriting.html\" target=\"_blank\">http:\/\/stackoverflow.com\/questions\/2793150\/how-to-use-java-net-urlconnection-to-fire-and-handle-http-requests<\/a><\/li>\n<li>The HTTPBuilder website <a onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/groovy.codehaus.org']);\" href=\"http:\/\/groovy.codehaus.org\/modules\/http-builder\/\" target=\"_blank\">http:\/\/groovy.codehaus.org\/modules\/http-builder\/<\/a><\/li>\n<li>The HttpComponents website <a onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/hc.apache.org']);\" href=\"http:\/\/hc.apache.org\/index.html\" target=\"_blank\">http:\/\/hc.apache.org\/index.html<\/a><\/li>\n<li>The source code that goes along with this article on github at <a onclick=\"javascript:_gaq.push(['_trackEvent','outbound-article','http:\/\/github.com']);\" href=\"https:\/\/github.com\/kellyrob99\/groovy-http\" target=\"_blank\">https:\/\/github.com\/kellyrob99\/groovy-http<\/a>. This project includes the Gradle wrapper so you should be able to just clone the repository and start using it without installing any additional software(other than Java, of course). You can run all of the tests with .\/gradlew clean build and you can start the webserver with .\/gradlew jettyRun<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><strong><em>Reference: <\/em><\/strong><a href=\"http:\/\/www.kellyrob99.com\/blog\/2013\/02\/10\/groovy-and-http\/\">Groovy and HTTP<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/p\/jcg.html\">JCG partner<\/a> Kelly Robinson at the <a href=\"http:\/\/www.kellyrob99.com\/\">The Kaptain on \u2026 stuff<\/a> blog.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article originally appeared in the December 2012 issue of GroovyMag. Some different ways that Groovy makes interacting with the web easier One of the major benefits of Groovy is how it simplifies some of the common scenarios we deal with in Java. Complex code with conditionals, error handling and many other concerns can be &hellip;<\/p>\n","protected":false},"author":232,"featured_media":132,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21],"tags":[],"class_list":["post-8446","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-groovy"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Groovy and HTTP<\/title>\n<meta name=\"description\" content=\"This article originally appeared in the December 2012 issue of GroovyMag. Some different ways that Groovy makes interacting with the web easier One of the\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Groovy and HTTP\" \/>\n<meta property=\"og:description\" content=\"This article originally appeared in the December 2012 issue of GroovyMag. Some different ways that Groovy makes interacting with the web easier One of the\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2013-02-12T11:00:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/groovy-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Kelly Robinson\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kelly Robinson\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html\"},\"author\":{\"name\":\"Kelly Robinson\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/b29a41a079b38879cb487b5538cba0e4\"},\"headline\":\"Groovy and HTTP\",\"datePublished\":\"2013-02-12T11:00:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html\"},\"wordCount\":1540,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/groovy-logo.jpg\",\"articleSection\":[\"Groovy\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html\",\"name\":\"Groovy and HTTP\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/groovy-logo.jpg\",\"datePublished\":\"2013-02-12T11:00:54+00:00\",\"description\":\"This article originally appeared in the December 2012 issue of GroovyMag. Some different ways that Groovy makes interacting with the web easier One of the\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/groovy-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/groovy-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/02\\\/groovy-and-http.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JVM Languages\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/jvm-languages\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Groovy\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/jvm-languages\\\/groovy\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Groovy and HTTP\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/b29a41a079b38879cb487b5538cba0e4\",\"name\":\"Kelly Robinson\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e41f09f3548f065fe6967ac904d3ea2a638614c16d879cac47cfad64e5b1426a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e41f09f3548f065fe6967ac904d3ea2a638614c16d879cac47cfad64e5b1426a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/e41f09f3548f065fe6967ac904d3ea2a638614c16d879cac47cfad64e5b1426a?s=96&d=mm&r=g\",\"caption\":\"Kelly Robinson\"},\"sameAs\":[\"http:\\\/\\\/www.kellyrob99.com\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/Kelly-Robinson\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Groovy and HTTP","description":"This article originally appeared in the December 2012 issue of GroovyMag. Some different ways that Groovy makes interacting with the web easier One of the","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html","og_locale":"en_US","og_type":"article","og_title":"Groovy and HTTP","og_description":"This article originally appeared in the December 2012 issue of GroovyMag. Some different ways that Groovy makes interacting with the web easier One of the","og_url":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2013-02-12T11:00:54+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/groovy-logo.jpg","type":"image\/jpeg"}],"author":"Kelly Robinson","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Kelly Robinson","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html"},"author":{"name":"Kelly Robinson","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/b29a41a079b38879cb487b5538cba0e4"},"headline":"Groovy and HTTP","datePublished":"2013-02-12T11:00:54+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html"},"wordCount":1540,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/groovy-logo.jpg","articleSection":["Groovy"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html","url":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html","name":"Groovy and HTTP","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/groovy-logo.jpg","datePublished":"2013-02-12T11:00:54+00:00","description":"This article originally appeared in the December 2012 issue of GroovyMag. Some different ways that Groovy makes interacting with the web easier One of the","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/groovy-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/groovy-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2013\/02\/groovy-and-http.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"JVM Languages","item":"https:\/\/www.javacodegeeks.com\/category\/jvm-languages"},{"@type":"ListItem","position":3,"name":"Groovy","item":"https:\/\/www.javacodegeeks.com\/category\/jvm-languages\/groovy"},{"@type":"ListItem","position":4,"name":"Groovy and HTTP"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/b29a41a079b38879cb487b5538cba0e4","name":"Kelly Robinson","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/e41f09f3548f065fe6967ac904d3ea2a638614c16d879cac47cfad64e5b1426a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/e41f09f3548f065fe6967ac904d3ea2a638614c16d879cac47cfad64e5b1426a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e41f09f3548f065fe6967ac904d3ea2a638614c16d879cac47cfad64e5b1426a?s=96&d=mm&r=g","caption":"Kelly Robinson"},"sameAs":["http:\/\/www.kellyrob99.com\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/Kelly-Robinson"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/8446","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/232"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=8446"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/8446\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/132"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=8446"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=8446"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=8446"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}