2

I have a project that I am compiling using javac. I want to be able to fetch resources without having to first build my project into a JAR file, but at the same time, I don't want to hard code the location either (C://Users/name/etc).

I know that if I had a JAR file, I could use a ClassLoader and call one of the resource methods from there. Alternatively, if my resources were contained within another JAR file, and that JAR file was on my class path, then I could fetch it from the JAR file in a similar format.

But how do I do so when I am only compiling in javac? I don't want to have to rework all of my resource fetching logic when I eventually turn this into a JAR file, but I also don't want to have to make a jar file every time I compile and want to test a change. I just want to be able to specify to Java that this is where to find my resources, and I don't want to change that strategy when I finally decide to making a JAR file.

davidalayachew
  • 1,279
  • 1
  • 11
  • 22
  • 1
    You can locate resources in the folder same way as in jar. Just make sure your folder with resources is provided with -cp with the correct root – gdomo Aug 03 '23 at 17:33
  • @gdomo Put that into an answer and I'll accept it. – davidalayachew Aug 03 '23 at 17:34
  • @user16320675 That is good to know, but I far prefer the -cp option, as it allows me to be explicit and not depend on assumptions. That is safer for me in the long term. – davidalayachew Aug 03 '23 at 17:40
  • There is no need and I would say is an antipattern to add to the classpath something that it is already there. You only need to add to the classpath if it is in a different project or a separate jar. – aled Aug 03 '23 at 17:45
  • @aled I don't think you understand the full context here. I want to have my resources in an entirely separate folder from where my code (and compiled .class files) will be. Because of this, the -cp option works perfectly for my needs. My code is not going to be nearby my resources, therefore your suggestion doesn't work, and your concerns about antipattern are irrelevant to my situation. That is because my resources were not on the classpath to begin with. – davidalayachew Aug 03 '23 at 18:10
  • 2
    assumptions? well, if the code is running, the ClassLoader sure did find the classes that are running, or? If the resources are *sharing* the same location as the classes (deployed together) there is no need for an additional entry (`-cp` or `CLASSPATH`) - Sure, if you *need* a separate location, then it must be added to the classpath – user16320675 Aug 03 '23 at 18:21
  • @user16320675 My criticism was to aled, not you. You gave a helpful comment -- you are telling me that, if my resources are already on the classpath, then I can forgo the `-cp`. That is useful info, but I can't take advantage of it because my resources are not already on the classpath. Aled, on the otherhand, made the assumption that my resources were already on the classpath, and told me that doing `-cp` is an antipattern. I am criticizing aled for jumping to conclusions. You did nothing wrong. And yes, the accepted answer included what you said, which is good. It made the answer better. – davidalayachew Aug 03 '23 at 18:31
  • 1
    it's OK - I did not refer to anything regarding aled's comment or your reply to it (or at least I think so) - just the "not depend on assumptions" kind of made me think that you did not understand what I wanted to say... Anyway the ClassLoader uses the same mechanism to find/load resources as it does for classes (no matter if in a JAR, a directory, or ??) – user16320675 Aug 03 '23 at 18:38
  • @user16320675 I understand. I think the name classpath is part of the confusion because, when I say resources, I actually mean image files. They exist in a very different folder from the rest of my code, and thus, was not in a location that the `ClassLoader` knew to look. I suppose I could move them there, but I don't want to because that folder will likely get deleted whenever I need to do clean builds. Java will recreate the folder before inserting the created .class files, but I would have lost my images. I could probably turn off that behaviour, but it's easier to put the images elsewhere. – davidalayachew Aug 03 '23 at 18:43
  • 2
    *kind of* an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)... like the real problem is how the app is being built -- most IDEs do the correct copying of resources, so do most build tools (I know of) – user16320675 Aug 03 '23 at 18:49
  • @user16320675 In this individual instance, you would be correct. However, that is a separate issue that I can fix. Ultimately, I want to be able to store my resources off the default classpath, and be able to include them in as necessary with an explicit command. This is because I want to be able to have my resources be something the user can easily edit and interact with, even after I have built my code. – davidalayachew Aug 03 '23 at 18:51
  • I agree with @user16320675. It doesn't look like classpath resource management is what should be used for editable files. I don't have enough context but probably should be managed as regular files. – aled Aug 03 '23 at 19:39
  • @aled By all means, if you have an alternate suggestion, I am willing to hear it. – davidalayachew Aug 03 '23 at 19:42
  • For the use case described in the question is what @user16320675 said. However if the user case is that the application edits and manages files that is a complete different situation to the original question. You may want to open a new question but if it is very high level it could be off topic. – aled Aug 03 '23 at 19:56
  • @aled So to be clear, it is not the application that is editing and managing files, it is the user. What I wanted was to be able to use the same JAR, but have different values for the `-cp` flag when running the application, depending on the context. That way, I only need to make minor changes on the command line to handle an entirely different context. This gives me a lot of flexibility, and allows me to repurpose an existing solution to a new context without having to change any code. – davidalayachew Aug 04 '23 at 01:15

1 Answers1

1

You can locate resources in the folder same way as in a jar. Just make sure your folder with resources is listed via -cp when running java and relative paths in your code corresponds to it.

Here is an example.

java -cp ".;first/path/to/resource/folder;second/path;third/path" PackageName.NameOfClassContainingMainMethod

That said, the resource might be inside of the same folder that your compiled code is in. In that case, there is no need to provide it explicitly via -cp.

Whenever you are loading a resource in your code by ClassLoader.getResource / getResourceAsStream java looks for it in the classpath. Providing .jar (which is essentially just a zipped folder) and raw folder is just an alternative ways to specify a content to be loaded into classpath.

davidalayachew
  • 1,279
  • 1
  • 11
  • 22
gdomo
  • 1,650
  • 1
  • 9
  • 18
  • This is very helpful, thank you very much. Could you also include the part about .jar and how the way to do it for a .jar is the same for javac? I feel like that would really help communicate how the way to solve this problem is actually the same for both contexts. – davidalayachew Aug 03 '23 at 18:12
  • 1
    Not sure if I got your question. I've extended the answer a bit. If it's not enough, please, specify your question. – gdomo Aug 03 '23 at 20:00
  • That's exactly it, ty vm – davidalayachew Aug 03 '23 at 20:04