Skip to content

Commit 8b7ed75

Browse files
committed
Rework the way find main task sets due to issues with provider assignments
1 parent d303077 commit 8b7ed75

File tree

2 files changed

+159
-110
lines changed

2 files changed

+159
-110
lines changed

grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy

Lines changed: 141 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
2929
import org.apache.tools.ant.filters.EscapeUnicode
3030
import org.apache.tools.ant.filters.ReplaceTokens
3131
import org.gradle.api.Action
32+
import org.gradle.api.GradleException
3233
import org.gradle.api.NamedDomainObjectProvider
3334
import org.gradle.api.Plugin
3435
import org.gradle.api.Project
@@ -164,6 +165,18 @@ class GrailsGradlePlugin extends GroovyPlugin {
164165
}
165166
}
166167

168+
private static Provider<String> getMainClassProvider(Project project) {
169+
Provider<FindMainClassTask> findMainClassTask = project.tasks.named('findMainClass', FindMainClassTask)
170+
project.provider {
171+
File cacheFile = findMainClassTask.get().mainClassCacheFile.orNull?.asFile
172+
if (!cacheFile.exists()) {
173+
return null
174+
}
175+
176+
cacheFile?.text
177+
}
178+
}
179+
167180
private void configureGroovyCompiler(Project project) {
168181
Provider<Directory> sourceConfigFiles = project.layout.buildDirectory.dir('groovyCompilerConfiguration')
169182
Provider<RegularFile> groovyCompilerConfigFile = project.layout.buildDirectory.file('grailsGroovyCompilerConfig.groovy')
@@ -433,13 +446,22 @@ class GrailsGradlePlugin extends GroovyPlugin {
433446
for (ctxCommand in applicationContextCommands) {
434447
String taskName = GrailsNameUtils.getLogicalPropertyName(ctxCommand, 'Command')
435448
String commandName = GrailsNameUtils.getScriptName(GrailsNameUtils.getLogicalName(ctxCommand, 'Command'))
436-
if (project.tasks.findByName(taskName) == null) {
437-
project.tasks.create(taskName, ApplicationContextCommandTask) {
438-
classpath = fileCollection
439-
command = commandName
440-
systemProperty Environment.KEY, System.getProperty(Environment.KEY, Environment.DEVELOPMENT.getName())
441-
if (project.hasProperty('args')) {
442-
args(CommandLineParser.translateCommandline(project.args))
449+
if (!project.tasks.names.contains(taskName)) {
450+
project.tasks.register(taskName, ApplicationContextCommandTask).configure {
451+
it.classpath = fileCollection
452+
it.command = commandName
453+
it.systemProperty Environment.KEY, System.getProperty(Environment.KEY, Environment.DEVELOPMENT.getName())
454+
List<Object> args = []
455+
def otherArgs = project.findProperty('args')
456+
if (otherArgs) {
457+
args.addAll(CommandLineParser.translateCommandline(otherArgs as String))
458+
}
459+
460+
def appClassProvider = GrailsGradlePlugin.getMainClassProvider(project)
461+
462+
it.doFirst {
463+
args << appClassProvider.get()
464+
it.args(args)
443465
}
444466
}
445467
}
@@ -564,57 +586,46 @@ class GrailsGradlePlugin extends GroovyPlugin {
564586
}
565587

566588
NamedDomainObjectProvider<Configuration> consoleConfiguration = project.configurations.register('console')
567-
def consoleTask = createConsoleTask(project, tasks, consoleConfiguration)
568-
def shellTask = createShellTask(project, tasks, consoleConfiguration)
569-
570-
tasks.named('findMainClass').configure {
571-
it.doLast {
572-
def extraProperties = project.getExtensions().getByType(ExtraPropertiesExtension)
573-
if (!extraProperties.has('mainClassName')) {
574-
return // disabled because we don't expect to run a grails app (likely a plugin)
575-
}
576-
577-
def mainClassName = extraProperties.get('mainClassName')
578-
if (mainClassName) {
579-
consoleTask.get().args mainClassName
580-
shellTask.get().args mainClassName
581-
project.tasks.withType(ApplicationContextCommandTask) { ApplicationContextCommandTask task ->
582-
task.args mainClassName
583-
}
584-
}
585-
project.tasks.withType(ApplicationContextScriptTask) { ApplicationContextScriptTask task ->
586-
task.args mainClassName
587-
}
588-
}
589-
}
590-
591-
consoleTask.configure {
592-
it.dependsOn(tasks.named('classes'), tasks.named('findMainClass'))
593-
}
594-
595-
shellTask.configure {
596-
it.dependsOn(tasks.named('classes'), tasks.named('findMainClass'))
597-
}
589+
createConsoleTask(project, tasks, consoleConfiguration)
590+
createShellTask(project, tasks, consoleConfiguration)
598591
}
599592
}
600593

601594
@CompileDynamic
602595
protected TaskProvider<JavaExec> createConsoleTask(Project project, TaskContainer tasks, NamedDomainObjectProvider<Configuration> configuration) {
603596
def consoleTask = tasks.register('console', JavaExec)
604-
consoleTask.configure {
605-
it.classpath = project.sourceSets.main.runtimeClasspath + configuration.get()
606-
it.mainClass.set('grails.ui.console.GrailsSwingConsole')
597+
project.afterEvaluate {
598+
consoleTask.configure {
599+
it.dependsOn(tasks.named('classes'), tasks.named('findMainClass', FindMainClassTask))
600+
it.classpath = project.sourceSets.main.runtimeClasspath + configuration.get()
601+
it.mainClass.set('grails.ui.console.GrailsSwingConsole')
602+
603+
def appClass = GrailsGradlePlugin.getMainClassProvider(project)
604+
605+
it.doFirst {
606+
it.args(appClass.get())
607+
}
608+
}
607609
}
608610
consoleTask
609611
}
610612

611613
@CompileDynamic
612614
protected TaskProvider<JavaExec> createShellTask(Project project, TaskContainer tasks, NamedDomainObjectProvider<Configuration> configuration) {
613615
def shellTask = tasks.register('shell', JavaExec)
614-
shellTask.configure {
615-
it.classpath = project.sourceSets.main.runtimeClasspath + configuration.get()
616-
it.mainClass.set('grails.ui.shell.GrailsShell')
617-
it.standardInput = System.in
616+
project.afterEvaluate {
617+
shellTask.configure {
618+
it.dependsOn(tasks.named('classes'), tasks.named('findMainClass', FindMainClassTask))
619+
it.classpath = project.sourceSets.main.runtimeClasspath + configuration.get()
620+
it.mainClass.set('grails.ui.shell.GrailsShell')
621+
it.standardInput = System.in
622+
623+
def appClass = GrailsGradlePlugin.getMainClassProvider(project)
624+
625+
it.doFirst {
626+
it.args(appClass.get())
627+
}
628+
}
618629
}
619630
shellTask
620631
}
@@ -629,6 +640,7 @@ class GrailsGradlePlugin extends GroovyPlugin {
629640
}
630641
}
631642

643+
@CompileDynamic
632644
protected void registerFindMainClassTask(Project project) {
633645
TaskContainer taskContainer = project.tasks
634646

@@ -644,77 +656,72 @@ class GrailsGradlePlugin extends GroovyPlugin {
644656
}
645657
}
646658

647-
// Set it on the extensions & spring boot extension "just" to be complete in case any other tasks use these values
648659
project.afterEvaluate {
649-
def extraProperties = project.extensions.getByType(ExtraPropertiesExtension)
650-
extraProperties.set('mainClassName', project.provider {
651-
if (extraProperties.has('mainClassName')) {
652-
return extraProperties.get('mainClassName')
653-
}
654-
655-
File cacheFile = findMainClassTask.get().mainClassCacheFile.orNull?.asFile
656-
if (!cacheFile.exists()) {
657-
return null
660+
// Support overrides - via mainClass property
661+
def propertyMainClassName = project.findProperty('mainClass')
662+
if(propertyMainClassName) {
663+
findMainClassTask.configure {
664+
it.mainClassName.set(propertyMainClassName)
658665
}
666+
}
659667

660-
cacheFile?.text
661-
})
662-
668+
// Support overrides - via mainClass springboot extension
663669
def springBootExtension = project.extensions.getByType(SpringBootExtension)
664-
springBootExtension.mainClass.set(project.provider {
665-
if (springBootExtension.mainClass.isPresent()) {
666-
return springBootExtension.mainClass.get() as String
670+
String springBootMainClassName = springBootExtension.mainClass.getOrNull()
671+
if(springBootMainClassName) {
672+
findMainClassTask.configure {
673+
it.mainClassName.set(springBootMainClassName)
667674
}
675+
}
668676

669-
File cacheFile = findMainClassTask.get().mainClassCacheFile.orNull?.asFile
670-
if (!cacheFile.exists()) {
671-
return null
677+
if(springBootMainClassName && propertyMainClassName) {
678+
if(springBootMainClassName != propertyMainClassName) {
679+
throw new GradleException("If overriding the mainClass, the property 'mainClass' and the springboot.mainClass must be set to the same value")
672680
}
681+
}
682+
683+
def extraProperties = project.extensions.getByType(ExtraPropertiesExtension)
684+
def overriddenMainClass = propertyMainClassName ?: springBootMainClassName
685+
if(!overriddenMainClass) {
686+
// the findMainClass task needs to set these values
687+
extraProperties.set('mainClassName', project.provider {
688+
File cacheFile = findMainClassTask.get().mainClassCacheFile.orNull?.asFile
689+
if (!cacheFile.exists()) {
690+
return null
691+
}
692+
693+
cacheFile?.text
694+
})
673695

674-
cacheFile?.text
675-
})
696+
springBootExtension.mainClass.set(project.provider {
697+
File cacheFile = findMainClassTask.get().mainClassCacheFile.orNull?.asFile
698+
if (!cacheFile.exists()) {
699+
return null
700+
}
701+
702+
cacheFile?.text
703+
})
704+
}
705+
else {
706+
// we need to set the overridden value on both
707+
extraProperties.set('mainClass', overriddenMainClass)
708+
springBootExtension.mainClass.set(overriddenMainClass)
709+
}
676710
}
677711

678712
project.tasks.withType(BootArchive).configureEach { BootArchive bootTask ->
679713
bootTask.dependsOn(findMainClassTask)
680-
bootTask.mainClass.convention(project.provider {
681-
File cacheFile = findMainClassTask.get().mainClassCacheFile.orNull?.asFile
682-
if (!cacheFile.exists()) {
683-
return null
684-
}
685-
686-
cacheFile?.text
687-
})
714+
bootTask.mainClass.convention(GrailsGradlePlugin.getMainClassProvider(project))
688715
}
689716

690717
project.tasks.withType(BootRun).configureEach { BootRun it ->
691718
it.dependsOn(findMainClassTask)
692-
it.mainClass.convention(project.provider {
693-
File cacheFile = findMainClassTask.get().mainClassCacheFile.orNull?.asFile
694-
if (!cacheFile.exists()) {
695-
return null
696-
}
697-
698-
cacheFile?.text
699-
})
719+
it.mainClass.convention(GrailsGradlePlugin.getMainClassProvider(project))
700720
}
701721

702722
project.tasks.withType(ResolveMainClassName).configureEach {
703723
it.dependsOn(findMainClassTask)
704-
705-
it.configuredMainClassName.set(project.provider {
706-
def springBootExtension = project.extensions.getByType(SpringBootExtension)
707-
if (springBootExtension.mainClass.isPresent()) {
708-
return springBootExtension.mainClass.get() as String
709-
}
710-
711-
File cacheFile = findMainClassTask.get().mainClassCacheFile.orNull?.asFile
712-
if (!cacheFile.exists()) {
713-
return null
714-
}
715-
716-
cacheFile?.text
717-
})
724+
it.configuredMainClassName.convention(GrailsGradlePlugin.getMainClassProvider(project))
718725
}
719726
} else if (!FindMainClassTask.class.isAssignableFrom(existingTask.class)) {
720727
project.logger.warn('Grails Projects typically register a findMainClass task to force the MainClass resolution for Spring Boot. This task already exists so this will not occur.')
@@ -797,13 +804,24 @@ class GrailsGradlePlugin extends GroovyPlugin {
797804
@CompileDynamic
798805
protected void configureRunScript(Project project) {
799806
if (!project.tasks.names.contains('runScript')) {
800-
project.tasks.register('runScript', ApplicationContextScriptTask).configure {
801-
SourceSet mainSourceSet = SourceSets.findMainSourceSet(project)
802-
it.classpath = mainSourceSet.runtimeClasspath + project.configurations.getByName('console')
803-
it.systemProperty Environment.KEY, System.getProperty(Environment.KEY, Environment.DEVELOPMENT.getName())
804-
def argsProperty = project.findProperty('args')
805-
if (argsProperty) {
806-
it.args(CommandLineParser.translateCommandline(argsProperty))
807+
def runTask = project.tasks.register('runScript', ApplicationContextScriptTask)
808+
project.afterEvaluate {
809+
runTask.configure {
810+
SourceSet mainSourceSet = SourceSets.findMainSourceSet(project)
811+
it.classpath = mainSourceSet.runtimeClasspath + project.configurations.getByName('console')
812+
it.systemProperty Environment.KEY, System.getProperty(Environment.KEY, Environment.DEVELOPMENT.getName())
813+
List<Object> args = []
814+
def otherArgs = project.findProperty('args')
815+
if (otherArgs) {
816+
args.addAll(CommandLineParser.translateCommandline(otherArgs as String))
817+
}
818+
819+
def appClassProvider = GrailsGradlePlugin.getMainClassProvider(project)
820+
821+
it.doFirst {
822+
args << appClassProvider.get()
823+
it.args(args)
824+
}
807825
}
808826
}
809827
}
@@ -812,13 +830,26 @@ class GrailsGradlePlugin extends GroovyPlugin {
812830
@CompileDynamic
813831
protected void configureRunCommand(Project project) {
814832
if (!project.tasks.names.contains('runCommand')) {
815-
project.tasks.register('runCommand', ApplicationContextCommandTask).configure {
816-
SourceSet mainSourceSet = SourceSets.findMainSourceSet(project)
817-
it.classpath = mainSourceSet.runtimeClasspath + project.configurations.getByName('console')
818-
it.systemProperty Environment.KEY, System.getProperty(Environment.KEY, Environment.DEVELOPMENT.getName())
819-
def argsProperty = project.findProperty('args')
820-
if (argsProperty) {
821-
it.args(CommandLineParser.translateCommandline(argsProperty))
833+
def runTask = project.tasks.register('runCommand', ApplicationContextCommandTask)
834+
project.afterEvaluate {
835+
runTask.configure {
836+
SourceSet mainSourceSet = SourceSets.findMainSourceSet(project)
837+
it.classpath = mainSourceSet.runtimeClasspath + project.configurations.getByName('console')
838+
it.systemProperty Environment.KEY, System.getProperty(Environment.KEY, Environment.DEVELOPMENT.getName())
839+
840+
List<Object> args = []
841+
def otherArgs = project.findProperty('args')
842+
if (otherArgs) {
843+
args.addAll(CommandLineParser.translateCommandline(otherArgs as String))
844+
}
845+
846+
def appClassProvider = GrailsGradlePlugin.getMainClassProvider(project)
847+
848+
it.doFirst {
849+
args << appClassProvider.get()
850+
it.args(args)
851+
}
852+
822853
}
823854
}
824855
}

grails-gradle/tasks/src/main/groovy/org/grails/gradle/plugin/run/FindMainClassTask.groovy

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import org.gradle.api.provider.Property
2929
import org.gradle.api.tasks.CacheableTask
3030
import org.gradle.api.tasks.Input
3131
import org.gradle.api.tasks.InputFiles
32+
import org.gradle.api.tasks.Optional
3233
import org.gradle.api.tasks.OutputFile
3334
import org.gradle.api.tasks.PathSensitive
3435
import org.gradle.api.tasks.PathSensitivity
@@ -59,6 +60,13 @@ abstract class FindMainClassTask extends DefaultTask {
5960
@OutputFile
6061
final RegularFileProperty mainClassCacheFile
6162

63+
/**
64+
* allows forcing the main class name & ensures this task retriggers to save to the cache file if overridden
65+
*/
66+
@Input
67+
@Optional
68+
final Property<String> mainClassName
69+
6270
@Input
6371
final Property<Boolean> isGrailsPlugin
6472

@@ -100,6 +108,7 @@ abstract class FindMainClassTask extends DefaultTask {
100108
Task bootWarTask = project.tasks.findByName(SpringBootPlugin.BOOT_WAR_TASK_NAME)
101109
(bootWarTask && bootWarTask.enabled) as boolean
102110
})
111+
mainClassName = objects.property(String)
103112
}
104113

105114
@TaskAction
@@ -114,6 +123,15 @@ abstract class FindMainClassTask extends DefaultTask {
114123
return
115124
}
116125

126+
if(mainClassName.isPresent()) {
127+
def overrideClassName = mainClassName.get()
128+
logger.info("Overriding main class with: ${ overrideClassName}")
129+
File cacheFile = mainClassCacheFile.get().asFile
130+
cacheFile.parentFile.mkdirs()
131+
cacheFile.text = overrideClassName
132+
return
133+
}
134+
117135
MainClassHolder mainClassHolder = findMainClass()
118136
if (mainClassHolder) {
119137
File cacheFile = mainClassCacheFile.get().asFile

0 commit comments

Comments
 (0)