casparjespersen
casparjespersen

Reputation: 3870

Groovy syntax for enter/exit block

Is there a way to define a block/environment with custom open and close methods? Currently, I have:

script {
   withCredentials([usernamePassword(credentialsId: '...', usernameVariable: 'CONFIG_USER', passwordVariable: 'CONFIG_PASS')]) {
      def sql = Sql.newInstance("...", CONFIG_USER, CONFIG_PASS, "com.mysql.jdbc.Driver")
      sql.rows("SELECT * FROM visualization").each { row ->
         println "row ${row.branch}"
      }
      sql.close()
   }
}

I would like to be able to do:

with sqlConnection() { sql ->
   sql.rows("SELECT * FROM visualization").each { row ->
      println "row ${row.branch}"
   }
}

Where it automatically opens/closes the connection accordingly. I am new to Groovy, so it's the syntax I'm concerned about. In Python I would do this using an object __enter__/__exit__.

Upvotes: 1

Views: 263

Answers (1)

Mene
Mene

Reputation: 3809

If I understand you correctly you want a new method sqlConnection() that does the withCredentials part?

You can use a closure parameter to do something before or after something else.

def sqlConnection(Closure withSqlClosure) {
    withCredentials([usernamePassword(credentialsId: '...', usernameVariable: 'CONFIG_USER', passwordVariable: 'CONFIG_PASS')]) {
        Sql.newInstance("...", CONFIG_USER, CONFIG_PASS, "com.mysql.jdbc.Driver").withCloseable {sql ->
            withSqlClosure(sql)
        }
    }
}

Can be used like this

sqlConnection() { sql ->
    sql.rows("SELECT * FROM visualization").each { row ->
        println "row ${row.branch}"
    }
}

So everything before the call to the closure (withSqlClosure(sql)) corresponds to __enter__ everything after the call is your __exit__. Note that you will need to lookout for exceptions. Usually you will want to wrap the closure call in a try { ... } finally { ... } Statement. Here I used withCloseable which does that for us (assuming Sql.newInstance returns a Closeable).

To aid your IDE and enable @CompileStatic you should also add a @ClosureParams

def sqlConnection(
        @ClosureParams(value = groovy.transform.stc.SimpleType,
                options = ["your.sql.type"]) Closure withSqlClosure) {
    withCredentials([usernamePassword(credentialsId: '...', usernameVariable: 'CONFIG_USER', passwordVariable: 'CONFIG_PASS')]) {
        Sql.newInstance("...", CONFIG_USER, CONFIG_PASS, "com.mysql.jdbc.Driver").withCloseable {sql ->
            withSqlClosure(sql)
        }
    }
}

Here your.sql.type is the return type of Sql.newInstance.

Upvotes: 2

Related Questions