Closed stefanrother closed 6 years ago
Good find and thank you for reporting!. I’ll look into getting this resolved in a later build.
On Feb 22, 2017, at 6:49 AM, Stefan Rother-Stübs notifications@github.com wrote:
Problem
We are migrating our Grails 2.2.2 application from the resources plugin to the asset-pipeline plugin. Some views are already migrated but most of them still use the resources plugin.
Sometimes the application does not start and produces the following stack trace on initialization of the asset-pipeline: | 2017-01-27 09:16:25,342 [localhost-startStop-1] ERROR org.grails.plugin.resource.ResourceProcessor - Unable to load resources groovy.lang.MissingMethodException: No signature of method: asset.pipeline.grails.CachingLinkGenerator.appendMapKey() is applicable for argument types: (java.lang.StringBuilder, java.util.LinkedHashMap) values: [resource, [plugin:jquery, dir:js/jquery, ...]] at asset.pipeline.grails.CachingLinkGenerator.makeKey(CachingLinkGenerator.groovy:55) at asset.pipeline.grails.CachingLinkGenerator.resource(CachingLinkGenerator.groovy:24) at org.grails.plugin.resource.ResourceProcessor.buildLinkToOriginalResource(ResourceProcessor.groovy:485) at org.grails.plugin.resource.ResourceModule$_closure1.doCall(ResourceModule.groovy:62) at org.grails.plugin.resource.ResourceModule.
(ResourceModule.groovy:58) at org.grails.plugin.resource.ResourceProcessor.defineModuleFromBuilder(ResourceProcessor.groovy:681) at org.grails.plugin.resource.ResourceProcessor$_loadModules_closure19.doCall(ResourceProcessor.groovy:802) at org.grails.plugin.resource.ResourceProcessor.loadModules(ResourceProcessor.groovy:802) at org.grails.plugin.resource.ResourceProcessor.reloadAll(ResourceProcessor.groovy:1075) at ResourcesGrailsPlugin$_closure3.doCall(ResourcesGrailsPlugin.groovy:172) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask.run(FutureTask.java:262) 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:745) The source of the problem seems to be buried in a bug in Groovy (GROOVY-3073 - Private inheritance bug: Closure accessing private method https://issues.apache.org/jira/browse/GROOVY-3073) and the fact that the class asset.pipeline.grails.CachingLinkGenerator extends org.codehaus.groovy.grails.web.mapping.CachingLinkGenerator and accesses the private method appendMapKey() from the super class via its makeKey() method.
We were surprised that this is possible (We did not expect the access to private methods of the super class to work) and that this sometimes fails.
The problem appears on our development machines (iMacs with OS X 10.11.6 and JDK 1.7.0_75) and our staging and production systems (Debian 8 with Tomcat 7.0.73 and JDK 1.7.0_111)
Workaround
Our workaround is to inject a modified copy of asset.pipeline.grails.CachingLinkGenerator that has copies of the private methods of the super class that were accessed by makeKey(). Via resources.groovy we inject the class the same way it is done in AssetPipelineGrailsPlugin.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/bertramdev/asset-pipeline/issues/148, or mute the thread https://github.com/notifications/unsubscribe-auth/AABaEl17P65Wk-E_SI8JiDOJ8EE2uzZ8ks5rfC7ZgaJpZM4MImmO.
Seeing the same upgrading to Grails 3.2.8 from 3.2.6.
2017-04-13 15:33:14,550 [http-nio-8080-exec-4] DEBUG o.g.w.s.v.GroovyPageView - Error processing GroovyPageView: [views/login/auth.gsp:30] Error executing tag <g:form>: No signature of method: asset.pipeline.grails.CachingLinkGenerator.appendMapKey() is applicable for argument types: (java.lang.StringBuilder, org.grails.taglib.GroovyPageAttributes) values: [link, [method:post, action:auth, id:loginForm]] org.grails.taglib.GrailsTagException: [views/login/auth.gsp:30] Error executing tag <g:form>: No signature of method: asset.pipeline.grails.CachingLinkGenerator.appendMapKey() is applicable for argument types: (java.lang.StringBuilder, org.grails.taglib.GroovyPageAttributes) values: [link, [method:post, action:auth, id:loginForm]]
I have the same problem as @jglapa
Stepping through in a debugger, i can see that this line: https://github.com/bertramdev/asset-pipeline/blob/master/asset-pipeline-grails/src/main/groovy/asset/pipeline/grails/CachingLinkGenerator.groovy#L56
calls this method: https://github.com/grails/grails-core/blob/v3.2.8/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/CachingLinkGenerator.java#L104
when the exception is thrown.
Same problem in createLink function (Grails updagre 3.2.9 from 3.2.7)
protected String generateLink(String action, String token) {
createLink(base: "$request.scheme://$request.serverName:$request.serverPort$request.contextPath",
controller: 'user', action: action, params: [t:token])
}
Error in log
Caused by: groovy.lang.MissingMethodException: No signature of method: asset.pipeline.grails.CachingLinkGenerator.appendMapKey() is applicable for argument types: (java.lang.StringBuilder, org.grails.taglib.GroovyPageAttributes) values: [link, [base:http://localhost:8080, controller:user, action:resetPassword, ...]]
at asset.pipeline.grails.CachingLinkGenerator.makeKey(CachingLinkGenerator.groovy:56)
at org.grails.web.mapping.CachingLinkGenerator.link(CachingLinkGenerator.java:79)
at org.grails.plugins.web.taglib.ApplicationTagLib.doCreateLink(ApplicationTagLib.groovy:382)
at org.grails.plugins.web.taglib.ApplicationTagLib$_closure9.doCall(ApplicationTagLib.groovy:359)
at org.grails.taglib.TagOutput.captureTagOutput(TagOutput.java:64)
at grails.artefact.gsp.TagLibraryInvoker$Trait$Helper.methodMissing(TagLibraryInvoker.groovy:88)
at btask.UserController.generateLink(UserController.groovy:859)
at btask.UserController.forgotPassword(UserController.groovy:662)
... 47 common frames omitted
I started to implement @stefanrother 's workaround in his report, but I found that by reimplementing the private method it depends on another ton of private stuff in the class and doesn't seem feasible. I think the simple fix is for the base class (org.codehaus.groovy.grails.web.mapping.CachingLinkGenerator) to not mark that method as private. Anyone have any pull with the devs of that module? I've never forked grails framework else I'd just do it and submit a PR. My workaround was to stop using g:link which isn't feasible in anything but the short term.
I wonder why this started happening with just a minor Grails version update. From the release notes it looks like the version was build with a newer Groovy 2.4.10
. They warn that the StaticCompile
is more strict though.
You can theoretically bypass the private access by using reflection but I'm not sure if this is such a good idea.
Downgrading to Groovy 2.4.7 in my Grails 3.2.9 webapp project clears up this problem for me. I did this by:
I'm sure there is a better way, but here is how i updated my build.gradle to explicitly override all groovy packages versions:
dependencies {
provided "org.codehaus.groovy:groovy:${groovyVersion}"
provided "org.codehaus.groovy:groovy-all:${groovyVersion}"
provided "org.codehaus.groovy:groovy-ant:${groovyVersion}"
provided "org.codehaus.groovy:groovy-groovydoc:${groovyVersion}"
provided "org.codehaus.groovy:groovy-json:${groovyVersion}"
provided "org.codehaus.groovy:groovy-sql:${groovyVersion}"
provided "org.codehaus.groovy:groovy-templates:${groovyVersion}"
provided "org.codehaus.groovy:groovy-test:${groovyVersion}"
provided "org.codehaus.groovy:groovy-xml:${groovyVersion}"
console "org.codehaus.groovy:groovy:${groovyVersion}"
console "org.codehaus.groovy:groovy-console:${groovyVersion}"
console "org.codehaus.groovy:groovy-groovysh:${groovyVersion}"
console "org.codehaus.groovy:groovy-swing:${groovyVersion}"
console "org.codehaus.groovy:groovy-templates:${groovyVersion}"
console "org.codehaus.groovy:groovy-xml:${groovyVersion}"
....
}
./grailsw dependency-report --plain-output
FYI I've raised an issue in the grails core project https://github.com/grails/grails-core/issues/10660
UPDATE the method visibility has been changed to protected
with this https://github.com/grails/grails-core/commit/7e48044add7b0d489a48e6a72e1c860b45a23668
This should be available with the next Grails release.
nice thanks!
Problem
We are migrating our Grails 2.2.2 application from the resources plugin to the asset-pipeline plugin. Some views are already migrated but most of them still use the resources plugin.
Sometimes the application does not start and produces the following stack trace on initialization of the asset-pipeline:
| 2017-01-27 09:16:25,342 [localhost-startStop-1] ERROR org.grails.plugin.resource.ResourceProcessor - Unable to load resources groovy.lang.MissingMethodException: No signature of method: asset.pipeline.grails.CachingLinkGenerator.appendMapKey() is applicable for argument types: (java.lang.StringBuilder, java.util.LinkedHashMap) values: [resource, [plugin:jquery, dir:js/jquery, ...]] at asset.pipeline.grails.CachingLinkGenerator.makeKey(CachingLinkGenerator.groovy:55) at asset.pipeline.grails.CachingLinkGenerator.resource(CachingLinkGenerator.groovy:24) at org.grails.plugin.resource.ResourceProcessor.buildLinkToOriginalResource(ResourceProcessor.groovy:485) at org.grails.plugin.resource.ResourceModule$_closure1.doCall(ResourceModule.groovy:62) at org.grails.plugin.resource.ResourceModule.<init>(ResourceModule.groovy:58) at org.grails.plugin.resource.ResourceProcessor.defineModuleFromBuilder(ResourceProcessor.groovy:681) at org.grails.plugin.resource.ResourceProcessor$_loadModules_closure19.doCall(ResourceProcessor.groovy:802) at org.grails.plugin.resource.ResourceProcessor.loadModules(ResourceProcessor.groovy:802) at org.grails.plugin.resource.ResourceProcessor.reloadAll(ResourceProcessor.groovy:1075) at ResourcesGrailsPlugin$_closure3.doCall(ResourcesGrailsPlugin.groovy:172) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask.run(FutureTask.java:262) 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:745)
The source of the problem seems to be buried in a bug in Groovy (GROOVY-3073 - Private inheritance bug: Closure accessing private method) and the fact that the class
asset.pipeline.grails.CachingLinkGenerator
extendsorg.codehaus.groovy.grails.web.mapping.CachingLinkGenerator
and accesses the private methodappendMapKey()
from the super class via itsmakeKey()
method.We were surprised that this is possible (We did not expect the access to private methods of the super class to work) and that this sometimes fails.
The problem appears on our development machines (iMacs with OS X 10.11.6 and JDK 1.7.0_75) and our staging and production systems (Debian 8 with Tomcat 7.0.73 and JDK 1.7.0_111)
Workaround
Our workaround is to inject a modified copy of
asset.pipeline.grails.CachingLinkGenerator
that has copies of the private methods of the super class that were accessed bymakeKey()
. Viaresources.groovy
we inject the class the same way it is done inAssetPipelineGrailsPlugin
.