0

I wrote a program in which a pdf file should be opened on an Action Event (you can have a look at my code below).

menuElementHilfe.addActionListener(new ActionListener() {   
    public void actionPerformed(ActionEvent arg0) {
        File hilfe = new File ("src\\resources\\Hilfe.pdf");
        try {
            java.awt.Desktop.getDesktop().open(hilfe);
        } catch (IOException e) {
            e.printStackTrace();
        }       
    }   
});

If I execute the program via Eclipse everything works, but after exporting as a runnable jar I get following Exception:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: The file: src\resources\Hilfe.pdf doesn't exist.

Any Feedback is appreciated

barbsan
  • 3,418
  • 11
  • 21
  • 28
Sven
  • 3
  • 1

2 Answers2

0

The way you're retrieving resources may be the problem. try this :

menuElementHilfe.addActionListener(new ActionListener() {   
    public void actionPerformed(ActionEvent arg0) {
    File hilfe = new File(getClass().getResource("/resources/Hilfe.pdf").getFile());
        try {
        java.awt.Desktop.getDesktop().open(hilfe);
        } catch (IOException e) {
            e.printStackTrace();
        }       
    }   
});

When running in Eclipse, you are targeting a file in your build path. When running from JAR/WAR, the URL is different and look like "jar:file:/your-path/your-jar.jar!/Hilfe.pdf" which is not what you set when calling new File(...) So to get the right URL for internal resources, you have to use methods like getResource or getResourceAsStream depending on your needs.

Check out following explanations for more information :) https://docs.oracle.com/javase/8/docs/technotes/guides/lang/resources.html

[EDIT]

I assume you're working on some Swing app, but I dont know if you're aware that doing some task like that in your AWT-EventQueue thread will freeze your UI. To prevent that you have to run UI-unrelated stuff in another thread.

This is made using SwingUtilities.invokeLater (Java 5 and prior) method and/or the SwingWorker class (since Java 6).

as mentionned in this answer

You should put the previous solution in something like that :

 SwingUtilities.invokeLater(new Runnable() {
    public void run() {
       // Your UI unrelated code here
    }
 });
aadiene
  • 327
  • 3
  • 7
0

The resource can be packed in the application jar, hence File (physical disk file) is not possible. Copy it to a temporary file, so that the desktop can open it.

menuElementHilfe.addActionListener(evt -> {   
    Path tmp = Files.createTempFile("hilfe-", ".pdf");
    Files.copy(getClass().getResourceAsStream("/Hilfe.pdf"), tmp);
    try {
        Desktop.getDesktop().open(tmp.toFile());
        tmp.toFile().deleteOnExit();
    } catch (IOException e) {
        e.printStackTrace();
    }       
});

An other difference is the forward slash, and that the path is case-sensitive, opposed to Windows File.


After problems

menuElementHilfe.addActionListener(evt ->
        SwingUtilities.invokeLater(() -> {
            Path tmp = Files.createTempFile("hilfe-", ".pdf");
            Logger.getLogger(getClass().getName()).log(Level.INFO, "actionPerformed "
                    + tmp + "; event: " + evt);
            Files.copy(getClass().getResourceAsStream("/resources/Hilfe.pdf"), tmp);
            try {
                Desktop.getDesktop().open(tmp.toFile());
                //tmp.toFile().deleteOnExit();
            } catch (IOException e) {
                Logger.getLogger(getClass().getName()).log(Level.WARN, "Error with " + tmp,
                        e);
            }       
        }));
  • I did not delete, so the Desktop access can live longer than the java app.
  • I did an invokeLater in order to have no frozen GUI on the actionPerformed.
  • I added logging to see every call to actionPerformed
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • thanks for your answer, but i think something doesnt work here. on Desktop.getDesktop().open(hilfe.toFile()); i get the error: hilfe cant be resolved – Sven Jul 05 '19 at 12:40
  • @Sven should have `tmp` instead of `hilfe` (twice). Corrected – Joop Eggen Jul 05 '19 at 12:42
  • The means that the path was not found on the class path (getResource/getResourceAsStream). Open the jar (7zip or such), and look for the (case-sensitive) path. Maybe it should have been `/resources/Hilfe.pdf` or `/hilfe.PDF` or whatever. – Joop Eggen Jul 05 '19 at 12:51
  • the full path in 7zip is D:\Tool\tool.jar\resources\Hilfe.pdf ; should i use this instead of "/Hilfe.pdf" – Sven Jul 05 '19 at 12:57
  • If tool.jar is on the classpath, contains the classes, the path should have been `/resources/Hilfe.pdf`. – Joop Eggen Jul 05 '19 at 14:47
  • So I think i corrected my resources folder and tried your code again. I get following error: java.nio.file.FileAlreadyExistsException: C:\Users\swoerner\AppData\Local\Temp\hilfe-469223706109657558.pdf ; So i went to that directory and deleted the "hilfe" temp files, but I get the same error again when executing. Any ideas? – Sven Jul 08 '19 at 05:42
  • You can try comment out deleteOnExit. Maybe actionPerformed is run twice after another for som odd reason. I'll change some code. – Joop Eggen Jul 08 '19 at 07:35