Grails Liquibase plugin conflicts with Spring Security plugin

Hello,

I recently migrated a Grails application from the Acegi plugin to the new Spring Security plugin and got a NoClassDefFoundError error when running migrate that was complaining about missing Spring Security classes.  After taking a look at LiquibaseSetup.groovy and playing with it a bit I was able to work around it; see attached patch.  It may or may not be the best solution to the problem but it allowed me to run the migrate script without errors.  I am wondering if anyone else has run into this issue and/or if a fix is coming in a later release.

I am running liquibase-1.9.3.0 with Grails 1.3.2/Groovy 1.7.3/Sun JDK 1.6.0_20-b02.  Here’s the complete stack trace.

Error executing script Migrate: org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
java.lang.NoClassDefFoundError: org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
at SpringSecurityCoreGrailsPlugin$_closure1.class$(SpringSecurityCoreGrailsPlugin.groovy)
at SpringSecurityCoreGrailsPlugin$_closure1.$get$$class$org$codehaus$groovy$grails$plugins$springsecurity$SpringSecurityUtils(SpringSecurityCoreGrailsPlugin.groovy)
at SpringSecurityCoreGrailsPlugin$_closure1.doCall(SpringSecurityCoreGrailsPlugin.groovy:128)
at _GrailsPackage$_run_closure5_closure19.doCall(_GrailsPackage.groovy:232)
at _GrailsPackage$_run_closure5_closure19.doCall(_GrailsPackage.groovy)
at _GrailsSettings$_run_closure10.doCall(_GrailsSettings.groovy:282)
at _GrailsSettings$_run_closure10.call(_GrailsSettings.groovy)
at _GrailsPackage$_run_closure5.doCall(_GrailsPackage.groovy:230)
at _GrailsPackage$_run_closure2.doCall(_GrailsPackage.groovy:168)
at LiquibaseSetup$_run_closure1.doCall(LiquibaseSetup.groovy:27)
at Migrate$_run_closure1.doCall(Migrate:4)
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:427)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:415)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.executeTargets(Gant.groovy:590)
at gant.Gant.executeTargets(Gant.groovy:589)
Error executing script Migrate: org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils

I think it’s related to a bug I received a patch with for grails 1.3, but executing grails to do the plugin deploy throws an exception on my machine that I have been unable to figure out. 

Even “grails clean” gives me this output:

    C:\development\grails-liquibase>\grails-1.3.2\bin\grails clean Welcome to Grails null - http://grails.org/ Licensed under Apache Standard License 2.0 Grails home is set to: C:\grails-1.3.2\bin\..

    Base Directory: C:\development\grails-liquibase
    Resolving dependencies…
    Error executing script Clean: null
    java.lang.NullPointerException
            at org.apache.ivy.core.resolve.ResolveOptions.getDefaultResolveId(Resolv
    eOptions.java:301)
            at org.apache.ivy.core.report.ResolveReport.(ResolveReport.java:66
    )
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

            at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstruct
    orAccessorImpl.java:39)
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
    onstructorAccessorImpl.java:27)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
            at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstru
    ctor.java:77)
            at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteN
    oUnwrapNoCoerce.callConstructor(ConstructorSite.java:107)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstru
    ctor(CallSiteArray.java:52)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor
    (AbstractCallSite.java:192)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor
    (AbstractCallSite.java:200)
            at org.codehaus.groovy.grails.resolve.IvyDependencyManager.resolveDepend
    encies(IvyDependencyManager.groovy:477)
            at org.codehaus.groovy.grails.resolve.IvyDependencyManager$resolveDepend
    encies$0.callCurrent(Unknown Source)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent
    (CallSiteArray.java:44)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(Abs
    tractCallSite.java:143)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(Abs
    tractCallSite.java:151)
            at org.codehaus.groovy.grails.resolve.IvyDependencyManager.resolveDepend
    encies(IvyDependencyManager.groovy:456)
            at org.codehaus.groovy.grails.resolve.IvyDependencyManager$resolveDepend
    encies.call(Unknown Source)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSi
    teArray.java:40)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCa
    llSite.java:117)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCa
    llSite.java:125)
            at grails.util.BuildSettings$_getBuildDependencies_closure13.doCall(Buil
    dSettings.groovy:381)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:597)
            at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMet
    hodSite.invoke(PogoMetaMethodSite.java:225)
            at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(P
    ogoMetaMethodSite.java:51)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent
    (CallSiteArray.java:44)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(Abs
    tractCallSite.java:143)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(Abs
    tractCallSite.java:151)
            at grails.util.BuildSettings$_getBuildDependencies_closure13.doCall(Buil
    dSettings.groovy)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:597)
            at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:
    88)
            at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058)
            at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1070)

            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:886)
            at groovy.lang.Closure.call(Closure.java:276)
            at groovy.lang.Closure.call(Closure.java:271)
            at groovy.lang.Closure$call$0.call(Unknown Source)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSi
    teArray.java:40)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCa
    llSite.java:117)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCa
    llSite.java:121)
            at grails.util.BuildSettings.getBuildDependencies(BuildSettings.groovy:3
    78)
            at org.codehaus.groovy.grails.cli.GrailsScriptRunner.getClassLoaderUrls(
    GrailsScriptRunner.java:832)
            at org.codehaus.groovy.grails.cli.GrailsScriptRunner.callPluginOrGrailsS
    cript(GrailsScriptRunner.java:420)
            at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeCommand(Grai
    lsScriptRunner.java:318)
            at org.codehaus.groovy.grails.cli.GrailsScriptRunner.main(GrailsScriptRu
    nner.java:135)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
    java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
    sorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:597)
            at org.codehaus.groovy.grails.cli.support.GrailsStarter.rootLoader(Grail
    sStarter.java:226)
            at org.codehaus.groovy.grails.cli.support.GrailsStarter.main(GrailsStart
    er.java:251)
    Error executing script Clean: null

