To avoid duplicate JAR resources on MS Windows.
If you use mybatis-plus
and your mapper-locations
starts with classpath*:
, Spring will find duplicate UrlResource
s for XML files which results in a crash on application startup.
Since their getCleanedUrl
values are different mybatis will throw an exception, even though they represent the same resource.
Comment From: pivotal-cla
@huyachigege Please sign the Contributor License Agreement!
Click here to manually synchronize the status of this Pull Request.
See the FAQ for frequently asked questions.
Comment From: pivotal-cla
@huyachigege Thank you for signing the Contributor License Agreement!
Comment From: huyachigege
ClassLoader.getResources("")
will generate a path like jar:file:/F:xyz.xml
; whereas, addClassPathManifestEntries()
will generate a path like jar:file:F:xyz.xml
.
They reference the same underlying resource, but UrlResource.getCleanedUrl()
is different for each of them, so you get duplicate UrlResource
s returned from PathMatchingResourcePatternResolver.getResources(location)
.
My English is not good, I hope you can understand.
Comment From: sbrannen
Hi @huyachigege,
Congratulations on creating your first PR ever! 👍
We'll look into it.
My English is not good, I hope you can understand.
Yes, your explanation is good enough to follow.
I edited the text to make it slightly clearer, and hopefully I didn't change the meaning you wished to convey.
Comment From: huyachigege
Hi @huyachigege,
Congratulations on creating your first PR ever! 👍
We'll look into it.
My English is not good, I hope you can understand.
Yes, your explanation is good enough to follow.
I edited the text to make it slightly clearer, and hopefully I didn't change the meaning you wished to convey.
Thanks, that is what I mean.
Comment From: jhoeller
addClassPathManifestEntries
delegates to hasDuplicate
before adding a new entry, and that method is meant to detect exactly such a difference in leading slashes. Could you try to find out why this is not correctly identifying the duplicate in your scenario?
Comment From: huyachigege
addClassPathManifestEntries
delegates tohasDuplicate
before adding a new entry, and that method is meant to detect exactly such a difference in leading slashes. Could you try to find out why this is not correctly identifying the duplicate in your scenario?
line 497 will get root resources, it will contain jar:file:/F:xxx/app.jar!/boot-info/classes
and jar:file:F:xxx/app.jar!
. They are different now. But child of them will be jar:file:/F:xxx/app.jar!/.../xxx.xml
and jar:file:F:xxx/app.jar!/.../xxx.xml
. They are duplicate on windows. If on Linux, they are both jar:file:/...
, so it works on Linux.
You can try on windows and use properties I just told.
Comment From: sbrannen
Hi @huyachigege,
line 497 will get root resources,
That doesn't map to the current code on the main
branch.
With which version of Spring Framework are you experiencing the duplicates?
Comment From: huyachigege
With which version of Spring Framework are you experiencing the duplicates?
5.3.x,sorry for that
Now is 23 clock in china,I need to go to bed. If there are any questions,I will reply tomorrow
Comment From: sbrannen
Related Issues
-
20539
-
20665
Comment From: sbrannen
If you use
mybatis-plus
and yourmapper-locations
starts withclasspath*:
Can you please provide us the exact location pattern you are using?
Specifically, what do you have for <???>
in classpath*:<???>
?
Comment From: huyachigege
If you use
mybatis-plus
and yourmapper-locations
starts withclasspath*:
Can you please provide us the exact location pattern you are using?
Specifically, what do you have for
<???>
inclasspath*:<???>
?
classpath*:/**/*_MYSQL.xml
Comment From: sbrannen
classpath://_MYSQL.xml
Thanks. That helps.
Can you please tell us which version of Java and Spring Boot you're using as well?
Comment From: huyachigege
classpath://_MYSQL.xml
Thanks. That helps.
Can you please tell us which version of Java and Spring Boot you're using as well?
OpenJDK-11,SpringBoot 2.6.12.
Comment From: sbrannen
line 497 will get root resources, it will contain
jar:file:/F:xxx/app.jar!/boot-info/classes
andjar:file:F:xxx/app.jar!
. They are different now. But child of them will bejar:file:/F:xxx/app.jar!/.../xxx.xml
andjar:file:F:xxx/app.jar!/.../xxx.xml
. They are duplicate on windows. If on Linux, they are bothjar:file:/...
, so it works on Linux.
Based on that feedback, it appears that we are getting two different roots (rootDirUrl
values) for the same underlying JAR:
jar:file:F:xxx/app.jar!
-- for the actual Spring Boot application JARjar:file:/F:xxx/app.jar!/boot-info/classes
-- from the MANIFEST of the Spring Boot application JAR
Then, in findPathMatchingResources()
we add the results of doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern)
without checking for duplicates.
The hasDuplicate()
method Juergen mentioned is used at a lower level and therefore does not detect duplicates at this higher level.
Comment From: sbrannen
This has been merged into main
in d5874ab99ef62b3da8a9269aa526b43328e968a9, revised in e71117dcdf8c713b0a364d896ea2221183eac64b, and backported to 5.3.x
.
Thanks