Wednesday, April 24, 2013

Grails upgrading from 1.3.7 to 2.1.0

I am working on a Grails project and it was with a very old version 1.3.7, I need to integrate AAF as identity provider to my application. AAF officially provides a grails plugin, however it works only with Grails 2.x. So what I have to do first is upgrading my Grails Application from 1.3.7 to 2.1.0.

I am not expert in Grails and just started to work on Grails project early this month. After spent almost one day on it, finally my application is with Grails 2.1.0 now.

Here, I write down a transcript of my upgrade session, and hope it will be helpful to the people like me who are still a newbie to Grails.

Before doing upgrade, I read the offical upgrade reference doc from:
http://grails.org/doc/2.1.0/guide/upgradingFromPreviousVersionsOfGrails.html

2013-04-24 10:30 am - Starting Grails 1.3.7 to 2.1.0 upgrade.

# grails upgrade


 Error Failed to resolve dependencies (Set log level to 'warn' in BuildConfig.groovy for more information):

- org.grails.plugins:mail:1.0-SNAPSHOT
- org.grails.plugins:tomcat:1.3.7
- org.grails.plugins:hibernate:1.3.7

This is because I have not manually changed the plugins's version to latest/greatest  (plugins version config can be found in BuildConfig.groovy OR application.properties) . To get the greatest version of plugins for Grails 2.1.0, just use command:

# grails plugin-info pluginName

Then manually update BuildConfig.groovy by looking at a fresh 2.1.0 application.

# grails upgrade

| Error SLF4J: Class path contains multiple SLF4J bindings.
| Error SLF4J: Found binding in [jar:file:/home/htxiong/.grails/ivy-cache/org.grails/grails-plugin-log4j/jars/grails-plugin-log4j-2.1.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
| Error SLF4J: Found binding in [jar:file:/home/htxiong/.grails/ivy-cache/org.slf4j/slf4j-log4j12/jars/slf4j-log4j12-1.5.8.jar!/org/slf4j/impl/StaticLoggerBinder.class]
| Error SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

 Project upgraded

Please just ignore the SLF4J error, it wont stop you to compile and run your app. I spent almost half of my time on trying to resolve this error and eventually found that it can be ignored.

# grails clean

  Application cleaned.

# grails compile
  
   SUCCESS

hint: If your compile failed because "can not resolove type ........" e.g. can not resolve org.tmatesoft.svn.core.SVNException. do not try to resolve the dependency in pom.xml, but just find the svn Grails plugin and install it.  

# grails test-app

Cannot create JDBC driver of class 'org.h2.Driver' for connect URL 'jdbc:hsqldb:mem:testDb'
java.sql.SQLException: No suitable driver

I have to modify DataSource.groovy and chagne HSQLDB to H2. 

test {
        dataSource {
pooled = true
driverClassName = "org.h2.Driver"
username = "sa"
password = ""
dbCreate = "update"
url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
        }
    }

# grails test-app

   PASSED.

# grails run-app

Error executing bootstraps: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: org.codehaus.groovy.grails.web.converters.marshaller.json.DomainClassMarshaller(java.lang.Boolean)
org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: org.codehaus.groovy.grails.web.converters.marshaller.json.DomainClassMarshaller(java.lang.Boolean)
at grails.converters.JSON.createNamedConfig(JSON.java:468)
at au.org.emii.portal.config.JsonMarshallingRegistrar._registerSnapshotLayer(JsonMarshallingRegistrar.groovy:88)
at au.org.emii.portal.config.JsonMarshallingRegistrar.registerJsonMarshallers(JsonMarshallingRegistrar.groovy:27)
at au.org.emii.portal.bootstrap.MenuBootStrap$_closure1.doCall(MenuBootStrap.groovy:18)
at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:301)
at grails.util.Environment.executeForEnvironment(Environment.java:294)
at grails.util.Environment.executeForCurrentEnvironment(Environment.java:270)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Caused by: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: org.codehaus.groovy.grails.web.converters.marshaller.json.DomainClassMarshaller(java.lang.Boolean)
at au.org.emii.portal.display.SnapshotLayerJsonMarshaller.<init>(SnapshotLayerJsonMarshaller.groovy:43)
at au.org.emii.portal.config.JsonMarshallingRegistrar$__registerSnapshotLayer_closure3.doCall(JsonMarshallingRegistrar.groovy:89)
at grails.converters.JSON.createNamedConfig(JSON.java:464)

Ahh, grails 2.1.0 provides a new version of class "DomainClassMarshaller" and the constructor takes one more parameter 'GrailsApplication'. 
So, to resolve it, just find its subclasses and put grailsApplication as the 2nd parameter in super() .

        SnapshotLayerJsonMarshaller() {
super(false, grailsApplication)
}

# grails run-app

   SUCCESS.

2013-04-24 40:10 pm - Grails upgraded.

----------------------------------------------------------------------------------------------------------------------------------
I got dependency not found & plugin failed to install errors many times, and sometimes Grails even tell you failed to resolve some dependencies which are included in Grails installation. 

e.g. 
[ERROR] Failed to execute goal on project grails-project: Could not resolve dependencies for project grails-project:grails-project:war:4.0-SNAPSHOT
: Failed to collect dependencies for [org.grails:grails-crud:jar:2.1.0 (compile), org.grails:grails-core:jar:2.1.0 (compile), org.grails:grails-spring:jar:2.1.0
(compile), org.grails:grails-test:jar:2.1.0 (compile), org.grails:grails-web:jar:2.1.0 (compile), org.slf4j:slf4j-api:jar:1.5.8 (compile), org.slf4j:slf4j-log4
j12:jar:1.5.8 (compile), log4j:log4j:jar:1.2.14 (provided), junit:junit:jar:4.5 (test), commons-lang:commons-lang:jar:2.4 (compile)]: Failed to read artifact de
scriptor for org.springframework.uaa:org.springframework.uaa.cl ient:jar:1.0.1.RELEASE: Could not transfer artifact org.springframework.uaa:org.springframework.uaa


I do not why Grails return such error, but there is a way to walkaround. 

delete the directory ivy-cache in your Grails folder (linux, ~/.grails/ivy-cache) and re-compile your app.
./grails folder works similar with .m2 folder for maven, it contains all the dependency jars for your Grails application. Empty it and re run grails compile will download all the dependencies from internet for your application.



-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Another example to do Grails upgrading can not found on http://www.technipelago.se/content/technipelago/blog/grails-upgrade-1.3.7-to-2.0.1 which from by another developer. 

No comments:

Post a Comment