groovy script classpath - groovy

I'm writing a script in Groovy and I would like someone to be able to execute it simply by running ./myscript.groovy. However, this script requires a 3rd party library (MySQL JDBC), and I don't know of any way to provide this to the script other than via a -classpath or -cp argument, e.g.
`./monitor-vouchers.groovy -cp /path/to/mysql-lib.jar`
For reasons I won't go into here, it's not actually possible to provide the JAR location to the script using the -classpath/-cp argument. Is there some way that I can load the JAR from within the script itself? I tried using #Grab
import groovy.sql.Sql
#Grab(group='mysql', module='mysql-connector-java', version='5.1.19')
def getConnection() {
def dbUrl = 'jdbc:mysql://database1.c5vveqm7rqgx.eu-west-1.rds.amazonaws.com:3306/vouchers_prod'
def dbUser = 'pucaroot'
def dbPassword = 'password'
def driverClass = "com.mysql.jdbc.Driver"
return Sql.newInstance(dbUrl, dbUser, dbPassword, driverClass)
}
getConnection().class
But this causes the following error:
Caught: java.sql.SQLException: No suitable driver
java.sql.SQLException: No suitable driver
at monitor-vouchers.getConnection(monitor-vouchers.groovy:13)
at monitor-vouchers.run(monitor-vouchers.groovy:17)
Is there a way I can execute this script using just ./monitor-vouchers.groovy

You should be able to do:
import groovy.sql.Sql
#GrabConfig(systemClassLoader=true)
#Grab('mysql:mysql-connector-java:5.1.19')
def getConnection() {
def dbUrl = 'jdbc:mysql://database1.c5vveqm7rqgx.eu-west-1.rds.amazonaws.com:3306/vouchers_prod'
def dbUser = 'pucaroot'
def dbPassword = 'bigsecret'
def driverClass = "com.mysql.jdbc.Driver"
return Sql.newInstance(dbUrl, dbUser, dbPassword, driverClass)
}
getConnection().class

Two more options:
Put the jar in ${user.home}/.groovy/lib
If the jar is in a known location, use this code to load it into the current class loader:
this.class.classLoader.rootLoader.addURL( new URL() )

Related

How to define database 'driver' using Groovy sql module

I am trying to connect to an Oracle Sql Developer DB using Groovys sql class, which requires 4 pieces of information: (db url, username, password, db driver) I have all information needed except the driver. I have tried using oracle.jdbc.driver.OracleDrive and have set my GROOVY_HOME as : Variable: %GROOVY_HOME%\lib Value: C:\Oracle_SQL_DEVELOPER\sqldeveloper
I am receiving the following error :
Caused by: java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
I have referenced a few answers here on StackOverflow but haven't had any luck setting up a connection. Here are the links I've read and tried:
Unable to connect to oracle database from groovy
SQLException: No suitable Driver Found for jdbc:oracle:thin:#//localhost:1521/orcl
I have also looked and researched the Groovy documentation but it is not clear on how to define the driver: https://groovy-lang.org/databases.html#_connecting_with_a_datasource
Any help would be much appreciated. Here is the code for reference:
import groovy.sql.Sql
class EstablishConnection {
def static url = 'url'
def static user = 'user'
def static password = 'pass'
def static driver = 'oracle.jdbc.driver.OracleDriver'
def static sql = Sql.newInstance(url, user, password, driver)
}
EstablishConnection.sql.eachRow('select * from ACCOUNT where CONSTI_ID = \'12345678\';'){
row ->
def a = row[0]
}

Spark Custom Logging

