(To assist with this question, I have github links at the bottom of this question)
I have (and am "starting with" the below gradle multiple module/project)
settings.gradle
rootProject.name = 'com.mycompany.myteam.myapp-rootProjectName'
include ':source:java:myapproot:myapp-toplayer-console-di-xml-one'
include ':source:java:myapproot:myapp-business-logic'
(maybe even a few that are purely .java/.class "code logic" libraries)
In the subproject:
':source:java:myapproot:myapp-toplayer-console-di-xml-one'
I have the typical Spring-Boot startup and a spring-bean setup using applicationContext.xml.
./source/java/myapproot/myapp-toplayer-console-di-xml-one/src/main/java/demo/SpringBootApplicationContextXmlConsoleApplication.java
--
./source/java/myapproot/myapp-toplayer-console-di-xml-one/src/main/resources/applicationContext.xml
./source/java/myapproot/myapp-toplayer-console-di-xml-one/src/main/resources/orch.one.di.xml
./source/java/myapproot/myapp-toplayer-console-di-xml-one/src/main/resources/clientporxy.one.di.xml
The contents of "applicationContext.xml" are below. Note, it has a "pointer" 'import' entries to some other.xml files.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="orch.one.di.xml"/>
<import resource="clientproxy.one.di.xml"/>
</beans>
Everything above works just fine. I've been doing the above approach for years and for many different projects.
============================================================
What I am trying to do is put the 2 "extra" *.di.xml files in another gradle module.
settings.gradle
rootProject.name = 'com.mycompany.myteam.myapp-rootProjectName'
include ':source:java:myapproot:myapp-toplayer-console-di-xml-one'
include ':source:java:myapproot:myapp-business-logic'
(new one below)
include ':source:java:myapproot:myapp-shared-resxex'
And I want to move the *.di.xml files to this different/new gradle-subproject/module. (':source:java:myapproot:myapp-shared-resxex' to be clear)
So now I have moved the two *.di.xml files.
File location is here: (under "resources")
./source/java/myapproot/myapp-shared-resxex/src/main/resources/orch.one.di.xml
./source/java/myapproot/myapp-shared-resxex/src/main/resources/clientproxy.one.di.xml
So now when I start the "main" application, I get errors like below (and I kinda expected these errors)
Caused by: java.io.FileNotFoundException:
./source/java/myapproot/myapp-toplayer-console-di-xml-one/build/resources/main/clientproxy.one.di.xml
(No such file or directory)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112)
at java.base/sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:86)
at java.base/sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:184)
at org.springframework.core.io.UrlResource.getInputStream(UrlResource.java:187)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:333)
I have "tried" (and worked through) things like these:
https://docs.gradle.org/current/userguide/cross_project_publications.html
Gradle: common resource dependency for multiple java projects
How module can use resources of another module using gradle multi-module
Like many days and many hours been trying to figure out the magic-sauce.
So, my "in general" question is
How can I get a spring bean.xml file to work from a different gradle-subproject/module?
I will show my latest attempt:
./source/java/myapproot/myapp-shared-resxex/build.gradle
configurations {
myCoolConfigurationName
}
task tryToPackageStuffForOtherSubprojectsTask(type: Jar) {
archiveClassifier
from sourceSets.main.resources
}
artifacts {
myCoolConfigurationName tryToPackageStuffForOtherSubprojectsTask
}
dependencies {
implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-domain')
implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-interfaces')
implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-concrete')
}
and then:
./source/java/myapproot/myapp-toplayer-console-di-xml-one/build.gradle
plugins {
id "application"
}
apply plugin : "java"
ext {
javaMainClass = "demo.SpringBootApplicationContextXmlConsoleApplication"
}
application {
mainClassName = javaMainClass
}
task myCustomPrintClasspathTask {
doLast {
configurations.runtimeClasspath.each { println 'helloThere->' + it }
}
}
dependencies {
//the below line, if left not-commented-out, will produce a warning : "Execution optimizations have been disabled for task"
implementation project(path: ':source:java:myapproot:myapp-shared-resxex', configuration: 'myCoolConfigurationName')
implementation(group: 'org.springframework.boot', name: 'spring-boot-starter', version: springBootVersion) {
exclude module: "logback-classic"
}
implementation(group: 'org.springframework.boot', name: 'spring-boot-autoconfigure', version: springBootVersion) {
exclude module: "logback-classic"
}
implementation project(":source:java:myapproot:myapp-shared-resxex")
implementation project(':source:java:myapproot:myapp-business-logic')
implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-domain')
implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-interfaces')
implementation project(':source:java:myapproot:clientproxies:myclientproxy-root:myclientproxy-concrete')
implementation group: 'org.apache.commons', name: 'commons-lang3', version: commonsLangVersion
implementation group: 'javax.inject', name: 'javax.inject', version: "${javaxInjectVersion}"
implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion
implementation group: 'org.slf4j', name: 'slf4j-simple', version: slf4jSimpleVersion
testImplementation group: 'junit', name: 'junit', version: junitVersion
testImplementation group: 'org.mockito', name: 'mockito-core', version: mockitoVersion
}
When I run (a clean build and then) the custom task:
$ ./gradlew clean build
$ ./gradlew myCustomPrintClasspathTask
I get the below output:
> Task :source:java:myapproot:myapp-toplayer-console-di-xml-one:myCustomPrintClasspathTask
helloThere->./source/java/myapproot/myapp-shared-resxex/build/libs/myapp-shared-resxex.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter/2.7.5/c28e1546461803490588085345ba5d2897d232bc/spring-boot-starter-2.7.5.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-autoconfigure/2.7.5/96646e63a2296d0a3209383e81cdb8c87ab2f913/spring-boot-autoconfigure-2.7.5.jar
helloThere->./source/java/myapproot/myapp-business-logic/build/libs/myapp-business-logic.jar
helloThere->./source/java/myapproot/clientproxies/myclientproxy-root/myclientproxy-concrete/build/libs/myclientproxy-concrete.jar
helloThere->./source/java/myapproot/clientproxies/myclientproxy-root/myclientproxy-interfaces/build/libs/myclientproxy-interfaces.jar
helloThere->./source/java/myapproot/clientproxies/myclientproxy-root/myclientproxy-domain/build/libs/myclientproxy-domain.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.apache.commons/commons-lang3/3.12.0/c6842c86792ff03b9f1d1fe2aab8dc23aa6c6f0e/commons-lang3-3.12.0.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/javax.inject/javax.inject/1/6975da39a7040257bd51d21a231b76c915872d38/javax.inject-1.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-simple/1.7.36/a41f9cfe6faafb2eb83a1c7dd2d0dfd844e2a936/slf4j-simple-1.7.36.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-logging/2.7.5/61f4c53e35baa31a269bbeb7bb9d5e781448feef/spring-boot-starter-logging-2.7.5.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-to-slf4j/2.17.2/17dd0fae2747d9a28c67bc9534108823d2376b46/log4j-to-slf4j-2.17.2.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.slf4j/jul-to-slf4j/1.7.36/ed46d81cef9c412a88caef405b58f93a678ff2ca/jul-to-slf4j-1.7.36.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.36/6c62681a2f655b49963a5983b8b0950a6120ae14/slf4j-api-1.7.36.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot/2.7.5/fd04e228e6e21b7ad13c10ae29afd31868d842e5/spring-boot-2.7.5.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/jakarta.annotation/jakarta.annotation-api/1.3.5/59eb84ee0d616332ff44aba065f3888cf002cd2d/jakarta.annotation-api-1.3.5.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-context/5.3.23/530b36b2ce2c9e471c6a260c3f181bcd20325a58/spring-context-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aop/5.3.23/30d0034ba29178e98781d85f51a7eb709a628e9b/spring-aop-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/5.3.23/3bdefbf6042ed742cbe16f27d2d14cca9096a606/spring-beans-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-expression/5.3.23/3a676bf4b9bc42bd37ab5ad264acb6ceb63397a2/spring-expression-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/5.3.23/91407dc1106ea423c44150f3da1a0b4f8e25e5ca/spring-core-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.yaml/snakeyaml/1.30/8fde7fe2586328ac3c68db92045e1c8759125000/snakeyaml-1.30.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jcl/5.3.23/3c7eb5fcca67b611065f73ff4325e398f8b051a3/spring-jcl-5.3.23.jar
helloThere->/Users/MyDomainUserName/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.17.2/f42d6afa111b4dec5d2aea0fe2197240749a4ea6/log4j-api-2.17.2.jar
If I "peek" into the jar:
./source/java/myapproot/myapp-shared-resxex/build/libs/myapp-shared-resxex.jar
I do see the two *.di.xml files.
and then if I run:
$ ./gradlew run
I continue to get:
Caused by: java.io.FileNotFoundException: ./source/java/myapproot/myapp-toplayer-console-di-xml-one/build/resources/main/clientproxy.one.di.xml (No such file or directory)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112)
at java.base/sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:86)
at java.base/sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:184)
at org.springframework.core.io.UrlResource.getInputStream(UrlResource.java:187)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:333)
... 32 more
My./gradle/wrapper/gradle-wrapper.properties file (for completeness and to know my gradle-version)
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
.....
Github repo with the code.
https://github.com/granadacoder/gradle-multi-with-spring-bean-proof
"main" branch...has a working spring-bean di.xml setup. "main" branch relates to my comment above "everything above works just fine".
I have a second branch (and a PR so you can see the "diff").
branch:
and PR (from the feature branch to the main branch to show the "diff")
https://github.com/granadacoder/gradle-multi-with-spring-bean-proof/pull/2/files
Ok.
I found an "old" documentation page.
https://docs.spring.io/spring-framework/docs/3.0.0.M4/reference/html/ch04s07.html
I'll post the quote from the above URL, in case it "disappears".. especially since it is "old" documentation.
//START ARTICLE QUOTE
4.7.2.2 The classpath*: prefix When constructing an XML-based application context, a location string may use the special classpath*: prefix:
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml"); This special prefix specifies that all classpath resources that match the given name must be obtained (internally, this essentially happens via a ClassLoader.getResources(...) call), and then merged to form the final application context definition.
[Note] Classpath*: portability The wildcard classpath relies on the getResources() method of the underlying classloader. As most application servers nowadays supply their own classloader implementation, the behavior might differ especially when dealing with jar files. A simple test to check if classpath* works is to use the classloader to load a file from within a jar on the classpath: getClass().getClassLoader().getResources(""). Try this test with files that have the same name but are placed inside two different locations. In case an inappropriate result is returned, check the application server documentation for settings that might affect the classloader behavior.
The "classpath*:" prefix can also be combined with a PathMatcher pattern in the rest of the location path, for example "classpath*:META-INF/*-beans.xml". In this case, the resolution strategy is fairly simple: a ClassLoader.getResources() call is used on the last non-wildcard path segment to get all the matching resources in the class loader hierarchy, and then off each resource the same PathMatcher resoltion strategy described above is used for the wildcard subpath.
//END ARTICLE QUOTE
So I had forgotten about the "string-magic" of using classpath (before file-names, etc).
I was able to update my applicationContext.xml file to the below.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- below are "imports" to OTHER (spring-bean) di.xml files -->
<import resource="classpath:clientproxy.one.di.xml"/>
<import resource="classpath*:orchestrators.one.di.xml"/>
</beans>
You can read about the difference between using the "*" (after classpath) in the below SOF question/answers.
Spring classpath prefix difference
For clarity....all I did was "move" the two di.xml files to the "other" gradle/module-subproject. I did not use any of the "myCoolConfigurationName" stuff I showed in my original question... as one of my "tries".
"so simple"........I was happy and in disbelief with my days of struggle with this.....
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.