Too Many Languages!

groovy, Java, programming, Python, Scala

ARGH! I’ve been bounced between languages. It’s driving me NUTS.

This is a comparison of how to do something in each to help me map between them.

There is definitely more to each of these languages than what’s shown. But I have to start somewhere….

English:

Given a list of integers ( 1, 2, 3 ), cube each value, then filter out even numbers, then calculate the sum of the remaining numbers.

Java:

int answer = Stream.of( 1, 2, 3 )
 .map( i -> i * i * i )
 .filter( i -> i % 2 != 0 )
 .mapToInt( i -> i )
 .sum();

Groovy:

int answer = [ 1, 2, 3 ]
 .collect { it * it * it }
 .findAll { it % 2 != 0 }
 .sum()

Scala:

val answer = List( 1, 2, 3 )
 .map( i => i * i * i )
 .filter( _ % 2 != 0 )
 .sum

Python:

answer = sum([
  j for j in [
    i * i * i for i in [1, 2, 3]
  ] if j % 2 > 0
])

 

Grails’s RESTClient

Grails, groovy, programming

The groovy.net.http.RESTClient class is a subclass of a more general groovyx.net.http.HttpBuilder class and comes with the “rest” plugin (http://grails.org/plugin/rest).

GET

A simple GET request with query parameters:

def rest = new RESTClient('http://www.my.com')
try {
// equivalent to: http://www.my.com/abc/123?param1=p1&param2=p2&param3=p3a&param3=p3b
def response = rest.get([
path:'/abc/123',
contentType:'application/json',
query:[param1:'p1', param2:'p2', param3:['p3a','p3b']])

// Assuming the server respects Content-Type and returns a JSON,
// the follow will provide the JSONObject or JSONArray
// for the returned results
def json = response.data
...
} catch (HttpResponseException ex) {
// errors and response status codes >= 400 end up here
}

POST

A sample for POSTing data w/ JSON

def rest = new RESTClient('http://www.my.com')
try {
// equivalent to: POST http://www.my.com/abc/123 with body of '{"param1": 1, "param2": "2"}'
def response = rest.post(path:'/abc/123',
contentType:'application/json',
body: [param1: 1, param2: "2"])
json = response.data
} catch (HttpResponseException ex) {
...
}

groovy.net.http.HttpBuilder uses the RequestConfigDelegate class to parse the map provided to get() and post(). The map supports these keys:

  • uri — used to specify the complete URL for the request, excluding the query component.  If used with path, then this should be the base URL. This value overrides the value passed to the ctor of RESTClient
  • query — used to specify a map of values representing the query parameters.  Lists are supported (see the GET example above).
  • path — used in conjunction with uri if you want to separate the path and base components of a URL.
  • contentType — the Content-Type to use and accept (either a String literal such as ‘application/json’ or a groovyx.net.http.ContentType constant).
  • requestContentType — if the request body type is different than the response (Accepts) body type, then this value is used to specify the request’s content type.
  • body — the body of the request
  • headers — used to specify a map of headers for the request

No support for URL fragments (as of rest-0.8)

You will need to create a java.net.URI instance with the entire URL w/ query and fragment and pass it to the ctor of RESTClient.

Response

By default, get() and post() will return an instance of groovyx.net.http.HttpResponseDecorator.  Commonly used methods are isSuccess() and getData().

  • isSuccess() returns true if the HTTP status code is < 400.
  • getData() will return the parsed body, and the type depends on the contentType used for the get() or post() method.

 

xml.MarkupBuilder in Groovy

groovy, programming

Typical use of the builder starts with:

import groovy.xml.MarkupBuilder

def writer = new StringWriter()
def xml = new MarkupBuilder(writer)

...

String generatedXml = writer.toString()

Then the “building” part is what’s not documented all that well.

Fundamentals

To get element and value:

xml.Outer("hello") 

Output:

<Outer>hello</Outer>

To add attributes, pass them as a map to the function:

xml.Outer(xmlns:'http://www.abc.com/blahblahblah')

Output:

<Outer xmlns:"http://www.abc.com/blahblahblah" />

To add children, add a closure in which to add more tags:

xml.Outer(xmlns:'http://www.abc.com/blahblahblah') {
   Inner("inner val")
}

Output:

<Outer xmlns:"http://www.abc.com/blahblahblah">
   <Inner>inner val</Inner>
</Outer>

Adding some attributes AND value to Inner:

xml.Outer(xmlns:'http://www.abc.com/blahblahblah') {
   Inner(id:"myId", "inner val")
}

Output:

<Outer xmlns:"http://www.abc.com/blahblahblah">
   <Inner id="myId">inner val</Inner>
</Outer>

NOTE how the Inner() call: it’s a Map followed by a String.

Loops

Turns out we can add code (such as loops) inside the closure:

xml.Outer(xmlns:'http://www.abc.com/blahblahblah') {
   Inner(id:"myId", "inner val")
   (1..5).each {i -> 
      MoreInner("innerChild ${i}")
   }
}

Output:

<Outer xmlns='http://www.abc.com/blahblahblah'>
  <Inner id='myId'>inner val</Inner>
  <MoreInner>innerChild 1</MoreInner>
  <MoreInner>innerChild 2</MoreInner>
  <MoreInner>innerChild 3</MoreInner>
  <MoreInner>innerChild 4</MoreInner>
  <MoreInner>innerChild 5</MoreInner>
</Outer>

Other than loops, more sophisticated code can be used. But that will complicate the code. Which brings us to functions.

Function calls

def addInnerChildren(builder) {
   builder.Inner(id:"myId", "inner val") {
      (1..5).each {i -> 
         MoreInner("innerChild ${i}")
      }
   }
}

xml.Outer(xmlns:'http://www.abc.com/blahblahblah') {
   addInnerChildren(xml)
}

Output:

<Outer xmlns='http://www.abc.com/blahblahblah'>
  <Inner id='myId'>inner val</Inner>
  <MoreInner>innerChild 1</MoreInner>
  <MoreInner>innerChild 2</MoreInner>
  <MoreInner>innerChild 3</MoreInner>
  <MoreInner>innerChild 4</MoreInner>
  <MoreInner>innerChild 5</MoreInner>
</Outer>

Prefix for namespace

It’s a bit cumbersome; we have to quote the “tag”:

xml.'hahaha:Outer'('xmlns:hahaha': 'http://www.abc.com/blahblahblah') {
   whatever('floats')
   'hahaha:your'('boat')
}

Output:

<hahaha:Outer xmlns:hahaha='http://www.abc.com/blahblahblah'>
  <whatever>floats</whatever>
  <hahaha:your>boat</hahaha:your>
</hahaha:Outer>

Dynamic tags

Finally, if we do not know the exact tag yet:

String tag = "hahaha"

...

xml."${tag}"(xmlns: 'http://www.abc.com/blahblahblah') {
   whatever('floats your boat')
}

Output:

<hahaha xmlns='http://www.abc.com/blahblahblah'>
  <whatever>floats your boat</whatever>
</hahaha>