Grails database migration plugin updateOnStart is not working - grails

I need some help here. I have configured database migration plugin as the documentation says:
grails.plugin.databasemigration.updateOnStart = true
grails.plugin.databasemigration.updateOnStartFileNames = ['changelog.groovy']
This works fine when running 'grails run-app'. My database is migrated as expected, but how would I get this behavior when deploy my 'grails war' artifact?
I have tested it on tomcat, by manually copying the artifact to tomcat/webapps folder, but during deployment, hibernate complains about missing columns (the one that should have been created by the database migration plugin).
Any ideas?
Thanks!

Are you sure that those two lines of code are available in production environment too?
This is an example of what I normally do in my applications:
environments {
development {
grails.plugin.databasemigration.updateOnStart = true
grails.plugin.databasemigration.updateOnStartFileNames = ['changelog.groovy']
// ... other useful development settings
}
test {
grails.plugin.databasemigration.updateOnStart = true
grails.plugin.databasemigration.autoMigrateScripts = ['RunApp','TestApp']
grails.plugin.databasemigration.forceAutoMigrate = true
grails.plugin.databasemigration.dropOnStart = true
if (loadTestData) {
grails.plugin.databasemigration.updateOnStartFileNames = ['testchangelog.groovy', 'testdata.groovy']
} else {
grails.plugin.databasemigration.updateOnStartFileNames = ['testchangelog.groovy']
// ... something test-related
}
}
production {
grails.plugin.databasemigration.updateOnStart = true
grails.plugin.databasemigration.updateOnStartFileNames = ['changelog.groovy']
// ... production config settings
}
}
Also, be sure to comment out relevant dbCreate entries in DataSource.groovy to avoid issues with migrations.

See this answer to a similar question https://stackoverflow.com/a/25053160/3939511
I find that the default value for grails.plugin.databasemigration.changelogLocation at compile time is correct to have your change-logs included in the production war. I.e. I don't set/change this property in Config.groovy at compile time.
But in deployment I set grails.plugin.databasemigration.changelogLocation = 'migrations', as the change-logs end up in WEB-INF/classes/migrations/ (as groovy scripts, not compiled classes).

I believe if you do a dbm-update that create the patches for you in the destination database.
Grabbed this from the Grails site.
http://grails-plugins.github.io/grails-database-migration/docs/manual/ref/Update%20Scripts/dbm-update.html
dbm-update
Purpose
Updates a database to the current version.
Description
Runs all un-run changeSets from the changelog. Executes against the database configured in DataSource.groovy for the current environment (defaults to dev).
Usage:

Related

Grails 3 - no production logs

I've seen some other posts about this but no solutions yet; I've never had an issue with NO LOGS in earlier versions of Grails so this is highly annoying as I'm trying to trouble-shoot why my app works as expected in QA but not in production.
There are no logs created by the application in the tomcat container; not a one.
I have catalina.date files for actual tomcat processes but NOTHING for the app, which I feel in earlier Grails versions was included here or stdout. Anyone have a solution for this?
This is Grails 3, FYI
In [grails-app/conf/logback.groovy] there is a method to build logs however it is confined to development mode. Comment out the conditional tags (if ..) and re-build/deploy. Logs will show up # the path specified in the method, in my case, stacktrace.log:
def targetDir = BuildSettings.TARGET_DIR
//if (Environment.isDevelopmentMode() && targetDir) {
appender("FULL_STACKTRACE", FileAppender) {
file = "${targetDir}/stacktrace.log"
append = true
encoder(PatternLayoutEncoder) {
pattern = "%level %logger - %msg%n"
}
}
logger("StackTrace", ERROR, ['FULL_STACKTRACE'], false)
//}

Disable reloading in Grails 3.1 / springloaded

