Having two Projects:
Id like to have the Advanced to have all classes the Classic
have. But as I run Advanced/gradle bootRun
all the Advanced
classes seems to be missing.
Advanced/src/main/java/foo/Bar.java:
package foo;
public class Bar{
//empty
}
Classic/src/main/java/foo/Classic.java:
package foo;
public class Classic {
public static void main(){
try {
Class.forName("foo.Bar");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Exception:
java.lang.ClassNotFoundException: foo.Bar
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:340)
at foo.Classic.main(Classic.java:14)
java.lang.ClassNotFoundException: foo.Bar
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:144)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:340)
at foo.Classic.main(Classic.java:14)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
I have this in my Advanced/build.gradle:
...
dependencies{
...
implementation project(':classic')
...
}
...
Jacob G.
I talked for awhile with OP in one of the chat rooms, and I've discovered a few things. When attempting to build the Advanced project with Gradle, it reports 50+ compilations errors regarding package not found:, referring to packages in the Classic project. Also, Classic and Advanced do not share a root project, so I have a feeling that attempting to depend on project(':classic') is futile. OP stated that commits can only be made to Advanced, so it may not be possible to fix the issue at all. For anyone curious, OP is also not using an IDE.
I made an edit to the question, I added an limitation. It was an very important edit that I can only commit changes in Advanced. Because of the fact that I have no experience in gradle I was not aware of the imporance of this additional information. I feel sorry for the late limitation, feel comfort for the courtesy and hope for understanding.
The Spring Boot gradle plugin provides the bootRun task that allows a developer to start the application in a “developer mode” without first building a JAR file and then starting this JAR file. Thus, it's a quick way to test the latest changes you made to the codebase.
Introduction. The Spring Boot Gradle Plugin provides Spring Boot support in Gradle. It allows you to package executable jar or war archives, run Spring Boot applications, and use the dependency management provided by spring-boot-dependencies . Spring Boot's Gradle plugin requires Gradle 6.8, 6.9, or 7.
If we're using the Spring Boot Gradle plugin, there are a few configurations inherited from org.springframework.boot where we could specify our main class. In the project's Gradle file, mainClassName can be defined within springBoot configuration block. This change made here is picked up by bootRun and bootJar task:
The gradle plugin extends our build script’s DSL with elements from our spring boot plugin’s spring boot settings. Set the appropriate properties of the spring boot plugin is very important.
For example, let's set the main class by using the mainClassName property: Alternatively, we can use use the same property from the Spring Boot DSL: 3.2. Spring Boot 1.x With Spring Boot 1.x, bootRepackage is responsible for creating the executable archive (jar or war file depending on the configuration.
The bootRun task can be simply configured in build.gradle. For example, we can define the main class: 5. Relation With Other Plugins 5.1. Dependency Management Plugin For Spring Boot 1.x, it used to apply the dependency management plugin automatically.
As far as I could understand from the question we are dealing with a multiple project scenario. In this case the multi project builds documentation tells us that it is necessary to have a settings.gradle in the folder that contains the two projects:
then it is possible to run both the projects without cd
change directory into the specific folder , but directly from the multi-project root by command: gradle advanced:bootRun
Advanced
project.we can still get a solution but in this scenario ( actually not a gradle multi-project)
no need to have a settings.gradle
at the parent directory level of Advanced
; it satisfy the requirement of not being able to commit outside of Advanced
it doesn't matter how it's built the Classic
project, we don't care about it since we can't commit on it
we can't use in Advanced/build.gradle
the implementation project(':classic')
as dependency since this works only in real gradle multi-project scenarios ; in here we must use a file dependency or another type of dependecy available for the user's development environment.
In this case it is possible to run the Advanced project by cd Advanced
then , from the Advanced directory run th command: gradle bootRun
..In order to better understand how it works lets's inspect the
SystemClassLoader
's current paths by adding this lines of code in Advanced/src/main/java/com/example/springboot/Application.java
ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url: urls){
System.out.println(url.getFile());
}
the output is:
<multi-project-root>/Advanced/build/classes/java/main/
<multi-project-root>/Advanced/build/resources/main/
<multi-project-root>/Classic/build/libs/Classic-0.0.1-SNAPSHOT.jar
~/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring
... [suppressed many othe spring devtools and gradle related caches ]
this allow both the Advanced and the Classic classes to find each others
The POC source-code new branch has been updated accordingly
What you need is Gradle's composite build. See my POC project. The advanced project includes the classic project by this line
The advanced/App.java calls classic.App.main, And the classic.App class can load foo.Bar from the advanced project. No need to do a commit to classic project.
Execute "gradlew run" in the advanced folder
to see how it works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With