0

I have generated ba jar file from maven pom file and added the test data files in to target folder using resources tag in POM file.. Even though the files are there inside the target folder,jar is not able to find the files.

Scenario: There is a 2 buttons in joptionpane and when user clicks on the button, file present inside the target folder should be copied ins to he user choosen directory. Code is working in eclipse, but when I execute the Jar file, getting FileNotFoundException

Eg code:

File file=new File("Resources/testdata/data.xls") ;

I'm getting FileNotFoundException here. I have given Resources directory directly as it is added to target.. Is I missing anything??

Code

File temp=null;
                    try {
                        temp = new File(getClass().getClassLoader().getResource("testdata/ResetPassword_UI/New_User_Creation_Data.xls").toURI());
                    } catch (Exception e2) {
                        temp = new File("./src/main/resources/testdata/ResetPassword_UI/New_User_Creation_Data.xls");
                    }

POM

<plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>utilities.ResetPasswordUI</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id> <!-- this is used for inheritance merges -->
                        <phase>package</phase> <!-- bind to the packaging phase -->
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

 <resources>
        <resource>
        <directory>${basedir}/src/main/resources</directory>
         <targetPath>${project.build.directory}/src/main/resources</targetPath>
        <filtering>false</filtering>
            <includes>
              <include>testdata/*</include>
              <include>testdata/ResetPassword_UI/*</include>
              <include>locators.properties</include>
            </includes>
        </resource>
        </resources>

Exception

Exception in thread "AWT-EventQueue-0" java.lang.FileNotFoundException: c://.../src/resources/testdata/ResetPassword_UI/New_User_Creation_Data.xls
        at utilities.ResetPasswordUI$2.actionPerformed(ResetPasswordUI.java:168)
        at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
        at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
        at java.awt.Component.processMouseEvent(Unknown Source)
        at javax.swing.JComponent.processMouseEvent(Unknown Source)
        at java.awt.Component.processEvent(Unknown Source)
        at java.awt.Container.processEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Window.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
        at java.awt.EventQueue.access$500(Unknown Source)

Folder Structure

New Find: when I extract the Jar file, I'm able to see the testdata folder,and files that I have added. but don't know how to use that files which present in the jar

inside jar
  |_test data -> data files
  |_other files

now I want to use that files which are located inside the jar. so that i can able to run irrespective of location and I can just share the Jar without any docs that I'm using inside.

Folder Structure inside Jar file based on this, is there any way to pass the valid file path to getResource method.

Satish
  • 3
  • 3
  • You're probably trying to read the file using some form of `InputStream` anyway so try `getResourceAsStream("resource path")`. Alternatively, if you really need a file, write the stream to a temporary file and use that. – Thomas Mar 31 '21 at 11:51
  • @Thomas, I'm looking for the correct way to get the path of file which is present inside the jar file, because when If want to share with peers, I can directly share that jar with out adding any data files manually – Satish Mar 31 '21 at 11:54
  • And also that code is working fine with out any issues in Eclipse IDE, the only failure is dealing with Jar( placing in some random location and executing that jar) – Satish Mar 31 '21 at 11:55
  • Well there is no "file" in that jar but just a resource much like there are no files in zip archives but zip entries (in fact jar files are zip archives). You could extract those into files but they are not accessible from the outside via a simple file path. So either extract the resource to a file if needed or simply work with the resource. - And a note on IDE use: the IDE will most likely work with unpackaged classes and resources so there is no jar (yet) and thus the resources are actually files. – Thomas Mar 31 '21 at 11:58
  • @Thomas, So is it not possible to access the files present in the jar.. if there is way, How can i do that. – Satish Mar 31 '21 at 12:02
  • What exactly are you trying to do with those "files"? You can only read them and to do that you need an `InputStream` in the end so why not use `getResourceAsStream()`? If you share the jar with your peers what would they do with those resources? How would they access them from the outside? And if they only access them from within your application then again, why not use the input stream? – Thomas Mar 31 '21 at 12:13

2 Answers2

1
  • The java.io.File class represents actual files on disk (and not in jar files or otherwise virtualized resources) and cannot be expanded to represent anything else. It is therefore impossible to use a File instance to represent a resource, and you should not do this.
  • Almost all APIs in java that require a file have an overloaded method that take a URI and/or InputStream instead.
  • You can ask java to obtain a resource from the same place java fetches class files (so, from within that jar file for example), in the form of either a URI or InputStream, which you then pass to these APIs.
  • If your API truly only accepts files, plan A is to go file a bug with that library, and then to work around it, write out your data to a temp dir. Not recommended of course, that's quite a hassle.

The right way to turn a resource into a URI (for example, to pass to an ImageIcon constructor), within a class named Example:

Example.class.getResource("myimg.png");

This looks in the exact same place (and even the same folder) that contains Example.class (so, the 'package' of Example is prepended to your resource string). If you'd rather look in the 'root' of where Example.class lives (e.g. from the root of the jar file that contains Example.class), ask for getResource("/myimg.png") instead.

For an inputstream:

try (InputStream in = Example.class.getResourceAsStream("myicon.png")) {
   // use 'in' here
}

Both methods return null if the resource is not found. If you ask for an InputStream, you are responsible for closing it, so use try-with-resources to do so.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Sure. I will check this solution but any way I'm doing the same thing like how you mentioned to get the resource from class ```getClass().getClassLoader().getResource("testdata/ResetPassword_UI/New_User_Creation_Data.xls").toURI()``` . Is this won't work? – Satish Mar 31 '21 at 12:10
  • @Satish once you have the URI you'd do what exactly? Read the first bullet point in this answer: you can't just pass the uri as a path to `File` and expect it to be readable. – Thomas Mar 31 '21 at 12:15
  • `getClass().getClassLoader().getResource` this is doubly broken; there are circumstances where this will fail. It's also not idiomatic and needlessly longer. `YourClass.class.get...` is what yout want (fails when loaded in bootstrap scenarios, fails when subclassing). You need to copy the _EXACT_ path of the resource in the jar, including leading slash, and pass that to `MyClass.class.getResource`. – rzwitserloot Mar 31 '21 at 12:16
  • And, yes, as Thomas said, if you pass that URI to a `new File()` constructor, that does not work. If `File` is anywhere in your source file, this is not going to work, it has to go. – rzwitserloot Mar 31 '21 at 12:17
  • Ok.. so first I need to check InputStream that it is able to picking that and converting in to InputStream or not.. If it is able to pick then I can use that InputStream and build that file otherwise it can be null right.? – Satish Mar 31 '21 at 12:20
  • @rzwitserloot, I have tried with your suggestions, but still i'm getting null pointer exception and Yes. it's cause of may be the file path I'm passing.. so can you please check that i'm giving correctly. ```try { temp = new File(ResetPasswordUI.class.getResource("testdata/ResetPassword_UI_Datasheet.xls").toURI()); } catch (Exception e2) { InputStream ip=ResetPasswordUI.class.getResourceAsStream("testdata/ResetPassword_UI_Datasheet.xls");if(ip==null) { //do somthing }else { System.out.println("Stream found");}}``` – Satish Mar 31 '21 at 12:39
  • I'm adding inside folder structure for you referecnes. Check in the Question please. – Satish Mar 31 '21 at 12:42
  • 1
    No, you need to read the answer. I told told: __As long as you use java.io.File this cannot ever work, period - and there is no reason to use that__ and you keep completely ignoring this advice. As long as you ignore it, you cannot solve this problem and there is nothing I or others can do to help you here. – rzwitserloot Mar 31 '21 at 13:27
0

This Solved my Problem -> please find the below

Solution

ResetPasswordUI.class.getClassLoader().getResource("New_User_Creation_Data.xls").openStream()

get the input stream from the resource and use that input stream as per your requirement,

Solution in the below URL How to get a path to a resource in a Java JAR file

Satish
  • 3
  • 3