Have you seen anything similar before?

Nathan

I found the problem thanks to http://stackoverflow.com/questions/1160615/error-in-grails

Can you try updating your plugin and see if it helps?

Nathan

I uninstalled 1.9.3.0 and installed 1.9.3.1 and that fixes the problem.  Thanks.

Good, thanks for letting me know.

Nathan

OK, I saw the error again while upgrading my staging environment.  I upgraded liquibase before installing spring-security-core.  But uninstalling liquibase and then reinstalling it fixed the issue.  it seems like the order of installation is relevant.

That is odd.  We have no 3rd party dependencies, including spring so I don’t know how our code would affect other modules. 

Anyone with more grails expertise able to help?

Nathan

I don’t think it’s a dependency issue.  I think it has to do with how LiquibaseSetup.groovy is initializing.  Have another look at the patch I attached to my original post.  I admit I hacked at it pretty quickly and got it working, but I think there is something worth investigating there.  What seems to be happening is that Spring is trying to initialize itself before grails is ready for it, for lack of a better explanation.  On the way to what’s in the patch I had an intermediate step where I simply commented out the call to packageApp() on line 21 in LiquibaseSetup.groovy and didn’t mess with the depends() call on line 18.  The NoClassDefFoundError went away but was replaced by an error complaining that a Spring Security database table was missing, which was a bummer because the migration I was running was supposed to create the missing tables.  When I changed the depends() call to what’s in the patch everything worked fine. (I think that’s the sequence of events, anyway… I was in a hurry to get it working.)

I’ll have another look at it  and see if i can figure it out.  Admittedly this is a really oddball case, I’m not sure how many others are running into this issue.  But I’ll try to sort it out because it’ll help me and maybe save someone else some hassle.

I committed your patch along with version requirement change.  Let me know if it is working better now.

Nathan

Thanks a lot.

Jed

Hello together,

is this supposed to be resolved? I just tried to use the liquibase grails plugin for the first time and got this exception after running “grails generate-changelog”:

    Error executing script GenerateChangelog: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager': Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: Lorg/codehaus/groovy/grails/plugins/springsecurity/acl/AclObjectIdentity; org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager': Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: Lorg/codehaus/groovy/grails/plugins/springsecurity/acl/AclObjectIdentity;

the mentioned class AclObjectIdentity is provided by the spring-security-acl plugin

Thanks in advance!

Sven

I wonder if the change did not actually make it into the grails plugin repository.  I’ll double check the version that is in there.

Nathan

Thanks for your answer. I am using the liquibase 1.9.3.5 plugin which I consider the current one. From my application.properties:

    app.grails.version=1.3.5 app.name=MyApp app.servlet.version=2.4 app.version=0.2.1 plugins.hibernate=1.3.5 plugins.joda-time=1.1 plugins.jquery=1.4.3.2 plugins.jquery-ui=1.8.4.3 plugins.liquibase=1.9.3.5 plugins.spring-security-acl=1.0.1 plugins.spring-security-core=1.0.1 plugins.tomcat=1.3.5 plugins.webflow=1.3.5 plugins.wikitext=0.1.2

In case this is only a fix for 2.0: Is there a place where I can get a 2.0rc grails plugin or even the source?

Thanks a lot,

Sven

The repository is at https://github.com/liquibase/grails-liquibase although I haven’t put the 2.0 liquibase in there yet.  If you build that locally and install it does it work for you?

Nathan

Unfortunately not.

I tried again and created a project that contains nothing except the two plugins liquibase (from git) and spring-security-acl. Even without additional domain classes I get the exception.
Here is a more complete part of the stacktrace:

    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager': Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: Lorg/codehaus/groovy/grails/plugins/springsecurity/acl/AclObjectIdentity; at grails.spring.BeanBuilder.createApplicationContext(BeanBuilder.java:582) at grails.spring.BeanBuilder$createApplicationContext.call(Unknown Source) at _GrailsBootstrap_groovy$_run_closure1.doCall(_GrailsBootstrap_groovy:64) at LiquibaseSetup_groovy$_run_closure1.doCall(LiquibaseSetup_groovy:21) at GenerateChangelog$_run_closure1.doCall(GenerateChangelog:7) at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381) ... 10 more

It is worth noting that AclObjectIdentity is created by the s2-acl install script under grails-app/domain/… . But it is extending the class “AbstractAclObjectIdentity” which is provided by the acl plugin itself. If I manually copy AbstractAclObjectIdentity.groovy to the main project “generate-changelog” works again.
So I suspect there is a problem with a classloader. Unfortunately I don’t know of the grails plugin mechanism. I will ask on the grails user list if somebody can help out.

Sven

I got help from Burt Beckwith, the author of the spring-security plugins. He pointed out:

The Liquibase plugin scripts are a little dated. This line in LiquibaseSetup.groovy is the culprit:
    rootLoader.addURL(new File("${classesDirPath}").toURL())
 

Older versions of Grails needed that but it’s no longer needed. I don’t know why it’d cause this issue, but deleting the line fixes this issue.

(see http://www.pubbs.net/201011/grails/21075-re-grails-user-spring-security-acl-and-liquibase-plugin-incompatibility.html)

I can confirm this, but now I have another error:

    liquibase.exception.JDBCException: java.sql.SQLException: Column not found: PASSWORD in statement [SELECT password FROM "user" WHERE 1 = 0]

Thanks,

Sven

Thanks for the pointer.  I will get that line removed.

I’m not sure what your new error is from, I don’t believe that SQL is from our codebase at all.

Nathan

I applied a patch from another thread to git that should resolve the issue.  I don’t remember if you submitted the patch or someone else.

Nathan