Hi, I have a grails application that I have rec...
# questions
a
Hi, I have a grails application that I have recently upgraded from 5.3.6 to 6.2.0 The upgrade all worked fine, except for one issue, whereby although the app ran fine via gradle bootRun or running tests, but when deployed in tomcat the webapp was not recognised (Tomcat did not start it). With further investigation, it appears that the BootInitializerClassInjector AST Transformer in grails-web-boot is not running at compile time, and is not creating the ApplicationLoader class to go with my Application class - it is missing from the war file. If I modify my Application during runtime in dev mode, then I can see the BootInitializerClassInjector is running, and creating the ApplicationLoader - but not if I do a clean and then build a war file. I cannot see any messages/errors when compiling. I can manually create an ApplicationLoader class, with the same code as would be created by BootInitializerClassInjector, and when I do this, everything works find in tomcat. But this doesn't feel like the right solution. As this is a fairly large multi-module grails project, I'm sure this must be due to some missing configuration, or similar, but I cannot find where this might be (I have compared all major config, definition of Application class, dependencies, etc against a freshly created 6.2 webapp) Does anyone know what this might be, or can anyone point me towards where I should be looking to try & debug/diagnose this? (not a big expert on writing/debugging AST Transformations). Many thanks in advance for any advice.
j
Are you building the war with
gradle assemble
? And does bootStartScripts complete*?* 103434 PM: Executing 'assemble'... Starting Gradle Daemon... Gradle Daemon started in 1 s 241 ms
Task :clearBuildDir
Task :assetCompile
Task :compileJava NO-SOURCE
Task :compileGroovy
Task :generateGitProperties FROM-CACHE
Task :buildProperties
Task :processResources
Task :classes
Task :bootWarMainClassName
Task :compileWebappGroovyPages NO-SOURCE
Task :compileGroovyPages
Task :bootWar
Task :*bootStartScripts*
Task :bootDistTar
Task :bootDistZip
Task :jar
Task :*startScripts*
Task :distTar
Task :distZip
Task :war
Task :assemble
BUILD SUCCESSFUL in 42s 10 actionable tasks: 9 executed, 1 from cache 103516 PM: Execution finished 'assemble'.
a
I don't have the bootStartScripts stage executed at all, which is presumably the issue: > Task IotaacompileAstJava NO-SOURCE > Task IotaacompileAstGroovy NO-SOURCE > Task IotaaastClasses UP-TO-DATE > Task IotaacompileJava NO-SOURCE > Task IotaacopyAstClasses NO-SOURCE > Task IotaacompileGroovy > Task Iotaaclasses > Task IotaacompileWebappGroovyPages NO-SOURCE > Task IotaacompileGroovyPages > Task Iotaajar > Task PumpHouseassetCompile > Task PumpHousecompileAstJava NO-SOURCE > Task PumpHousecompileAstGroovy NO-SOURCE > Task PumpHouseastClasses UP-TO-DATE > Task PumpHousecompileJava NO-SOURCE > Task PumpHousecompileGroovy > Task PumpHousecopyAstClasses NO-SOURCE > Task PumpHouseclasses > Task PumpHousebootWarMainClassName > Task PumpHousebootWar > Task PumpHousewar > Task PumpHouseassemble
ok, I have added the application plugin to my build.gradle, and made sure application.mainClass is set, and it does now do the bootStartScripts stage, but still does not appear to create the ApplicationLoader class > Task PumpHouseassetCompile FROM-CACHE > Task PumpHousecompileAstJava NO-SOURCE > Task PumpHousecompileAstGroovy NO-SOURCE > Task PumpHouseastClasses UP-TO-DATE > Task PumpHousecompileJava NO-SOURCE > Task PumpHousecompileGroovy FROM-CACHE > Task PumpHousecopyAstClasses NO-SOURCE > Task PumpHouseclasses > Task PumpHousebootWarMainClassName > Task PumpHousebootWar > Task PumpHousebootStartScripts > Task PumpHousebootDistTar > Task PumpHousebootDistZip > Task PumpHousejar > Task PumpHousestartScripts > Task PumpHousedistTar > Task PumpHousedistZip > Task PumpHousewar > Task PumpHouseassemble
ok, presuambly with Grails 6.2, it's no longer using the ApplicationLoader, but is instead using SpringApplicationWebApplicationInitializer - however, this is throwing an exception when starting in tomcat - which looks like it is because Spring-Application-Source-Classes isn't set in the Manifest
ok, that exception is https://github.com/grails/grails-core/issues/13547 but when fixing that, I'm back to the issue of the webapp not starting in Tomcat (webapp is detected, and recognises logging, but does not actually start grails)
j
Which generated lib or distribution are you using from the build directory? plain or boot? When you say Tomcat, is that Tomcat provided by your server instance or are you using the boot war which includes Tomcat? There are a ton of combinations, so just trying to understand yours. I personally deploy on AWS Elastic Beanstalk with the Java SE Platform (Not Tomcat), use the generated boot war and it is started with
Copy code
java -jar admin.war
a
I'm trying to create a war file to use within a standalone tomcat.
At the moment, 2 wars are generated, one with org.springframework.boot directory, one without (and I would normally use the one without). If I try to deploy either of these in tomcat9, the webapp is detected and deployed, but grails application is not started - although if I manually create an ApplicationLoader class to go alongside the Application class, then it is started. If I try to use my app outside of standalone tomcat (e.g. via gradle bootRun, or running integration test), it all works fine.
j
Does your Application class extend GrailsAutoConfiguration?
Copy code
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import groovy.transform.CompileStatic

@CompileStatic
class Application extends GrailsAutoConfiguration {
    static void main(String[] args) {
        GrailsApp.run(Application, args)
    }
}
That's all I can think of. I'll let someone with more recent experience deploying to standalone tomcat hopefully help. I did confirm that ApplicationLoader.class was in the generated boot and plain wars for an application generated from https://start.grails.org/ for 6.2.0
a
yes, the Application class does extend GrailsAutoConfiguration:
class Application extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(Application, args)
}
If I alter this class at runtime in dev mode, I can see the BootInitializerClassInjector running and creating the ApplicationLoader for this class in the debugger - it's as if it's generally ok, but the ast transformation is not being run at all during compilation/build.
Ok, after a fair bit of debugging into the gradle & groovy compilation processes, I have found what the issue is. In case anyone else comes across the same issue: My grails project is a large multi-module gradle project with 1 app (within minimal files) and about 30 plugins (where all the main code is) It's set up with a buildSrc project, which contains several conventions.gradle files, importing standard dependencies, etc, so they don't need to be re-defined for each plugin. However, the conventions.gradle file common to the app and all plugins, for setting common settings/dependencies/plugins, included the 'org.grails.grails-plugin' gradle plugin. This means that: - the main app project applied the grails-plugin gradle plugin, rather than the base grails gradle plugin - this meant that a build/config.groovy ast transformation class was created (by the grails-plugin gradle plugin), and was applied to all source files in the main app, setting the Node MetaData property "isPlugin" to true. - this meant that when the BootInitializerClassInjector ran, it skipped over the main Application class, as it is was marked as a Plugin. Some part of this has changed between 5.3.6 and 6.2.0, but I'm not sure what part. But replacing the "grails-plugin" gradle plugin with the core "grails" gradle plugin, for the main App, has fixed the issue. hurrah!
🚀 1
🎉 1