Skip to content

Commit 54b0808

Browse files
authored
Merge pull request #14833 from jdaugherty/7.0.x
#14832 - support findMainTask caching with plugins & boot tasks in the task graph
2 parents f233361 + 9c6d935 commit 54b0808

3 files changed

Lines changed: 41 additions & 23 deletions

File tree

grails-gradle/model/src/main/groovy/org/grails/io/support/MainClassFinder.groovy

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,23 @@ class MainClassFinder {
5151
* Searches for the main class relative to the give path that is within the project tree
5252
*
5353
* @param path The path as a URI
54+
* @param supportCaching Whether to cache the result for future calls
5455
* @return The name of the main class
5556
*/
56-
static String searchMainClass(URI path) {
57+
static String searchMainClass(URI path, boolean supportCaching = true) {
5758
if (!path) {
5859
return null
5960
}
6061

6162
def pathStr = path.toString()
62-
if (mainClasses.containsKey(pathStr)) {
63-
return mainClasses.get(pathStr).className
63+
if (supportCaching && mainClasses.containsKey(pathStr)) {
64+
def holder = mainClasses.get(pathStr)
65+
if(holder.classFile.exists()) {
66+
return holder.className
67+
}
68+
else {
69+
mainClasses.remove(pathStr)
70+
}
6471
}
6572

6673
try {
@@ -89,11 +96,11 @@ class MainClassFinder {
8996

9097
MainClassHolder holder = null
9198
for (File dir in searchDirs) {
92-
holder = findMainClass(dir)
99+
holder = findMainClass(dir, supportCaching)
93100
if (holder) break
94101
}
95102

96-
if (holder != null) {
103+
if (supportCaching && holder != null) {
97104
mainClasses.put(pathStr, holder)
98105
}
99106

@@ -118,7 +125,7 @@ class MainClassFinder {
118125
return null
119126
}
120127

121-
static MainClassHolder findMainClass(File rootFolder = BuildSettings.CLASSES_DIR) {
128+
static MainClassHolder findMainClass(File rootFolder = BuildSettings.CLASSES_DIR, boolean supportCaching = true) {
122129
if (rootFolder == null) {
123130
// try current directory
124131
rootFolder = new File(ROOT_FOLDER_PATH)
@@ -133,8 +140,11 @@ class MainClassFinder {
133140
}
134141

135142
final String rootFolderCanonicalPath = rootFolder.canonicalPath
136-
if (mainClasses.containsKey(rootFolderCanonicalPath)) {
137-
return mainClasses.get(rootFolderCanonicalPath)
143+
if (supportCaching && mainClasses.containsKey(rootFolderCanonicalPath)) {
144+
def holder = mainClasses.get(rootFolderCanonicalPath)
145+
if(holder.classFile.exists()) {
146+
return holder
147+
}
138148
}
139149
ArrayDeque<File> stack = new ArrayDeque<>()
140150
stack.push rootFolder
@@ -150,7 +160,9 @@ class MainClassFinder {
150160
holder.className = classReader.getClassName().replace('/', '.').replace('\\', '.')
151161
holder.classFile = file
152162

153-
mainClasses.put(rootFolderCanonicalPath, holder)
163+
if(supportCaching) {
164+
mainClasses.put(rootFolderCanonicalPath, holder)
165+
}
154166

155167
return holder
156168
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,8 @@ class GrailsGradlePlugin extends GroovyPlugin {
651651
def mainClassFileContainer = project.layout.buildDirectory.file('resolvedMainClassName')
652652
TaskProvider<FindMainClassTask> findMainClassTask = project.tasks.register('findMainClass', FindMainClassTask)
653653
findMainClassTask.configure {
654-
it.mustRunAfter(project.tasks.withType(GroovyCompile))
654+
it.dependsOn(project.tasks.named('compileGroovy', GroovyCompile), project.tasks.named('classes'))
655+
it.mustRunAfter(project.tasks.named('classes'))
655656
it.mainClassCacheFile.set(mainClassFileContainer)
656657
it.outputs.upToDateWhen {
657658
mainClassFileContainer.orNull?.asFile?.exists()

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

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ import groovy.transform.CompileStatic
2222
import org.gradle.api.DefaultTask
2323
import org.gradle.api.Project
2424
import org.gradle.api.Task
25+
import org.gradle.api.file.ConfigurableFileCollection
2526
import org.gradle.api.file.FileCollection
2627
import org.gradle.api.file.RegularFileProperty
2728
import org.gradle.api.model.ObjectFactory
2829
import org.gradle.api.provider.Property
2930
import org.gradle.api.tasks.CacheableTask
31+
import org.gradle.api.tasks.Classpath
3032
import org.gradle.api.tasks.Input
3133
import org.gradle.api.tasks.InputFiles
3234
import org.gradle.api.tasks.Optional
@@ -98,45 +100,46 @@ abstract class FindMainClassTask extends DefaultTask {
98100
})
99101
enabledBootRunTask = objects.property(Boolean).convention(project.provider {
100102
Task bootRunTask = project.tasks.findByName('bootRun')
101-
(bootRunTask && bootRunTask.enabled) as boolean
103+
(bootRunTask && bootRunTask.enabled && project.gradle.taskGraph.hasTask(bootRunTask)) as boolean
102104
})
103105
enabledBootJarTask = objects.property(Boolean).convention(project.provider {
104106
Task bootJarTask = project.tasks.findByName(SpringBootPlugin.BOOT_JAR_TASK_NAME)
105-
(bootJarTask && bootJarTask.enabled) as boolean
107+
(bootJarTask && bootJarTask.enabled && project.gradle.taskGraph.hasTask(bootJarTask)) as boolean
106108
})
107109
enabledBootWarTask = objects.property(Boolean).convention(project.provider {
108110
Task bootWarTask = project.tasks.findByName(SpringBootPlugin.BOOT_WAR_TASK_NAME)
109-
(bootWarTask && bootWarTask.enabled) as boolean
111+
(bootWarTask && bootWarTask.enabled && project.gradle.taskGraph.hasTask(bootWarTask)) as boolean
110112
})
111113
mainClassName = objects.property(String)
112114
}
113115

114116
@TaskAction
115117
void setMainClassProperty() {
116-
if (!enabledBootRunTask.get()) {
117-
logger.info('The bootRun task does not exist or is disabled, so this must not be a runnable grails application. Skipping finding main class.')
118-
return
118+
File cacheFile = mainClassCacheFile.get().asFile
119+
if(cacheFile.exists()) {
120+
// the only time this task should invoke is when gradle has deemed it necessary to run, always remove the
121+
// the cache file to prevent invalid states when running tasks other than bootRun, bootJar, or bootWar
122+
cacheFile.delete()
119123
}
120124

121-
if (!enabledBootJarTask.get() && !enabledBootWarTask.get()) {
122-
logger.info('There is neither a {} or {} task that will run. Skipping finding main Application class.', SpringBootPlugin.BOOT_JAR_TASK_NAME, SpringBootPlugin.BOOT_WAR_TASK_NAME)
125+
if (!enabledBootRunTask.get() && !enabledBootJarTask.get() && !enabledBootWarTask.get()) {
126+
logger.info('No Spring Boot tasks were found that will run ({}, {}, or {}). Skipping finding main Application class.', 'bootRun', SpringBootPlugin.BOOT_JAR_TASK_NAME, SpringBootPlugin.BOOT_WAR_TASK_NAME)
123127
return
124128
}
125129

126130
if (mainClassName.isPresent()) {
127131
def overrideClassName = mainClassName.get()
128132
logger.info('Overriding main class with: {}', overrideClassName)
129-
File cacheFile = mainClassCacheFile.get().asFile
130133
cacheFile.parentFile.mkdirs()
131134
cacheFile.text = overrideClassName
132135
return
133136
}
134137

135138
MainClassHolder mainClassHolder = findMainClass()
136139
if (mainClassHolder) {
137-
File cacheFile = mainClassCacheFile.get().asFile
138140
cacheFile.parentFile.mkdirs()
139141
cacheFile.text = mainClassHolder.className
142+
logger.info('Found main class: {}', mainClassHolder.className)
140143
} else if (!isGrailsPlugin.get()) {
141144
logger.warn('No main class found. Please set \'springBoot.mainClass\'.')
142145
}
@@ -152,20 +155,22 @@ abstract class FindMainClassTask extends DefaultTask {
152155
}
153156
MainClassHolder mainClassHolder = null
154157
for (File classesDir in classesDirs) {
155-
mainClassHolder = mainClassFinder.findMainClass(classesDir)
158+
logger.debug("Searching for main class in: {}", classesDir.absolutePath)
159+
mainClassHolder = mainClassFinder.findMainClass(classesDir, false) // do not cache inside of the finder since gradle is responsible for caching
156160
if (mainClassHolder) {
161+
logger.debug("Found main class: {} at {}", mainClassHolder.className, mainClassHolder.classFile.absolutePath)
157162
break
158163
}
159164
}
160165

161166
if (!mainClassHolder) {
162167
if (isGrailsPlugin.get()) {
163168
// this is ok if the project is a plugin because it's likely not going to be a runnable grails app
164-
logger.lifecycle('WARNING: this plugin project does not have an Application.class and thus the bootJar / bootRun will be invalid.')
169+
logger.lifecycle('WARNING: this plugin project does not have an Application.class and thus the bootJar / bootWar / bootRun will be invalid.')
165170
return null
166171
}
167172

168-
throw new RuntimeException('Could not find Application main class. Please set \'springBoot.mainClass\' or disable BootJar & BootArchive tasks.')
173+
throw new RuntimeException('Could not find Application main class. Please set \'springBoot.mainClass\' or disable bootRun & bootArchive (bootJar / bootWar) tasks.')
169174
}
170175

171176
return mainClassHolder

0 commit comments

Comments
 (0)