1

I have a Java project in Eclipse with the following directory structure:

Root
----->Data
----->lib
----->src
      ----->packageName
            ------------> Main.java

The lib folder contains all the jars and some other files the project depends on. The data has some wav files the project processes. I want to run this project from the command line and hence I was exporting this project as a runnable jar. However when I do that, I see that the resulting jar has all the contents of the data and the lib folders in the root folder itself and the data/lib folders are completely gone.

What have I tried without success:

I used WinRar to simply add the data and lib folders with the appropriate content to the generated Jar. However, when I run this Jar, the compiler is unable to find the files present in the Data and Lib folders.

Any ideas on what can I do to solve my problem?

TheBlueNotebook
  • 1,204
  • 3
  • 15
  • 35

1 Answers1

0

I suppose that Data and lib are added to the classpath in Eclipse. When you reference their contents, you do so by their path from the classpath root. When packaging then na jar, Eclipse puts the content of each directory listed in the classpath into one directory. However, subdirectories will be preserved.

To preserve Data, you can put it in a directory, the convention is to name this resources, and add this directory to the classpath instead of Data. However, everywhere you access files in Data, you'll need to adjust the path, as now Data becomes part of the path (relative path from classpath root).

As for lib, you cannot do similarly, because when you access its content (I suppose through import statements) you probably don't have a way to specify a subdirectory.

The above assumes that you are accessing these resources via classpath paths. If you are accessing them using filesystem paths, then you need to change all those accesses to use methods that use the classpath, such as the various getters in ClassLoader.

janos
  • 120,954
  • 29
  • 226
  • 236
  • Alright. So in my lib folder I should not put anything else apart from the jar files the project depends on. In the resources folder I can create an external folder and put other dependencies there? These dependencies are some model files so I am not accessing its contents through the import statements anyway. Am I correct in my inference? – TheBlueNotebook Nov 23 '15 at 06:31
  • Could you also elaborate on how should I refer to the files in the data folder (which is now in the resource folder)? Currently I used to simply call FileInputStream(qualifiedFileName) where qualifiedFileName used to be "data/"+fileName. Now I will have to make it "resources/data/"+fileName, which doesn't make sense as in the runnable jar, again resources will be lost. – TheBlueNotebook Nov 23 '15 at 06:36
  • Yes, like that. Just to be clear, in the resources folder, the sub folders you create are not called "external" – janos Nov 23 '15 at 06:36
  • That's odd. No, resources should not be part of the path. Something is off here. If you are already referencing those files with "Data/" prefix, then the "Data" directory itself should be in the jar... It seems there is something here you're not telling us, or overlooking – janos Nov 23 '15 at 06:39
  • I moved the data folder to the resources folder and also created a new folder called "models" in resources. In the models folder i have kept the model files that I have been using. I have also added the resources folder to the classpath. Now when I run the program on eclipse, I get a fileNotFoundException, because I am referring to the files as "data/fileName" or "models/fileName". The program runs fine, if I refer them as "resources/data/fileName" or "resources/models.fileName". Of course, if I create a runnable jar file with this, I get fileNotFoundExceptions when i run the jar file. – TheBlueNotebook Nov 23 '15 at 06:52
  • OK I see now. It seems that currently you are accessing these files by filesystem path, not by classpath. When you run in Eclipse, this seems to work, because Eclipse launches programs from the project root by default, from which the relative paths exist. However, to access files in the jar, you need to use methods that use the classpath. For example via `this.class.getResourceAsStream("Data/....")`. If you rewrite this way then it will work in both Eclipse and from the runnable jar too. – janos Nov 23 '15 at 07:03
  • Yes, I was indeed missing the getResourceAsStream part. This worked now. Except, one of the APIs I am using expects a FileInputStream instead of an InputStream returned by the getResourceAsStream. Looking up on how to do the conversions now. – TheBlueNotebook Nov 23 '15 at 07:17
  • Nope. I have a jar that is working now. I had to make some more tweaks eventually, but I have what I need now. Accepting this answer and the comment thread on it for the help and learning it provided. – TheBlueNotebook Nov 24 '15 at 02:21