How to configure quartz plugin in grails 3? - grails

Recently I tried configuring my grails app for use with quartz scheduler. Unfortunately I failed configuring JDBC job store. The quartz plugin seems to ignore quartz.properties file, where table prefix is defined as Z_STAFF_SCHEDULER. Application startup fails with exception:
Caused by: org.springframework.scheduling.SchedulingException: Could
not start Quartz Scheduler; nested exception is
org.quartz.SchedulerConfigException: Failure occured during job
recovery. [See nested exception:
org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row
lock: Table 'testing.qrtz_locks' doesn't exist [See nested exception:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table
'testing.qrtz_locks' doesn't exist]]
Here is the relevant code in application.groovy:
quartz {
autoStartup = true
jdbcStore = true
waitForJobsToCompleteOnShutdown = true
exposeSchedulerInRepository = false
props {
scheduler.skipUpdateCheck = true
}
}
environments {
test {
quartz {
jdbcStore = false
autoStartup = false
}
}
}
grails.config.locations = ["classpath:conf/quartz.properties"]
and this is my config in quartz.properties:
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = StaffScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = development
org.quartz.jobStore.tablePrefix = Z_STAFF_SCHEDULER_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.development.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.development.URL = jdbc:mysql://localhost:3306/testing?useSSL=false
org.quartz.dataSource.development.user = testing
org.quartz.dataSource.development.password = nopass
org.quartz.dataSource.development.maxConnections = 10
org.quartz.dataSource.development.validationQuery = select 1
Anyone out there who can help me please?
I'm using grails 3.2.3 and quartz plugin 2.0.9

I finally found the solution myself. Every option for the quartz plugin can be configured in application.yml itself. See http://www.quartz-scheduler.org/documentation/quartz-2.2.x/configuration/ for a list of supported parameters.
You do not need any further files. Here's an extract from my application.yml as an example:
quartz:
autoStartup: true
jdbcStore: true
scheduler:
instanceName: 'staff_scheduler'
instanceId: 'AUTO'
threadPool:
class: 'org.quartz.simpl.SimpleThreadPool'
threadCount: 25
threadPriority: 5
jobStore:
misfireThreshold: 60000
class: 'org.quartz.impl.jdbcjobstore.JobStoreTX'
driverDelegateClass: 'org.quartz.impl.jdbcjobstore.StdJDBCDelegate'
useProperties: false
dataSource: 'development'
tablePrefix: 'Z_STAFF_SCHEDULER_'
isClustered: true
clusterCheckinInterval: 20000
dataSource:
development:
driver: 'com.mysql.jdbc.Driver'
URL: 'jdbc:mysql://localhost:3306/testing?useSSL=false'
user: 'testing'
password: 'nopass'
maxConnections: 28
validationQuery: 'select 1'

Related

Dynamic Quartz Configuration in Grails 3

In Grails 2, we had the following block of code in our Config.groovy file. The ConfigurationManagement class did a runtime lookup in a Configuration Management Database to determine if the quartz.autoStartup parameter should be true or false. We also used similar configuration to load additional Quartz properties.
quartz {
def autoStartupOnTheseServers = ConfigurationManagement.getValue("myApp.quartz.autoStartupOnTheseServers", "").split(",")
if ( autoStartupOnTheseServers.any { it.trim().toUpperCase() == hostName.toUpperCase() } ) {
autoStartup = true
}
else {
autoStartup = false
}
// Default for clustering (jdbcStore) has to be "false" so the app will run locally.
// Clustering (jdbcStore) will be true for DEV, TEST, QA, and PROD (set by Configuartion Management).
jdbcStore = ConfigurationManagement.getValue("myApp.quartz.jdbcStore", "false").toBoolean()
// don't set the props if not enabling quartz clustering...causes an exception.
if(jdbcStore == true) { props(quartzProps) }
}
In Grails 3, similar code used in application.groovy doesn't work and there isn't any facility for conditionals that I can find for application.yml. Is there any way in Grails 3 to do a similar dynamic configuration?
In Grails 3, it seems that you can't set these values directly, but you can declare a local variable and use that to set the property. So, for my example above, the following works:
def extServerList = ConfigurationManagement.getValue("myApp.quartz.autoStartupOnTheseServers", "").split(",")
def extAutoStartup = extServerList.any { it.trim().toUpperCase() == hostName.toUpperCase() }
def extJdbcStore = ConfigurationManagement.getValue("myApp.quartz.jdbcStore", "false").toBoolean()
quartz {
autoStartupOnTheseServers = extServerList
autoStartup = extAutoStartup
jdbcStore = extJdbcStore
}

Grails 3.0.1 - how and where to configure grails.gorm.default.mapping

I had in the old Config.groovy:
grails.gorm.default.mapping = {
id generator = 'identity'
// send only the dirty fields to the database for updating
dynamicUpdate = true
dynamicInsert = true
}
So I put this in the additionally application.groovy, but it won't be respected any more. All updates are full, sending all fields to the database, even the not changed ones.
I tried to translate this in application.yml:
grails:
gorm:
default:
mapping:
id generator: "identity"
dynamicUpdate: true
dynamicInsert: true
... but still without luck.
With Grails 3.1.10, it works in application.groovy:
dataSource {
//....
}
grails.gorm.default.mapping = {
uuid index:'idx_uuid', type: org.hibernate.type.UUIDCharType, length: 36, defaultValue: null
batchSize 15000
}
but had no sucess either while putting it in application.yml

Exception in grails dbm-update - NoSuchBeanDefinitionException

When I run "grails dbm-update --dataSource=production" I get the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'sessionFactory_production' is defined
at grails.plugin.databasemigration.MigrationUtils.findSessionFactory(MigrationUtils.groovy:142)
at grails.plugin.databasemigration.MigrationUtils.getDatabase(MigrationUtils.groovy:105)
at _DatabaseMigrationCommon_groovy$_run_closure2_closure11.doCall(_DatabaseMigrationCommon_groovy:52)
at grails.plugin.databasemigration.MigrationUtils.executeInSession(MigrationUtils.groovy:133)
at _DatabaseMigrationCommon_groovy$_run_closure2.doCall(_DatabaseMigrationCommon_groovy:51)
at DbmUpdate$_run_closure1.doCall(DbmUpdate:25)
It works on the default dataSource (if I run "grails dbm-update"), but doesn't work on production or on my custom data source.
I use Grails 2.4.3 and database-migration:1.4.0.
I'm running it on Amazon AWS - RDS MySql DB.
Here's my dataSource:
production {
grails.dbconsole.enabled = true
dataSource {
grails.dbconsole.enabled = true
username = "myusername"
password = "mypassword"
pooled = true
dbCreate = "none"
driverClassName = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://mydatabase.us-west-1.rds.amazonaws.com:3306/ebdb?autoReconnect=true" dialect = org.hibernate.dialect.MySQL5InnoDBDialect
properties {
validationQuery = "SELECT 1"
testOnBorrow = true
testOnReturn = true
testWhileIdle = true
timeBetweenEvictionRunsMillis = 1800000
numTestsPerEvictionRun = 3
minEvictableIdleTimeMillis = 1800000
}
}
}
The item you are refering to as production is not a datasource but the config for the regular dataSource in the production environment. So this call should work:
grails prod dbm-update

Defining an alternate connection pool in Grails 2.3.6

I know that, at some point between Grails 1.X and Grails 2.X, the default connection pooling library changed from commons-dbcp to tomcat-dbcp.
Now, I'm trying to configure either BoneCP or HikariCP as the connection pooling library for my Grails application.
However, I see that this answer offers a solution which might only apply to Grails 1.X.
I also found this Gist, but again, I don't know which Grails version it applies to.
So, is it possible to define a custom connection pool inside a Grails 2.3.6 application? Thanks!
UPDATE: OK so you actually need to tell Grails not to pool the datasources, since HikariCP is now taking care of this.
I saw connection weirdness in my apps if I left that switch on. So instead say:
pooled = false
OK yeah, #Joshua Moore is right.
I tried doing it with updated Grails methods and this is the relevant section of my resources.groovy file. As far as I can understand, the configuration values in Datasource.groovy are pulled into resources.groovy at runtime, after the target runtime environment has been identified (development, test or production).
def config = Holders.config
def dataSources = config.findAll {
it.key.toString().contains("dataSource_")
}
dataSources.each { key, value ->
def ds = value
"${key}"(HikariDataSource, { bean ->
def hp = new Properties()
hp.username = ds.username
hp.password = ds.password
hp.connectionTimeout = 6000
hp.maximumPoolSize = 60
hp.jdbcUrl = ds.url
hp.driverClassName = ds.driverClassName
HikariConfig hc = new HikariConfig(hp)
bean.constructorArgs = [hc]
})
}
And this is the relevant section of my DataSource.groovy configuration:
// environment specific settings
environments {
development {
dataSource_myapp1 {
pooled = false
username = "CONFIGURE_ME_EXTERNALLY"
password = "CONFIGURE_ME_EXTERNALLY"
driverClassName = 'oracle.jdbc.OracleDriver'
dialect = 'org.hibernate.dialect.Oracle10gDialect'
url = 'jdbc:oracle:thin:#MYDBHOST1:1521/MYSERVICEID1'
}
dataSource_myApp2 {
pooled = false
username = "CONFIGURE_ME_EXTERNALLY"
password = "CONFIGURE_ME_EXTERNALLY"
driverClassName = 'oracle.jdbc.OracleDriver'
dialect = 'org.hibernate.dialect.Oracle10gDialect'
url = 'jdbc:oracle:thin:#MYDBHOST2:1521/MYSERVICEID2'
}
}
}
In my case, it's pretty much the same for test and production environments. Thanks!

Configuring DataSource.groovy for Openshift for Grails

I'm trying to deploy a Grails application on Openshift.
I'm deploying the app using a locally built war file.
Right now, I am using the url given by the rhc-app-show command in the DataSource.groovy file for my Database configurations.
Whenever I try with the environment variables of Openshift (eg. $OPENSHIFT_MYSQL_DB_HOST), it crashes. Any idea or pointers on how to use those in the config file?
Thanks.
I haven't used OpenShift but Google led me to the FAQ which shows these environment variables:
OPENSHIFT_MYSQL_DB_HOST
OPENSHIFT_MYSQL_DB_PASSWORD
OPENSHIFT_MYSQL_DB_USERNAME
OPENSHIFT_MYSQL_DB_URL
OPENSHIFT_MYSQL_DB_PORT
so it looks like this would work:
production {
dataSource {
driverClassName = 'com.mysql.jdbc.Driver'
dialect = org.hibernate.dialect.MySQL5InnoDBDialect
String host = System.getenv('OPENSHIFT_MYSQL_DB_HOST')
String port = System.getenv('OPENSHIFT_MYSQL_DB_PORT')
String dbName = System.getenv('OPENSHIFT_APP_NAME')
url = "jdbc:mysql://$host:$port/$dbName"
username = System.getenv('OPENSHIFT_MYSQL_DB_USERNAME')
password = System.getenv('OPENSHIFT_MYSQL_DB_PASSWORD')
properties {
...
}
}
}
The missing bit is the database name - is that something that you would have available? I'm not sure of the format of OPENSHIFT_MYSQL_DB_URL but it looks like you might just be able to use url = "jdbc:${System.getenv('OPENSHIFT_MYSQL_DB_URL')}"
POSTGRES SQL ALSO ...there is a nice , tutorial for that on this link ...but the datasource configuration must be configured like this ....
production {
dataSource {
dbCreate = "update"
driverClassName = "org.postgresql.Driver"
dialect = org.hibernate.dialect.PostgreSQLDialect
uri = new URI(System.getenv('OPENSHIFT_POSTGRESQL_DB_URL'))
url = "jdbc:postgresql://"+uri.host+uri.path+"/"+System.getenv('OPENSHIFT_APP_NAME')
username = System.getenv('OPENSHIFT_POSTGRESQL_DB_USERNAME')
password = System.getenv('OPENSHIFT_POSTGRESQL_DB_PASSWORD')
}
second Alternative . . .
production {
dataSource {
dbCreate = "update"
driverClassName = "org.postgresql.Driver"
dialect = org.hibernate.dialect.PostgreSQLDialect
uri = new URI(System.getenv('OPENSHIFT_POSTGRESQL_DB_URL').toString())
appname = System.getenv('OPENSHIFT_APP_NAME').toString()
url = "jdbc:postgresql://"+uri.host.toString()+uri.path.toString()+"/"+appname
username = System.getenv('OPENSHIFT_POSTGRESQL_DB_USERNAME').toString()
password = System.getenv('OPENSHIFT_POSTGRESQL_DB_PASSWORD').toString()
}
In Grails 3.0.11, File application.yml
System.getenv doesn't work, so i had to configure manually the url connection for database in mysql.... Use the command of documentation https://developers.openshift.com/en/managing-port-forwarding.html
dataSource:
dbCreate: update
url : jdbc:mysql://thisIsTheUrlGetWithPort-ForwardCommandAndThePort:48381/server?verifyServerCertificate=false&autoReconnect=true&useSSL=false&requireSSL=false
driverClassName: com.mysql.jdbc.Driver
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
username : admin9CzsS #this is a username example
password : RR7y9uKw3t #this is a password example
properties:
jmxEnabled: true
initialSize: 5
maxActive: 50
minIdle: 5
maxIdle: 25
maxWait: 10000
maxAge: 600000
timeBetweenEvictionRunsMillis: 5000
minEvictableIdleTimeMillis: 60000
validationQuery: SELECT 1
validationQueryTimeout: 3
validationInterval: 15000
testOnBorrow: true
testWhileIdle: true
testOnReturn: false
jdbcInterceptors: ConnectionState
defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED

Resources