0

I have a use case where I need to export this specific piece of code as a java library (which will be a JAR eventually) but the problem is that it needs to use some piece of information stored in physical files on the file system.

I have 2 questions here:

1) Where should I put these files on the filesystem (One option that I could think of was in the resources directory of the Java module containing the library: Have a doubt though that the resources directory also gets compiled into the jar?)

2) When I am using this library from an external Java application, how would the library be able to locate the files? Would they still be in the classpath?

Abhishek Jain
  • 4,478
  • 8
  • 34
  • 51
  • What can of file is it ? A configuration file ? Should this file be overridden ? – Pierre-Henri Oct 09 '12 at 10:29
  • It is not clear if you want to move your files with your JAR (use `getResourceAsStream`) or if the files are independent of your JAR (specify the path in a .properties editable by the user / pass it as a startup parameter, as answered by logoff) – SJuan76 Oct 09 '12 at 10:31
  • @Pierre-HenriToussaint - Yes, you may treat it as a config file but the point am trying to ask here is: Lets scope it to the jar in which I have classes which need to be exposed to various applications. These classes need to access these config files (and these are fixed independent of the applications using the classes). When this jar gets imported to an application, and the application tries to use one of the classes in the above mentioned jar which try to retrieve some info from the config files, is everything going to work just fine without any classpath issues? – Abhishek Jain Oct 09 '12 at 10:52
  • if the "config files" are not java classes, nor are used for defining java dependencies in some custom manner - you will not have any classpath issue. – linski Oct 09 '12 at 10:59

5 Answers5

1

You have two options, first one is to place the files inside the package structure, so that they will be packed inside the jar. You would get them from the code like this:

getClass().getResourceAsStream("/path/to/your/resource/resource.ext");

If you would call it from a static method of class named A then you should write like this:

A.class.getResourceAsStream("/path/to/your/resource/resource.ext");

The "/path" part of the path is the topmost package, and the resource.ext is your file name.

The other option is to put them outside the jar package, but then the jar needs to know their location:

  • provide it as an argument to the program (java -jar program.jar system/path/to/file)
  • hardcode the location from which you would read the file with paths

The way I undestood your queastion and answered it, it has nothing to do with classpath:

The CLASSPATH variable is one way to tell applications, including the JDK tools, where to look for user classes. (Classes that are part of the JRE, JDK platform, and extensions should be defined through other means, such as the bootstrap class path or the extensions directory.)

EDIT: but you can nevertheless, put it there and get it from code like this:

System.getProperty("java.class.path");

It would however require some logic to parse it out.

linski
  • 5,046
  • 3
  • 22
  • 35
0

You can pass the location of the files in a property file or some technique like this.

logoff
  • 3,347
  • 5
  • 41
  • 58
0

Where should I put these files on the filesystem

That is up to you to decide, though it would be a good idea to make this configurable. It would also be a good idea to try to fit into the conventions of the host operating system / distro, though these vary ... and depend on the nature of your application.

When I am using this library from an external Java application, how would the library be able to locate the files?

You would typically use a configuration property or initialization parameter to hold/pass the location. If you were writing an application rather that a library, you could use the Java Preferences APIs, though this probably a poor choice for a library.

Would they still be in the classpath?

Only if you put the location on the classpath ... and that is going to make configuration more tricky. Given that these files are required to be stored in the file system, I'd recommend using FileInputStream or similar.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • @StephenC-I already have the files with me. I wanted to know a way of packaging these files inside the jar itself so that independent applications using the jar do not have to care about these files. To make the question a little more clear, I wanted to confirm that when these files are part of a jar and are being referenced by classes in the same jar, and this jar is being used by several other applications, would the referencing be the same as we would access a normal resource file in a module? I mean, looking from the application's perspective, does the classpath have these files as well? – Abhishek Jain Oct 09 '12 at 10:47
0

Using Eclipse, I always create a package 'resources' where I put the files the jar needs. I access the files (from pretty much anywhere) through

this.getClass().getClassLoader().getResources("/resources/file.ext");

With export->runnable jar all those files are included in the .jar. I'm not sure this is the correct way of doing it though. Also, I'm not 100% sure about the "/" before resources, maybe it should be omitted.

ohr
  • 1,717
  • 14
  • 15
Jonas Rosenqvist
  • 365
  • 5
  • 16
  • 3
    Did the OP mention Eclipse? He is actually talking about an application / library that will be installed independently of Eclipse. – Stephen C Oct 09 '12 at 10:42
0

I found a relevant answer as a part of another question : How to load a folder from a .jar?

I am able to successfully retrieve the files using the following code:

   /**
   * List directory contents for a resource folder. Not recursive.
   * This is basically a brute-force implementation.
   * Works for regular files and also JARs.
   * 
   * @author Greg Briggs
   * @param clazz Any java class that lives in the same place as the resources you want.
   * @param path Should end with "/", but not start with one.
   * @return Just the name of each member item, not the full paths.
   * @throws URISyntaxException 
   * @throws IOException 
   */
  String[] getResourceListing(Class clazz, String path) throws URISyntaxException, IOException {
      URL dirURL = clazz.getClassLoader().getResource(path);
      if (dirURL != null && dirURL.getProtocol().equals("file")) {
        /* A file path: easy enough */
        return new File(dirURL.toURI()).list();
      } 

      if (dirURL == null) {
        /* 
         * In case of a jar file, we can't actually find a directory.
         * Have to assume the same jar as clazz.
         */
        String me = clazz.getName().replace(".", "/")+".class";
        dirURL = clazz.getClassLoader().getResource(me);
      }

      if (dirURL.getProtocol().equals("jar")) {
        /* A JAR path */
        String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
        JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
        Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
        Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
        while(entries.hasMoreElements()) {
          String name = entries.nextElement().getName();
          if (name.startsWith(path)) { //filter according to the path
            String entry = name.substring(path.length());
            int checkSubdir = entry.indexOf("/");
            if (checkSubdir >= 0) {
              // if it is a subdirectory, we just return the directory name
              entry = entry.substring(0, checkSubdir);
            }
            result.add(entry);
          }
        }
        return result.toArray(new String[result.size()]);
      } 

      throw new UnsupportedOperationException("Cannot list files for URL "+dirURL);
  }
Community
  • 1
  • 1
Abhishek Jain
  • 4,478
  • 8
  • 34
  • 51