Pentaho data source access from Groovy - groovy

In Pentaho Report Designer (PRD), I want to connect to my Data source using a Groovy script (or EMCAScript script) by referring to JNDI created in default.properties file. So, I will create a mult-value list parameter containing JNDI names and connect to the data source based on the JNDI selected in the parameter.
Script:
import groovy.sql.Sql
import javax.naming.InitialContext
import javax.sql.DataSource
class SqlClient {
InitialContext context = new InitialContext()
DataSource dataSource = context.lookup("OLTP") as DataSource
def sql = new Sql(dataSource)
sql.execute("SELECT * FROM Person.User_JNDI")
TypedTableModel model = new TypedTableModel();
while(sql.next())
model.addRow(new Object [] {rs.getString(1)});
c.close();
return model;
}
I am getting the following error:
Caused by: org.apache.bsf.BSFException: exception from Groovy: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
expression: 11: unexpected token: sql # line 11, column 5.
sql.execute("SELECT * FROM Person.User_JNDI")
Also, PRD expects the script to return a model, probably something to do with TypedtableModel class.
Can anyone give me an example of Groovy script?

Assuming that you have filled the default.properties as it says here, you should be able to access the data source with something like:
import groovy.sql.Sql
import javax.naming.InitialContext
import javax.sql.DataSource
class SqlClient {
InitialContext context = new InitialContext()
DataSource dataSource = context.lookup("SampleData") as DataSource
def sql = new Sql(dataSource)
sql.execute '''
select * from ... '''
...
}
Using a Sql instance.

Related

Problem with executing sql query in BigQuery using ExecuteGroovyScript in NiFi

I have ExecuteGroovyScript 1.15.3 processor.
Additional classpath property points to java bigquery client and its dependencies.
List of jars:
api-common-1.9.0.jar
auto-value-annotations-1.7.jar
checker-compat-qual-2.5.5.jar
commons-codec-1.11.jar
commons-logging-1.2.jar
error_prone_annotations-2.3.4.jar
failureaccess-1.0.1.jar
gax-1.56.0.jar
gax-httpjson-0.73.0.jar
google-api-client-1.30.9.jar
google-api-services-bigquery-v2-rev20200324-1.30.9.jar
google-auth-library-credentials-0.20.0.jar
google-auth-library-oauth2-http-0.20.0.jar
google-cloud-bigquery-1.111.1.jar
google-cloud-core-1.93.4.jar
google-cloud-core-http-1.93.4.jar
google-http-client-1.34.2.jar
google-http-client-appengine-1.34.2.jar
google-http-client-jackson2-1.34.2.jar
google-oauth-client-1.30.5.jar
grpc-context-1.29.0.jar
gson-2.8.6.jar
guava-29.0-android.jar
httpclient-4.5.11.jar
httpcore-4.4.13.jar
j2objc-annotations-1.3.jar
jackson-core-2.10.2.jar
javax.annotation-api-1.3.2.jar
jsr305-3.0.2.jar
listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
opencensus-api-0.24.0.jar
opencensus-contrib-http-util-0.24.0.jar
proto-google-common-protos-1.17.0.jar
proto-google-iam-v1-0.13.0.jar
protobuf-java-3.11.4.jar
protobuf-java-util-3.11.4.jar
threetenbp-1.4.3.jar
Also processor has CTL.credentials property, value is controller service of GCPCredentialsControllerService type.
Script that instantiates BigQuery:
def creds = CTL.credentials.getGoogleCredentials()
def bigQuery = new BigQueryOptions.DefaultBigQueryFactory().create(
BigQueryOptions.newBuilder()
.setProjectId(ProjectId.evaluateAttributeExpressions().value)
.setCredentials(creds)
.build());
And I got error:
groovy.lang.MissingMethodException: No signature of method:
com.google.cloud.bigquery.BigQueryOptions$Builder.setCredentials() is applicable for argument types:
(com.google.auth.oauth2.ServiceAccountCredentials) values: [ServiceAccountCredentials{....}]
Possible solutions: setCredentials(com.google.auth.Credentials)
This is very strange because ServiceAccountCredentials extends Credentials.
So I tried to explicitly cast it:
def creds = CTL.credentials.getGoogleCredentials() as Credentials
I got error:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'ServiceAccountCredentials{....}'
with class 'com.google.auth.oauth2.ServiceAccountCredentials' to class 'com.google.auth.Credentials'
Then I tried to cast to ServiceAccountCredentials and I got:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'ServiceAccountCredentials{....}'
with class 'com.google.auth.oauth2.ServiceAccountCredentials' to class 'com.google.auth.oauth2.ServiceAccountCredentials'
Why am I getting a GroovyCastException? What could be the problem? Maybe there is an easier way to execute sql?

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]
}

groovy.lang.MissingPropertyException: No such property:

I am trying to get my head around groovy scripting to make some changes to a jenkins pipeline and I keep getting this error:
groovy.lang.MissingPropertyException: No such property: credentials for class:
I have tried declaring the variable with def but I still get the exception, eclipse does not recognise that the property exists.
What am I doing wrong?!
#!/usr/bin/groovy
package common.pipeline
import common.pipeline.Credentials
Credentials credentials = new Credentials()
def withCredentials(steps) {
credentials.productionPipeline(steps)
}
This script will be compiled by groovy into a Script class with the field definition inside the run method, and with another method withCredentials that is trying to access the field (kinda like this):
import common.pipeline.Credentials
class Script1 extends Script {
def withCredentials(steps) {
credentials.productionPipeline(steps)
}
def run(args) {
Credentials credentials = new Credentials()
}
}
As you can see, this won't work, as the credentials aren't at Field level in the class...
Groovy has an annotation to make this happen:
#!/usr/bin/groovy
package common.pipeline
import common.pipeline.Credentials
import groovy.transform.Field
#Field Credentials credentials = new Credentials()
def withCredentials(steps) {
credentials.productionPipeline(steps)
}

jenkins pipeline groovy.sql.Sql NotSerializableException

there is a problem with the class groovy.sql.Sql inside jenkinsfile.
We are using groovy.sql.Sql to call DB.
Try with simple import groovy.sql.Sql we are take error:
java.io.NotSerializableException: groovy.sql.Sql
Then, try to hide this class inside shell class in jenkins file, like this:
class Shell{
private groovy.sql.Sql sql
Shell(){
sql = Sql.newInstance("jdbc:oracle:thin:#$TNS", login, password, driver)
}
String callSql(String stmnt){
return sql.firstRow(stmnt).Variablename
}
}
But get another error "MissingPropertyException: No such property: Sql for class".
Can u help to fix this problem?

groovy script classpath

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() )

Resources