I have multiple spark projects in my IDE. By default spark is picking log4j.properties file in spark/conf folder.
As I have multiple spark projects, I want have multiple log4j.properties files(per project one). Probably as part of the project code(resources folder)
Is there a way we can pickup specified log4j.properries instead of default log4j.properties.
Note:
I tried this
--driver-java-options "-Dlog4j.configuration=file:///usr/local/Cellar/apache-spark/2.4.1/libexec/conf/driver_log4j.properties"
and it worked without any issues, however I'm looking for something like below.
however I want to load log4j.properties file which is in resource folder while creating the spark logger.
class SparkLogger():
def __init__(self, app_name, sparksession = None):
self._spark = sparksession
self.log4jLogger = None
if self._spark is not None:
sparkContext =self._spark.sparkContext
self.log4jLogger = sparkContext._jvm.org.apache.log4j
self.log4jLogger = self.log4jLogger.LogManager.getLogger(app_name)
def info(self, info):
if self.log4jLogger:
self.log4jLogger.info(str(info))
def error(self, info):
if self.log4jLogger:
self.log4jLogger.error(str(info))
def warn(self, info):
if self.log4jLogger:
self.log4jLogger.warn(str(info))
def debug(self, info):
if self.log4jLogger:
self.log4jLogger.debug(str(info))
You have to define application_name log logger properties in log4j file. When you call get logger method using applicaiton_name, you will able to access customized application basis logs generation.
I have attempted to build my custom Logging just like what u described in your question but failed at last. I have to say it was totally a waste.
Finally I chose java.util.logging instead of log4j. Actually it is an original Logging util within JDK. The purpose I use it is that I wanna log information only for myself into a specified file.
So the class is like below.
package org.apache.spark.internal
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.logging._
import scala.collection.mutable
protected [spark] object YLogger extends Serializable with Logging {
private var ylogs_ = new mutable.HashMap[String, Logger]()
private def initializeYLogging(className: String): Unit = {
// Here we set log file onto user's home.
val rootPath = System.getProperty("user.home")
val logPath = rootPath + File.separator + className + ".log"
logInfo(s"Create ylogger for class [${className}] with log file named [${logPath}]")
val log_ = Logger.getLogger(className)
val fileHandler = new FileHandler(logPath, false)
val formatter = new Formatter {
override def format(record: LogRecord): String = {
val time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date)
new StringBuilder()
.append("[")
.append(className)
.append("]")
.append("[")
.append(time)
.append("]")
.append(":: ")
.append(record.getMessage)
.append("\r\n")
.toString
}
}
fileHandler.setFormatter(formatter)
log_.addHandler(fileHandler)
ylogs_.put(className, log_)
}
private def ylog(logName: String): Logger = {
if (!ylogs_.contains(logName)) {
initializeYLogging(logName)
}
ylogs_.get(logName).get
}
def ylogInfo(logName: String)(info: String): Unit = {
if (ylog(logName).isLoggable(Level.INFO)) ylog(logName).info(info)
}
def ylogWarning(logName: String)(warning: String): Unit = {
if (ylog(logName).isLoggable(Level.WARNING)) ylog(logName).warning(warning)
}
}
And you can use it like below.
YLogger.ylogInfo("logFileName") ("This is a log.")
It's quite simple to use, I hope my answer could help u.

Groovy call another script to set variables

I'm trying to define variables in another groovy script that I want to use in my current script. I have two scripts like this:
script1.groovy
thing = evaluate(new File("script2.groovy"))
thing.setLocalEnv()
println(state)
script2.groovy
static def setLocalEnv(){
def state = "hi"
def item = "hey"
}
When I println(state), I get a missing property exception. Basically I want script2 to have config variables that I can load in the context of script1. How can I do this?
I'm not sure what/how you want to do exactly, but I guess you can achieve your goal using one of the class available in groovy dynamique scripting capabilities: groovy.lang.Binding or GroovyClassLoader or GroovyScriptEngine, here is an example using GroovyShell class:
abstract class MyScript extends Script {
String name
String greet() {
"Hello, $name!"
}
}
import org.codehaus.groovy.control.CompilerConfiguration
def config = new CompilerConfiguration()
config.scriptBaseClass = 'MyScript'
def shell = new GroovyShell(this.class.classLoader, new Binding(), config)
def script = shell.parse('greet()')
assert script instanceof MyScript
script.setName('covfefe')
assert script.run() == 'Hello, covfefe!'
This is one way to bind a variable to an external script file, more examples from the doc:
http://docs.groovy-lang.org/latest/html/documentation/guide-integrating.html
P.S. Loading external file can be done with GroovyClassLoader:
def gcl = new GroovyClassLoader()
def clazz2 = gcl.parseClass(new File(file.absolutePath))
Hope this helps.

Unable to apply Newify on Groovyshell

I want to run some dynamic script with help of Groovyshell. But, i don't want to write new keyword in dynamic script. So, i thought of adding a CompilerConfiguration with Newify keyword. But, things are not working as expected.
CompilerConfiguration configuration = new CompilerConfiguration()
configuration.addCompilationCustomizers(
new ASTTransformationCustomizer(
[pattern: "[A-Za-z0-9].*"],
Newify
))
GroovyShell shell = new GroovyShell(profile, configuration)
Still i am getting error
Cannot find matching method sample#BoundingRegion(int, int, int, int)
where BoundingRegion is a class
Perhaps you need to provide more information. This works for me:
import org.codehaus.groovy.control.*
import org.codehaus.groovy.control.customizers.*
def script = '''
class Main {
static main(args) {
assert BigInteger.new(42).toString() == '42' // Ruby style
assert BigDecimal('3.14').toString() == '3.14' // Python style matching regex
}
}
'''
def configuration = new CompilerConfiguration()
configuration.addCompilationCustomizers(
new ASTTransformationCustomizer(
[pattern: "[A-Za-z0-9].*"],
Newify
))
new GroovyShell(configuration).evaluate(script)

SOAP UI Groovy DB connection

I am trying the following script:
import groovy.sql.Sql
println 'Some GR8 projects:'
com.eviware.soapui.support.GroovyUtils.registerJdbcDriver('net.sourceforge.jtds.jdbc.Driver')
sql = Sql.newInstance( 'jdbc:jtds:sqlserver://localhost:1433/agilejury-thehl_MC', 'user', 'password', 'net.sourceforge.jtds.jdbc.Driver' )
def rows = sql.rows( 'select * from pool_person' )
println rows.size()
sql.close()
I expected to see stuff in the script log, but I see absolutely nothing. I have run this as a groovy test step and as a setup script.
Is this script running?
Use
log.info rows.size()
I assume you already have the driver jar inside ..\soapUI-*.*.*\bin\ext or in the classpath.

Resources