Tanish Ranjan
07/27/2024, 6:37 AMimplementation 'com.android.tools.build:gradle-api:8.5.1'
Which provided me with all the needed classes after the build. But at runtime I get ClassNotFoundException for the classes introduced by this dependency.
Can someone help me figure out what might be the reason for it?Vampire
07/27/2024, 8:58 AMTanish Ranjan
07/27/2024, 9:11 AMgoogle() to repositories in the root project build.gradle. It fetched the dependencies, build was successful, my IDE was able to recognize the dependency as well. When I used any class from the dependency such as AndroidBasePlugin or ApplicationExtension they would result in the ClassNotFoundException at runtime. Funny thing about it, when I add a breakpoijt right before any of these classes are used and try to the debug expression it would give me results perfectly, but then if I proceed, bam! ClassNotFound.Vampire
07/27/2024, 9:21 AMtoString() of the classloader of the class trying to use that other class,
and what is the toString() of the classloader of the class it tries to use which you said you can get in the debugger?Tanish Ranjan
07/27/2024, 9:33 AMSo you are building a Gradle plugin right?Yes to be used by the tooling api in the other module.
what is theI am not sure what you mean by this. How do I get the classLoader?of the classloader of the class trying to use that other classtoString()
Tanish Ranjan
07/27/2024, 9:35 AMpublic static boolean isAndroidProject(Project project) {
return findExtension(AndroidBasePlugin.class, project) != null;
}
It would throw the exception before findExtension is even called. Just mentioning AndroidBasePlugin.class causes the exception. Although I can put a breakpoint on the return statement and then evaluate the same expression successfully.Vampire
07/27/2024, 9:55 AMHow do I get the classLoader?
AndroidBasePlugin.class.getClassLoader()Vampire
07/27/2024, 9:55 AMVampire
07/27/2024, 9:56 AMVampire
07/27/2024, 9:56 AMVampire
07/27/2024, 9:56 AMTanish Ranjan
07/27/2024, 10:00 AMAndroidBasePlugin.class.getClassLoader() resulted in the following:
"InstrumentingVisitableURLClassLoader(ClassLoaderScopeIdentifier.Id{coreAndPlugins:settings[:]:buildSrc[:]:root-project[:](export)})"Vampire
07/27/2024, 10:01 AMTanish Ranjan
07/27/2024, 10:05 AMIt introduces an ordering requirement between your plugin and the android plugin, in that it only works as intended if you apply your plugin after the android plugin, not beforeJust to be on the same page. My plugin is a custom plugin to work with the tooling api. This snippet I shared is being used in my plugin for building a custom model. It is supposed to check if the user's project for which we are trying to build a model is an android project. Any articles you might share to help me find more about the issue and how to address them? 🙂
Tanish Ranjan
07/27/2024, 10:06 AMAnd for the class where it is used?
InstrumentingVisitableURLClassLoader(ClassLoaderScopeIdentifier.Id{coreAndPlugins:init-file:/D:/Tanish%20Ranjan/Development/Languages/Java/build-server-for-gradle/server/build/libs/plugins/init.gradle(export)})Vampire
07/27/2024, 10:07 AMMy plugin is a custom plugin to work with the tooling api. This snippet I shared is being used in my plugin for building a custom model.Uhm, ok, well, if it is not for "normal" usage and you ensure it is applied after the android plugin it might be ok.
Vampire
07/27/2024, 10:08 AMAnd for the class where it is used?There you have it, your plugin class is in the init script class loader. The android plugin class is in the root project class loader. So your plugin class cannot see the android class.
Tanish Ranjan
07/27/2024, 10:11 AMVampire
07/27/2024, 10:13 AMVampire
07/27/2024, 10:17 AMVampire
07/27/2024, 10:18 AMVampire
07/27/2024, 10:18 AMVampire
07/27/2024, 10:18 AMfalseVampire
07/27/2024, 10:20 AMTanish Ranjan
07/27/2024, 10:29 AMpublic static boolean isAndroidProject(Project project) {
return findExtension(AndroidBasePlugin.class, project) != null;
}
public static List<AndroidSourceSet> getAndroidSourceSets(Project project) {
ApplicationExtension appExtension = findExtension(ApplicationExtension.class, project);
if (appExtension != null) {
return new LinkedList<>(appExtension.getSourceSets());
}
LibraryExtension libExtension = findExtension(LibraryExtension.class, project);
if (libExtension != null) {
return new LinkedList<>(libExtension.getSourceSets());
}
return new LinkedList<>();
}
public static <T> T findExtension(Class<T> clazz, Project project) {
// Get from extensions if supported
if (GradleVersion.current().compareTo(GradleVersion.version("5.0")) >= 0) {
T extension = project.getExtensions().findByType(clazz);
if (extension != null) {
return extension;
}
}
// Fallback
T extension = project.getConvention().findByType(clazz);
if (extension != null) {
return extension;
}
return null;
}Tanish Ranjan
07/27/2024, 10:32 AMtask generateInitScript() {
doLast {
def initScript = file("$buildDir/libs/plugins/init.gradle")
initScript.parentFile.mkdirs()
initScript.write """
initscript {
dependencies {
classpath files('plugin.jar')
}
}
allprojects {
apply plugin: com.microsoft.java.bs.gradle.plugin.GradleBuildServerPlugin
}
"""
}
}
processResources {
dependsOn(':plugin:copyJar')
dependsOn copyRuntimeLibs
dependsOn(':server:generateInitScript')
duplicatesStrategy = 'include'
exclude 'NOTICE.txt'
}
Invocation part:
BuildActionExecuter<GradleSourceSets> buildExecutor =
Utils.getBuildActionExecuter(connection, preferenceManager.getPreferences(),
new GetSourceSetsAction());
buildExecutor.addProgressListener(reporter,
OperationType.FILE_DOWNLOAD, OperationType.PROJECT_CONFIGURATION)
.setStandardError(errorOut)
.addArguments("--init-script", initScript.getAbsolutePath());Vampire
07/27/2024, 10:39 AMBtw this is how the init script is being used in the build.gradle file from the server module where we use the plugin for the tooling api:Well, you explicitly only add the plugin jar to the classpath, so of course the dependency is not there.
Vampire
07/27/2024, 10:41 AMVampire
07/27/2024, 10:41 AMVampire
07/27/2024, 10:42 AMTanish Ranjan
07/27/2024, 10:51 AM