I'm trying to disable automatic reload/recompiling in Grails 3.1 as I would like to use JRebel instead.
I find springloaded rather limited, but more importantly is constantly fails with
File /Users/engrun/Development/projects/grailsPoc/grails-app/controllers/grailsPoc/HelloController.groovy changed, recompiling...
java.lang.IllegalAccessException: Class org.springsource.loaded.ReloadableType can not access a member of class org.springframework.aop.framework.CglibAopProxy$ClassLoaderAwareUndeclaredThrowableStrategy with modifiers "public"
I have tried all kinds of settings that I have found available, however, none actually disables reloading when running the run-app command
I have tried
disable.auto.recompile=true
on command line, GRAILS_OPTS, and in application.yml
I have tried the
-noreloading
flag, both on command line and GRAILS_OPTS.
According to docs, this should have worked
https://grails.org/wiki/Auto%20Reloading
And the answer accepted as the correct one here
how can I disable reloading in a grails 3.0.0 app?
does not work either.
Have anyone actually succeeded in disabling auto-reloading in Grails 3.1?
(And successfully configured Grails 3 with JRebel?)
In 3.x apps you can disable Spring Loaded by adding
grails {
agent {
enabled = false
}
}
to build.gradle.
Burt's answer is correct related to the question -> how to disable autoreloading.
However, Anton's answer is relevant to the second/related issue on getting Jrebel to work.
I now have a working example, which works with both
gradle bootRun -Pjrebel -> disable springloaded, using jrebel
gradle bootRun -> uses springloaded
and
grails
grails> run-app
My config is a combination of
export GRAILS_OPTS="-javaagent:$JREBEL_HOME/jrebel.jar -Drebel.base=/Users/<username>/.jrebel"
and build.gradle
rebel {
alwaysGenerate = false
showGenerated = true
//rebelXmlDirectory = "build/classes"
}
if (project.hasProperty('jrebel')) {
bootRun.dependsOn(generateRebel)
grails {
agent {
enabled = false
}
}
tasks.withType(JavaExec) {
jvmArgs "-javaagent:jrebel.jar"
jvmArgs "-Xverify:none"
}
}
Thanks #burt-beckwith and #anton-arhipov for your input!
To enable JRebel for Grails 3 project you need to configure -javaagent argument with the corresponding path the jrebel.jar in build.gradle file:
tasks.withType(JavaExec) { jvmArgs "-javaagent:jrebel.jar" }

How to force Grails to use a signed certificate with run-app or run-war

Even after adding this code to Config.groovy, Grails insists on using its own self-signed certificate:
grails.tomcat.truststorePath = "${grailsSettings.baseDir}/conf/ssl/truststore.jks"
grails.tomcat.truststorePassword = "changeit"
grails.tomcat.clientAuth = "want"
grails.tomcat.keystorePath = "${grailsSettings.baseDir}/conf/ssl/keystore.jks"
grails.tomcat.keystorePassword = "changeit"
grails.tomcat.keyAlias = "localhost"
Any idea how to force Grails to use the real keystore here?
Apparently, it's a common mistake to put these settings in Config.groovy. They belong in BuildConfig.groovy. Once I put them in BuildConfig.groovy, everything worked for me.
I couldn't get your example to work or figure out how to set any properties in BuildConfig.groovy, but for grails 2.5.0 this worked for me in scripts/_Events.groovy.
eventConfigureTomcat = { org.apache.catalina.startup.Tomcat tomcat ->
if (Environment.getCurrent() == Environment.DEVELOPMENT) {
System.setProperty("javax.net.debug", "ssl") //use this to confirm grails adds proper keystore/truststore settings
System.setProperty("javax.net.ssl.keyStoreType", "jks")
System.setProperty("javax.net.ssl.keyStore", "/absolute/path/to/keystore")
System.setProperty("javax.net.ssl.keyStorePassword", "<_password_>")
System.setProperty("javax.net.ssl.trustStoreType", "jks")
System.setProperty("javax.net.ssl.trustStore", "/absolute/path/to/truststore")
System.setProperty("javax.net.ssl.trustStorePassword", "<_password_>")
println "SSL configuration complete"
}
}

How to tell Grails application which environment it is in?

