Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy Closure explanation

Tags:

groovy

I'm familiar with normal groovy closures like these

def printSum = {a,b ->
   println a+b
}

printSum(5,7) // 12

However, I came across code from SpringWS plugin that I have a hard time understanding:

def withEndpointRequest = { url, payload ->
    def writer = new StringWriter()
    def request = new MarkupBuilder(writer)
    payload.delegate = request
    payload.call()
    def webServiceTemplate = new WebServiceTemplate()

    def response = webServiceTemplate.sendToEndpoint(url, writer.toString())
    new XmlSlurper().parseText(response)
}

I understand that above is a closure.

It is being used like this:

    def namespace = "http://www.myveryimportantcompany.com/hr/schemas"
    def serviceURL = "http://localhost:8080/myapp/services"
    def response = withEndpointRequest(serviceURL) {
        HolidayRequest(xmlns: namespace) {
            Holiday {
                StartDate("2006-07-03")
                EndDate("2006-07-07")
            }
            Employee {
                Number("42")
                FirstName("Russ")
                LastName("Miles")
            }
        }
    }

if serviceURL is being passed in then where is the payload?

Can someone please explain this snippet in some detail?

like image 932
Anthony Avatar asked Oct 03 '22 20:10

Anthony


1 Answers

In the above implementation, withEndpointRequest is a closure which takes two parameters.

withEndpointRequest(String serviceUrl, Closure payload).

When you are using withEndpointRequest from your client, you are actually doing

    def namespace = "http://www.myveryimportantcompany.com/hr/schemas"
    def serviceURL = "http://localhost:8080/myapp/services"
    def payload = {
         HolidayRequest(xmlns: namespace) {
            Holiday {
                StartDate("2006-07-03")
                EndDate("2006-07-07")
            }
            Employee {
                Number("42")
                FirstName("Russ")
                LastName("Miles")
            }
        }
    }
    def response = withEndpointRequest(serviceURL, payload) 

The above was made groovier by declaring the closure inline with withEndpointRequest. The above can also be written as

def response = withEndpointRequest(serviceURL, {
        //payload goes here as an inline closure as the second parameter
        HolidayRequest(xmlns: namespace) {
            Holiday {
                StartDate("2006-07-03")
                EndDate("2006-07-07")
            }
            Employee {
                Number("42")
                FirstName("Russ")
                LastName("Miles")
            }
        }
    })

which is less verbose. Finally, it can be streamlined and made more groovier by writing as

def response = withEndpointRequest(serviceURL) {
        HolidayRequest(xmlns: namespace) {
            Holiday {
                StartDate("2006-07-03")
                EndDate("2006-07-07")
            }
            Employee {
                Number("42")
                FirstName("Russ")
                LastName("Miles")
            }
        }
    }

One point to note here is that the Closure payload is the last parameter.

Now, note that the closure (payload) is not invoked until payload.call() is invoked as mentioned in your question inside SpringWS plugin.

Have a look at Closures as Method Arguments.

I hope I was able to convey what you wanted to understand. :)

like image 189
dmahapatro Avatar answered Oct 13 '22 10:10

dmahapatro