FileNotFoundException on linux machine when using getClassLoader().getResource - java

I made already quite some research on internet for this problem. I had no luck so far. Basically this piece of code works fine on Windows with my Junit test src\test\java\com\project\utils\MyTestCase.java :
URL urlApplicationContext = this.getClass().getClassLoader().getResource("applicationContext.xml");
final String[] paths = { urlApplicationContext.getFile()};
ApplicationContext ctx = new FileSystemXmlApplicationContext(paths);
This file is located there:
\src\test\resources\applicationContext.xml
However on the Jenkins machine which run on linux I got the following error :
testSimple(com.project.ClientImplTest): IOException parsing XML
document from file
[/data/continuous/workspace/sonar/main_proj/data/continuous/workspace/sonar/main_proj/target/main/WEB-INF/test-classes/applicationContext.xml];
nested exception is java.io.FileNotFoundException:
data/continuous/workspace/sonar/main_proj/target/main/WEB-INF/test-classes/applicationContext.xml
(No such file or directory)
I already verified that the file /data/continuous/workspace/sonar/main_proj/target/main/WEB-INF/test-classes/applicationContext.xml does exist.
Why the getResource() does not find the correct path on Linux. It seems it finds data/continous/... instead of /data/continous/... for some reason ? Therefore FileSystemXmlApplicationContext may return an exception because it cannot find the file.
Thanks

I had the same problem in my project - it was caused by spaces in the path - to handle such cases, you need to use the URL's toURI() method - do following:
ApplicationContext ctx;
URL urlApplicationContext = this.getClass().getClassLoader().getResource("applicationContext.xml");
if (urlApplicationContext != null) {
File appCtxFile = new File(urlApplicationContext.toURI());
ctx = new FileSystemXmlApplicationContext(new String[]{ appCtxFile.getAbsolutePath() });
} else {
throw new RuntimeException("Cannot find XML file 'applicationContext.xml'");
}

Try to add some debug output. URL has nice toString() method. Thus you'll get where app is looking for file.
It looks like you missed slash at the very beginning. Replace data/continuous/... to /data/continuous/... in your resource loader.

Since I don't have enough rep to upvote or comment or anything I will say what I need to say here lol
Oifan is absolutely right (read answer needs accepting).
Had the same issue on Jenkins. Code was trying to access a file during a test, path had spaces in it, resulted in FileNotFoundException. The file was definitely in the right location.
My testing also showed that the spaces were the culprit. We were just going to rename the project in Jenkins which would have resulted in no more spaces in our directory structure. Then I came across Oifan's answer.
Converting the URL from getResource() to a URI and passing that to File() solved the problem for us too.
BTW, the problem is not isolated to linux. I have seen this behavior on Windows Jenkins slaves as well.

Actually Jenkins does not complain about the applicationContext.xml file, but this one: data/continuous/workspace/sonar/main_proj/target/main/WEB-INF/test-classes/applicationContext-hibernate-junit.xml

Why the getResource() does not find the correct path on Linux.
I think you need to look at your code and stacktraces again.
The getResource() method does not throw IOException, or any subclasses of IOException. Not ever.
The exception you are seeing is being thrown by ... something else. And it is pretty clear from the message that the code that throws that exception is not looking for a file called "applicationContext.xml" either.
UPDATE
Even following your correction, it remains an incontravertable fact that getResource() cannot cause a FileNotFoundException. You are looking at the wrong code.

Related

Why does getResourceAsStream() return null when File does not exist before start of Test method?

Before flagging this as a duplicate please read the question!
I have a JUnit Test which tests a method that writes its result in a file. To check the result I want to read that result file and check its content.
The problem is that when the result file does not already exist before the start of the test, the method getResourceAsStream() returns null.
My code for the Test is something like this:
#Inject
private ObjectToTest obj
#Test
public void testMethod() throws Exception {
// Do some setup (inject mocks, set properties of obj, ...)
obj.method(); // <-- Creates result.txt
Mockito.verify(obj).method();
// Thread.sleep(1000); <-- I have tried to use this to wait some time for the result, but it did not work
// This part is null on the first run of the test
// When I run the test the second time, the file does already exist and it returns the right InputStream for the File
InputStream resultInp = this.getClass().getResourceAsStream("/test-out/result.txt");
String resultStr = IOUtils.toString(resultInp, "UTF-8");
assertThat(resultStr).isNotNull();
assertThat(resultStr.split("\n")).hasSize(5);
}
Is there any explanation to why this happens or must it have to do something with another part of the code?
I have not found anything regarding this issue on StackOverflow, but if I am wrong please guide me to the right post.
The getResourceAsStream() method returns a stream for a resource on the classpath, using directory / index information that is cached by the classloader. If you add a resource to some directory tree or archive on the classpath after the classpath has been cached, the classloader is likely to not "see" it1.
That is most likely is what has happened in your test code.
A Java application should not be trying to treat classloader resources like a general purpose file system. Instead, use File or Path to denote files, and FileInputStream or similar to open them.
1 - The actual behavior does not appear to be specified in the javadocs for ClassLoader, etcetera. My description is based on the observed / reported behavior of some Java implementations.

How to get list of files from URL