I would like to load Environment specific configurations in my grails application so that depending on which JVM the grails application is running on, I can point to that environment specific urls. In my case, I have 4 different environments to work with (instead of the default 3 that grails app assumes) when my app goes from dev to prod.
My JVMs all have a System property defined that, when I do "System.getProperty()", tell me which environment that application is running on.
My question is, what is the best place to check and load the environment-specific configurations during run-time? Inside BootStrap.groovy? I do not have the option to build my war file using command line or grails {env_name} war.
Thanks.
Set the variable grailsEnv as a environment Java variable for Tomcat below is an example:
set CATALINA_OPTS=%CATALINA_OPTS% -Xms256m -Xmx1024m -Dgrails.env=development
On a grails command line you add the environment variable:
grails run-app -Dgrails.env=stage
You can use check the environment variable like this:
if (grails.util.Environment.current.name == "development") {
UsageCodeDefinition ucd = new UsageCodeDefinition()
ucd.setDescription("UFARSFileUpload Upload Development")
ucd.setFiscalYear("12-13")
ucd.setInstructions("Welcome to UFARSFileUpload Development were Open")
ucd.save(failOnError: true)
}
You can use the Enumerated values instead of the name variable but if you use custom environmental values then they are mapped to the enumeration custom and using the name works to distinguish between the custom values.
if (grails.util.Environment.current == grails.util.Environment.DEVELOPMENT) {
Without setting the JVM startup parameter:
-Dgrails.env=whatever
Your grails app will use the value set in
<yourapp>/WEB-INF/classes/application.properties
There will be a value set like this:
grails.env=development
This default environment value is determined by what options are used when building the war. You can build the war with
-Dgrails.env=development war
Then the application.properties will have grails.env=development, if you leave that off, it defaults to grails.env=production
As far as your question, you are not specific about what is being configured to use "environment specific urls". And it is not clear how you are storing these environment specific urls. If, for example, the URL variable is a member variable of a Grails service and you are storing the environment specific URLs in the Config.groovy, then you could
import grails.util.Environment
...
//inject the GrailsApplication Configuration in Config.groovy
def grailsApplication
//Hold the URL value from Config.groovy
String environmentUrl
...
Environment current = Environment.getCurrent()
if(Environment.PRODUCTION == current) {
environmentUrl = grailsApplication.config.PRODUCTION_URL
} else {
environmentUrl = grailsApplication.config.DEVELOPMENT_URL
}
Where Config.groovy has
PRODUCTION_URL = "http://blah.com/blah/"
DEVELOPMENT_URL = "http://blah.dev/blah"
Hope that helps.
If you have a System property available that tells you what environment you're in you can simply add if statements or a switch statement in your Config.groovy file, like this:
if (System.getProperty("foo") == "myTestEnvironment") {
myConfigSetting = "test"
} else if (System.getProperty("foo") == "myProductionEnvironment") {
myConfigSetting = "production"
}
This solution also works in other config files under grails-app/conf
Grails config files are parsed using groovy ConfigSlurper so you can put executable code in there without a problem.
Sorry this is way late, but another way is to inject a configuration property in BootStrap.groovy.
For Example:
if (currentEnv == Environment.DEVELOPMENT) {
...
grailsApplication.config.some.property = DEVELOPMENT_ENVRIONMENT
...
}
else if (currentEnv == Environment.TEST) {
...
grailsApplication.config.some.property = TEST_ENVIRONMENT
...
}
I have used this recently and it works really well. We are using Grails 2.5.2
As an addendum to the other answers:
You can use Environment.isDevelopmentMode() or in a groovier way Environment.developmentMode to check if the environment is set to development. This is useful when you take the aproach of only modifying settings for development on your code where production settings are default.

Can't use progresql in grails

I'm importing a exists grails project, this project use postgresql use remote postgresql, they built it on real machine, now I need do it on my localhost machine, and use postgresql local.
Everything is OK, but the system can use postgresql, althought I set up it in datasource.config. My datasource.config is similar to old real one, just change something between remote server and local server. Here is my datasource.config.
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = false
cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
}
// environment specific settings
environments {
production {
pooled = true
driverClassName = "org.postgresql.Driver"
username = "postgres"
password = "postgres"
dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate'
url = "jdbc:postgresql://localhost:5432/faql_dev"
}
}
Here is some error I got:
Caused by: org.compass.gps.device.hibernate.HibernateGpsDeviceException: {hibernate}: Failed to index the database; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query using scroll
at org.compass.gps.device.hibernate.indexer.ScrollableHibernateIndexEntitiesIndexer.performIndex(ScrollableHibernateIndexEntitiesIndexer.java:172)
at org.compass.gps.device.support.parallel.ConcurrentParallelIndexExecutor$1$1.doInCompassWithoutResult(ConcurrentParallelIndexExecutor.java:104)
at org.compass.core.CompassCallbackWithoutResult.doInCompass(CompassCallbackWithoutResult.java:29)
at org.compass.core.CompassTemplate.execute(CompassTemplate.java:133)
at org.compass.gps.impl.SingleCompassGps.executeForIndex(SingleCompassGps.java:147)
at org.compass.gps.device.support.parallel.ConcurrentParallelIndexExecutor$1.call(ConcurrentParallelIndexExecutor.java:102)
... 5 more
Caused by: org.hibernate.exception.SQLGrammarException: could not execute query using scroll
at org.compass.gps.device.hibernate.indexer.ScrollableHibernateIndexEntitiesIndexer.performIndex(ScrollableHibernateIndexEntitiesIndexer.java:118)
... 10 more
Caused by: org.h2.jdbc.JdbcSQLException: Table "QUESTION" not found; SQL statement:
I imported everything involve to postgresql, So I can create table based on domain in development mode, but I can't run it. In production, it will throw that exception.
Thanks in advance!
Caused by: org.h2.jdbc.JdbcSQLException
This suggests to me that you're using the wrong JDBC driver. The data source configuration you've posted only sets the app up to use Postgres in production mode, if you run locally in dev mode then it'll use the default H2 database.

Resources