-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
10.0.1
-
x86_64
-
generic
ADDITIONAL SYSTEM INFORMATION :
Linux linux-xf9o 4.4.126-48-default #1 SMP Sat Apr 7 05:22:50 UTC 2018 (f24992c) x86_64 x86_64 x86_64 GNU/Linux
OpenSuSE leap 42.3
A DESCRIPTION OF THE PROBLEM :
<unsure if bug or missing feature>
Requiring the common jackson library (automatic module named in MANIFEST) via module-info leaves the developer open to runtime failures if requirements of those automatic modules (which do have module-info) are not correctly specified. In this case it's a automatic module (specified) using a jar (snakeyaml-1.18.jar which doesn't have a specified module name) which uses a jdk module. Jackson uses its manifest to give its jars specific module names, but doesn't yet have a module-info.java (probably due to breaking backwards compatibility)
<see steps to reproduce>
Given we can run jdeps and discover that java.sql is a requirement, shouldn't this be done during compilation and flagged as a compile time warning at least. Leaving it to be discovered (possibly by the end-user) at runtime seems very dangerous as it's not likely to be possible to cover off in tests all scenarios in third party modules. Even we say the developer running jdeps and adding to module-info.java first is best practice, it's possible that a module dependency could be accidentally missed or deleted and with enterprise apps with many dependencies this seems more likely. We could also argue 3rd party jar providers should upgrade, but given this is in something as fundamental as jackson, I'm not sure suggesting that jackson shouldn't be used just yet will go down too well. Having chosen module-info to be a .java file which breaks earlier versions of java is likely to mean this process will be much slower.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
<note I've manually renamed the package if there is a compile issue>
I've put together a simple test app:
(see source code)
Note I've commented out requirements that jdeps reports as depedencies of the jackson jars (which do not have module-info but given names via their manifests).
I compile:
javac -d out -p /home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.5/jackson-databind-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.5/jackson-core-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/dataformat/jackson-dataformat-yaml/2.9.5/jackson-dataformat-yaml-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/home/dav/.m2/repository/org/yaml/snakeyaml/1.18/snakeyaml-1.18.jar src/main/java/com/myname/utils/JsonToYaml.java src/main/java/module-info.java
Not even a warning(!)
I now run this:
java -p /home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.5/jackson-databind-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.5/jackson-core-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/dataformat/jackson-dataformat-yaml/2.9.5/jackson-dataformat-yaml-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/home/dav/.m2/repository/org/yaml/snakeyaml/1.18/snakeyaml-1.18.jar:out -m jsonToYaml/com.myname.utils.JsonToYaml
It's running okay
I enter some json via stdin:
{"hi":1}
and then:
Exception in thread "main" java.lang.NoClassDefFoundError: java/sql/Date
at snakeyaml@1.18/org.yaml.snakeyaml.nodes.Tag.<clinit>(Tag.java:64)
at com.fasterxml.jackson.dataformat.yaml@2.9.5/com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.<clinit>(YAMLGenerator.java:159)
at com.fasterxml.jackson.dataformat.yaml@2.9.5/com.fasterxml.jackson.dataformat.yaml.YAMLFactory._createGenerator(YAMLFactory.java:447)
at com.fasterxml.jackson.dataformat.yaml@2.9.5/com.fasterxml.jackson.dataformat.yaml.YAMLFactory.createGenerator(YAMLFactory.java:397)
at com.fasterxml.jackson.dataformat.yaml@2.9.5/com.fasterxml.jackson.dataformat.yaml.YAMLFactory.createGenerator(YAMLFactory.java:14)
at com.fasterxml.jackson.databind@2.9.5/com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3207)
at jsonToYaml/com.myname.utils.JsonToYaml.main(JsonToYaml.java:19)
Caused by: java.lang.ClassNotFoundException: java.sql.Date
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
... 7 more
Boom!
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Javac should check module-info dependencies that when a auto module is requested that any further dependencies are checked and either warned about, or access is granted to anything it needs (possible warning )
ACTUAL -
Classloader issue at runtime
---------- BEGIN SOURCE ----------
com.myname.utils.JsonToYaml.java:
package com.myname.utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import java.io.IOException;
public class JsonToYaml {
public static void main(String[] args) {
if (args.length != 0) {
System.out.println("No arguments expected, data read from stdin.");
System.exit(1);
}
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode nodeTree = mapper.readTree(System.in);
String yaml = new YAMLMapper().writeValueAsString(nodeTree);
System.out.println(yaml);
} catch (IOException e) {
e.printStackTrace();
}
}
}
In module-info:
module jsonToYaml {
requires com.fasterxml.jackson.dataformat.yaml;
requires com.fasterxml.jackson.databind;
// requires java.desktop;
// requires java.logging;
// requires java.xml;
// requires java.sql;
}
---------- END SOURCE ----------
Linux linux-xf9o 4.4.126-48-default #1 SMP Sat Apr 7 05:22:50 UTC 2018 (f24992c) x86_64 x86_64 x86_64 GNU/Linux
OpenSuSE leap 42.3
A DESCRIPTION OF THE PROBLEM :
<unsure if bug or missing feature>
Requiring the common jackson library (automatic module named in MANIFEST) via module-info leaves the developer open to runtime failures if requirements of those automatic modules (which do have module-info) are not correctly specified. In this case it's a automatic module (specified) using a jar (snakeyaml-1.18.jar which doesn't have a specified module name) which uses a jdk module. Jackson uses its manifest to give its jars specific module names, but doesn't yet have a module-info.java (probably due to breaking backwards compatibility)
<see steps to reproduce>
Given we can run jdeps and discover that java.sql is a requirement, shouldn't this be done during compilation and flagged as a compile time warning at least. Leaving it to be discovered (possibly by the end-user) at runtime seems very dangerous as it's not likely to be possible to cover off in tests all scenarios in third party modules. Even we say the developer running jdeps and adding to module-info.java first is best practice, it's possible that a module dependency could be accidentally missed or deleted and with enterprise apps with many dependencies this seems more likely. We could also argue 3rd party jar providers should upgrade, but given this is in something as fundamental as jackson, I'm not sure suggesting that jackson shouldn't be used just yet will go down too well. Having chosen module-info to be a .java file which breaks earlier versions of java is likely to mean this process will be much slower.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
<note I've manually renamed the package if there is a compile issue>
I've put together a simple test app:
(see source code)
Note I've commented out requirements that jdeps reports as depedencies of the jackson jars (which do not have module-info but given names via their manifests).
I compile:
javac -d out -p /home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.5/jackson-databind-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.5/jackson-core-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/dataformat/jackson-dataformat-yaml/2.9.5/jackson-dataformat-yaml-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/home/dav/.m2/repository/org/yaml/snakeyaml/1.18/snakeyaml-1.18.jar src/main/java/com/myname/utils/JsonToYaml.java src/main/java/module-info.java
Not even a warning(!)
I now run this:
java -p /home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.5/jackson-databind-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.5/jackson-core-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/dataformat/jackson-dataformat-yaml/2.9.5/jackson-dataformat-yaml-2.9.5.jar:/home/dav/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/home/dav/.m2/repository/org/yaml/snakeyaml/1.18/snakeyaml-1.18.jar:out -m jsonToYaml/com.myname.utils.JsonToYaml
It's running okay
I enter some json via stdin:
{"hi":1}
and then:
Exception in thread "main" java.lang.NoClassDefFoundError: java/sql/Date
at snakeyaml@1.18/org.yaml.snakeyaml.nodes.Tag.<clinit>(Tag.java:64)
at com.fasterxml.jackson.dataformat.yaml@2.9.5/com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.<clinit>(YAMLGenerator.java:159)
at com.fasterxml.jackson.dataformat.yaml@2.9.5/com.fasterxml.jackson.dataformat.yaml.YAMLFactory._createGenerator(YAMLFactory.java:447)
at com.fasterxml.jackson.dataformat.yaml@2.9.5/com.fasterxml.jackson.dataformat.yaml.YAMLFactory.createGenerator(YAMLFactory.java:397)
at com.fasterxml.jackson.dataformat.yaml@2.9.5/com.fasterxml.jackson.dataformat.yaml.YAMLFactory.createGenerator(YAMLFactory.java:14)
at com.fasterxml.jackson.databind@2.9.5/com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3207)
at jsonToYaml/com.myname.utils.JsonToYaml.main(JsonToYaml.java:19)
Caused by: java.lang.ClassNotFoundException: java.sql.Date
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
... 7 more
Boom!
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Javac should check module-info dependencies that when a auto module is requested that any further dependencies are checked and either warned about, or access is granted to anything it needs (possible warning )
ACTUAL -
Classloader issue at runtime
---------- BEGIN SOURCE ----------
com.myname.utils.JsonToYaml.java:
package com.myname.utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import java.io.IOException;
public class JsonToYaml {
public static void main(String[] args) {
if (args.length != 0) {
System.out.println("No arguments expected, data read from stdin.");
System.exit(1);
}
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode nodeTree = mapper.readTree(System.in);
String yaml = new YAMLMapper().writeValueAsString(nodeTree);
System.out.println(yaml);
} catch (IOException e) {
e.printStackTrace();
}
}
}
In module-info:
module jsonToYaml {
requires com.fasterxml.jackson.dataformat.yaml;
requires com.fasterxml.jackson.databind;
// requires java.desktop;
// requires java.logging;
// requires java.xml;
// requires java.sql;
}
---------- END SOURCE ----------