Java class loader bug: Caused by: java.io.IOException: Stream closed
According to this post, that exception could mean that the .yml
file is simply not found. Since you changed your project structure, it is possible that the logic used to build the configPaths
needs to be modified for the new structure. Did you try to log the content of configPaths
to see if the paths are correct for the new structure?
Also make sure that the .yml
files are included in the .war
file. Some build systems handle resources differently than java class files.
Popcorn
Updated on June 28, 2022Comments
-
Popcorn almost 2 years
I'm getting a strange bug regarding I believe class loader issues when I deploy my webapp to Tomcat. The bug doesn't appear when I run my webapp locally using Jetty. It seems like my input streams for my .yml resource files are being closed for some reason when they shouldn't be. This bug first appeared when I tried to convert my single module project into a multi module project. Before that, it was working fine on Tomcat using the exact same code:
Caused by: org.yaml.snakeyaml.error.YAMLException: java.io.IOException: Stream closed at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:200) at org.yaml.snakeyaml.reader.StreamReader.<init>(StreamReader.java:60) at org.yaml.snakeyaml.Yaml.load(Yaml.java:412) at com.config.ConfigProvider.<init>(ConfigProvider.java:20) ... 49 more Caused by: java.io.IOException: Stream closed at java.io.PushbackInputStream.ensureOpen(PushbackInputStream.java:57) at java.io.PushbackInputStream.read(PushbackInputStream.java:149) at org.yaml.snakeyaml.reader.UnicodeReader.init(UnicodeReader.java:90) at org.yaml.snakeyaml.reader.UnicodeReader.read(UnicodeReader.java:122) at java.io.Reader.read(Reader.java:123) at org.yaml.snakeyaml.reader.StreamReader.update(StreamReader.java:184) ... 55 more
Here's the line that causes the bug:
String s = ConfigProvider.getConfig().getString("test");
Here's the
ConfigProvider
class. It basically scans for all resource files of regex^.*\\.config\\.yml$
, converts it into aMap<String, Object>
, and combines all the obtainedMap<String, Object>
into a singleMap<String, Object>
:1 public class ConfigProvider { 2 protected static final String CONFIG_PACKAGE = ConfigProvider.class.getPackage().getName(); 3 protected static final Pattern CONFIG_PATH_REGEX = Pattern.compile("^.*\\.config\\.yml$"); 4 5 private static final ConfigProvider INSTANCE = new ConfigProvider(); 6 private Map<String, Object> configMap; 7 8 protected ConfigProvider() { 9 configMap = new HashMap<String, Object>(); 10 11 Set<String> configPaths = new Reflections(CONFIG_PACKAGE, 12 new ResourcesScanner()).getResources(CONFIG_PATH_REGEX); 13 14 if (configPaths.isEmpty()) { 15 throw new RuntimeException("no config paths found"); 16 } 17 18 for (String path : configPaths) { 19 InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path); 20 Map<String, Object> fullConfig = new Map<String, Object>((Map) new Yaml().load(inputStream)); 21 22 try { 23 inputStream.close(); 24 } catch (IOException e) { 25 throw new RuntimeException("error closing stream"); 26 } 27 28 MapUtils.merge(configMap, fullConfig); 29 } 30 } 31 32 public static ConfigMap getConfig() { 33 return INSTANCE.configMap; 34 } 35 }
Here's my project structure, titled Foo:
- Foo (this is a module) - .idea - application (this is a module) - src - main - java - resources - application.config.yml - webapp - test - pom.xml - client (this is a module) - src - main - java - resources - client.config.yml - webapp - test - pom.xml - pom.xml
ConfigProvider
is a class I get from my parent pom file (Foo/pom.xml
). I package aWAR
file from theapplication
module (Foo/application/target/application.war
), and deploy it with Tomcat. Previously, my project was a single module project with just aFoo
module being identical toapplication
module. Then I added aclient
module and converted the project into a multi module project, and the problem has showed up. I think it's because my class loader is getting messed up due to the multiple modules. I've spent a lot of time trying to debug this and still haven't gotten anywhere. Anyone know what could be the cause, or can think of possible things to try?Please let me know if you need more info.
-
Popcorn over 10 yearsThank you, the problem was indeed trying to read a .yml file that didn't exist.
-
Minjeong Choi about 4 yearsthank you, same in my case, the error was because it wasn't recognizing my yml file. I'm using intellij, and I didn't set resource folder as Resources Root in my IDE. After setting the folder as Resource Root, it picked up my yml file and successfully read the file.
-
Bhesh Sejawal almost 4 yearsI have the file and still i am getting the same error, even though i have provided absolute path no lock