to test some features of spring-boot-devtools
, I created a spring boot app using spring boot 1.5.3.RELEASE
from Spring Initializr, before writing anything I ran this app, but lines of red error message showed up:
it seemed that something is wrong with this fresh app, so I checked my pom file and tried to find the dependencies mentioned in the error message, with the help of IDEA I generated a maven diagram:
jaxb-api
was transitively introduced by a dependency mssql-jdbc
added by Spring Initializr, but the error message says that
D:.m2\repository\com\sunxmlbind\jaxb-impl\2.2.3-1\jaxb-api.jar does not exist
apparently the groupId of jaxb-api.jar
is wrong, to figure out what happened, I spent some time debugging spring-boot-devtools
, and traced the source of above mentioned error message, here is what happened:
private static List<URL> getUrlsFromManifestClassPathAttribute(JarFile jarFile)
throws IOException {
Manifest manifest = jarFile.getManifest();
if (manifest == null) {
return Collections.<URL>emptyList();
}
String classPath = manifest.getMainAttributes()
.getValue(Attributes.Name.CLASS_PATH);
if (!StringUtils.hasText(classPath)) {
return Collections.emptyList();
}
String[] entries = StringUtils.delimitedListToStringArray(classPath, " ");
List<URL> urls = new ArrayList<>(entries.length);
File parent = new File(jarFile.getName()).getParentFile();
for (String entry : entries) {
try {
File referenced = new File(parent, entry);
if (referenced.exists()) {
urls.add(referenced.toURI().toURL());
}
else {
System.err.println("Ignoring Class-Path entry " + entry + " found in "
+ jarFile.getName() + " as " + referenced
+ " does not exist");
}
}
catch (MalformedURLException ex) {
throw new IllegalStateException(
"Class-Path attribute contains malformed URL", ex);
}
}
return urls;
}
devtools reads MANIFEST.MF
from jaxb-impl-2.2.3.jar
and extracts the Class-Path
attribute from it, then split the content of Class-Path
into entries each of which then used to build corresponding URL, the content of MANIFEST.MF
is pasted below:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 1.5.0_22-b03 (Sun Microsystems Inc.)
Specification-Title: Java Architecture for XML Binding
Specification-Version: 2.2.2
Specification-Vendor: Oracle Corporation
Implementation-Title: JAXB Reference Implementation
Implementation-Version: 2.2.3
Implementation-Vendor: Oracle Corporation
Implementation-Vendor-Id: com.sun
Extension-Name: com.sun.xml.bind
Build-Id: hudson-jaxb-ri-2.2.3-3
Class-Path: jaxb-api.jar activation.jar jsr173_1.0_api.jar jaxb1-impl.
jar
Name: com.sun.xml.bind.v2.runtime
Implementation-Version: 2.2.3-hudson-jaxb-ri-2.2.3-3-
according to the logic of method getUrlsFromManifestClassPathAttribute
, devtools tries to find jaxb-api.jar
from the same directory where jaxb-impl-2.2.3.jar
resides, but the correct groupId of jaxb-api
is javax.xml.bind
.
I also tried downgrading the version of spring boot from 1.5.3.RELEASE
to 1.5.2.RELEASE
, the error message disappeared, so I guess this is a bug of devtools ?
I checked the commits of org.springframework.boot.devtools.restart.ChangeableUrls
, and found a commit which seemed to be an update for devtools.
is this a bug ? that red error message is pretty annoying, so I'm looking for a way to disable that.
thx in advance.
@allbutone Please don't spam people by mentioning them in issues for no apparent reason. If people want to be notified of new issues they can opt in by watching the repository.
@wilkinsona sorry, I'm a beginner on github, still learning new stuff, and don't know well about the rules. I'll fix that. thanks for your suggestion
devtools tries to find jaxb-api.jar from the same directory where jaxb-impl-2.2.3.jar resides, but the correct groupId of jaxb-api is javax.xml.bind.
The group ID isn't relevant here. A Class-Path
entry in a jar's manifest knows nothing of Maven or it's directory layout. The Class-Path
manifest entry is a space-separated list of file system paths to other jars that should be added to the class path. Those paths are relative to the jar that contains the manifest with the Class-Path
entry.
The manifest for jaxb-impl-2.2.3.jar
is, arguably, a bit broken. It lists four jars, yet does nothing to ensure that they exist. That means that the class path is not precisely defined and can vary depending on whether or not a jar with a particular name exists alongside the jaxb-impl-2.2.3.jar
. The error message is warning you that a jar that one of your application's dependencies is looking for does not exist.
Unfortunately, we can't use logging to reliably report this warning as ChangeableUrls
is called very early and, crucially, before the logging system is initialized. That's ok if you're using Logback as it logs debug messages and higher by default, but if you're using Log4j2 you won't see anything as it log nothing by default.
That leaves us with 3 choices:
3 feels overly complex, so we're left with 1 or 2.
I also met the same problem,Looking forward to solve the problem
Thinking about it a little more, there's a fourth option: switch to System.out. I think that's the best compromise here.
This is a development tool so it doesn't strike me as a big deal that we have some log output there. Perhaps System.out
feels more appropriate for this.
Most helpful comment
The group ID isn't relevant here. A
Class-Path
entry in a jar's manifest knows nothing of Maven or it's directory layout. TheClass-Path
manifest entry is a space-separated list of file system paths to other jars that should be added to the class path. Those paths are relative to the jar that contains the manifest with theClass-Path
entry.The manifest for
jaxb-impl-2.2.3.jar
is, arguably, a bit broken. It lists four jars, yet does nothing to ensure that they exist. That means that the class path is not precisely defined and can vary depending on whether or not a jar with a particular name exists alongside thejaxb-impl-2.2.3.jar
. The error message is warning you that a jar that one of your application's dependencies is looking for does not exist.Unfortunately, we can't use logging to reliably report this warning as
ChangeableUrls
is called very early and, crucially, before the logging system is initialized. That's ok if you're using Logback as it logs debug messages and higher by default, but if you're using Log4j2 you won't see anything as it log nothing by default.That leaves us with 3 choices:
3 feels overly complex, so we're left with 1 or 2.