I have an URL http ://......../somefolder/ I want to get the names of all the files inside this folder. I have tried this below code but it's showing error.
URL url = new URL("http://.............../pages/");
File f=new File(url.getFile());
String list[]=f.list();
for(String x:list)
{
System.out.println(x);
}
Error :-Exception in thread "main" java.lang.NullPointerException
at Directory.main(Directory.java:25)
It's not possible to do it like this.
HTTP has no concept of a "folder". The thing you see when you open that URL is just another web page, which happens to have a bunch of links to other pages. It's not special in any way as far as HTTP is concerned (and therefore HTTP clients, like the one built into Java).
That's not to say it's completely impossible. You might be able to get the file list another way.
Edit: The reason your code doesn't work is that it does something completely nonsensical. url.getFile() will return something like "/......./pages/", and then you pass that into the File constructor - which gives you a File representing the path /....../pages/ (or C:\......\pages\ on Windows). f.list() sees that that path doesn't exist on your computer, and returns null. There is no way to get a File that points to a URL, just like there's no way to get an int with the value 5.11.

Get name of running Jar or Exe

What I need to do is get the name of the running jar/exe file (it would be an EXE on windows, jar on mac/linux). I have been searching around and I can't seem to find out how.
How to get name of running Jar or Exe?
Hope this can help you, I test the code and this return you the full path and the name.
Maybe you want to play a little more with the code and give me some feed back.
File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI());‌
This was found on a similar but not == question on stackoverflow
How to get the path of a running JAR file?
File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI());‌
returns simple path in the compiled application and an error in jar:
URI is not hierarchical
My solution is:
private File getJarFile() throws FileNotFoundException {
String path = Main.class.getResource(Main.class.getSimpleName() + ".class").getFile();
if(path.startsWith("/")) {
throw new FileNotFoundException("This is not a jar file: \n" + path);
}
path = ClassLoader.getSystemClassLoader().getResource(path).getFile();
return new File(path.substring(0, path.lastIndexOf('!')));
}
File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().g‌​etPath());
Should give you the jar.
as for the exe, as I'm assuming you're using some sort of wrapper, you'll need to know the name of the exe before it's run. Then you could use something like :
Process p = Runtime.getRuntime().exec
(System.getenv("windir") +"\\system32\\"+"tasklist.exe");
Try the following
System.getProperty("java.class.path")
Using Lunch4j you can add an image name for exe file by editing generated xml, you have to change tag value true from false to true

Loading files within android

Android seems to make life pretty easy for loading resources of certain types. Once I leave the beaten path a little bit, it seems less helpful. I can load in images, sounds and other objects from the assets folder if and only if they are of certain types. If I try to load a binary file of my own format, I get a less than helpful 'file not found' exception, even though listing the directory shows that it is clearly there.
I've tried using the following methods to read a binary file of a custom format from the assets directory:
File jfile = new File("file://android_asset/"+filename); //tried to get the URI of the assets folder
JarFile file = new JarFile("assets/"+filename); //tried assuming the assets folder is root
fd = am.openNonAssetFd( filename); //tried getting my file as an non asset in the assets folder (n.b. it is definitely there)
fs = am.open(filename, AssetManager.ACCESS_BUFFER); //tried loading it as an asset
I'm thinking that there's something fundamental about android file I/O that I don't understand yet. The documentation for asset management seems incomplete and there must be some reason for deliberately making this unintuitive (something to do with security?). So, what's the fool proof, canonical way of loading a binary file of my own format within an android app?
UPDATE:
I tried file:///android_asset/ but still no joy.
String fullfilename = "file:///android_asset/"+filename;
File jfile = new File(fullfilename);
if (jfile.exists())
{
return new FileInputStream(jfile);
}
else
{
return null; //the file does exist but it always says it doesn't.
}
Are there any permissions for the file or in the project manifest that I need?
Thanks
I think the best way to load a file from the Assets folder would be to use AssetManager.open(String filename) - this gives you back an InputStream which you can then wrap in a BufferedInputStream and otherwise call read() to get the bytes. This would work regardless of the file type. What kind of problems have you had with this approach specifically?
I think you have left out the slash as in
File jfile = new File("file:///android_asset/"+filename);
There's three forward slashes, not two. :)
For me the solution was to uninistall the application, clean the project in Eclipse and run it again. The problem was Android couldn't find the new files I put in the asset folder.
I ended up reading this question so I hope this can be helpful to someone else.

FileInputStream is Null?

Okay, so this is the line that's returning null. What am I doing wrong while creating this FileInputStream?
FileInputStream fin = new FileInputStream(new File(getClass().getResource("data/levellocks.lv").toURI()));
The only thing that can be null there is getResource("data/levellocks.lv") which is calling the toURI call to fail
Either getClass or getResource could return null. Everything else should succeed or throw an exception.
Unless you really need a file input stream, you line can be simplified to:
InputStream in = getClass().getResourceAsStream("data/levellocks.lv");
Class.getResource() and Class.getResourceAsStream are relative to the package. To get the file relative to the root of the classpath, you can call those methods on the classloader:
InputStream in = getClass().getClassLoader().getResourceAsStream("data/levellocks.lv");
Did you make sure the file is in your binary folder, next to the .class files? Not just in your source folder next to the .java files?
I actually just dealt with this issue (I'm no expert) but try debugging and see where the constructor is trying to resolve the name to. For me, it was the package of the class. So when I put the file in the expected folder, it found it.
Would probably be different for you, as I'm using maven. But I put it in src/main/resources and it couldn't find it. When I put a folder structure in src/main/resources of com.work.hin.terminology.match (which was the package of the class), it found it.

Categories