Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't Access Resources In Executable Jar

Can someone please point out what I'm doing wrong here.

I have a small weather app that generates and sends an HTML email. With my code below, everything works fine when I run it from Eclipse. My email gets generated, it's able to access my image resources and it sends the email with the included attachment.

However, when I build the executable jar by running mvn install and run the jar using java -jar NameOfMyJar.jar I get java.io.FileNotFound Exceptions for my image resource.

I know that I have to be doing something wrong with how I'm accessing my image resources, I just don't understand why it works fine when it's not packaged, but bombs out whenever I package it into a jar.

Any advice is very much appreciated it.


My project layout enter image description here


How I'm accessing my image resource

//Setup the ATTACHMENTS
        MimeBodyPart attachmentsPart = new MimeBodyPart();
        try {
            attachmentsPart.attachFile("resources/Cloudy_Day.png");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }   

The StackTrace

    Exception in thread "main" java.lang.RuntimeException: javax.mail.MessagingException: IOException while sending message;
  nested exception is:
    java.io.FileNotFoundException: resources/Cloudy_Day.png (No such file or directory)
    at Utilities.SendEmailUsingGmailSMTP.SendTheEmail(SendEmailUsingGmailSMTP.java:139)
    at Utilities.SendEmailUsingGmailSMTP.SendWeatherEmail(SendEmailUsingGmailSMTP.java:66)
    at Weather.Main.start(Main.java:43)
    at Weather.Main.main(Main.java:23)
Caused by: javax.mail.MessagingException: IOException while sending message;
  nested exception is:
    java.io.FileNotFoundException: resources/Cloudy_Day.png (No such file or directory)
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1167)
    at javax.mail.Transport.send0(Transport.java:195)
    at javax.mail.Transport.send(Transport.java:124)
    at Utilities.SendEmailUsingGmailSMTP.SendTheEmail(SendEmailUsingGmailSMTP.java:134)
    ... 3 more
Caused by: java.io.FileNotFoundException: resources/Cloudy_Day.png (No such file or directory)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:146)
    at javax.activation.FileDataSource.getInputStream(FileDataSource.java:97)
    at javax.activation.DataHandler.writeTo(DataHandler.java:305)
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1485)
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:865)
    at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:462)
    at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:103)
    at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:889)
    at javax.activation.DataHandler.writeTo(DataHandler.java:317)
    at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1485)
    at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1773)
    at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1119)
    ... 6 more
like image 328
Chiefwarpaint Avatar asked Nov 19 '14 06:11

Chiefwarpaint


People also ask

How do I view the resources folder in a JAR file?

No, resources work perfectly well in a JAR. Just don't treat a resource as a File, because it isn't one. Instead, use the getResourceAsStream() method and you'll have an InputStream from which you can read the contents of the resource.

Why can't I run an executable JAR file?

If you can't run jar files on your Windows 10 PC, you might need to reinstall Java Runtime Environment. When JAR files are not opening, another great method is to simply use a universal file opener. Alternatively, some reported that turning your JAR file into a BAT file worked perfectly.


2 Answers

Others are correct with the use of getResourceAsStream, but the path is a little tricky. You see the little package icon in the resources folder? That signifies that all the files in the resource folder will be put into the root of the classpath. Just like all the packages in src/main/java are put in the root. So you would take out the resources from the path

InputStream is = getClass().getResourceAsStream("/Cloudy_Day.png");

An aside: Maven has a file structure conventions. Class path resources are usually put into src/main/resources. If you create a resources dir in the src/main, Eclipse should automatically pick it up, and create the little package icon for a path src/main/resource that you should see in the project explorer. These files would also go to the root and could be accessed the same way. I would fix the file structure to follow this convention.

Note: A MimeBodyPart, can be Constructed from an InputStream (As suggested by Bill Shannon, this is incorrect). As mentioned in his comment below

"You can also attach the data using"

mbp.setDataHandler(new DataHandler(new ByteArrayDataSource(
          this.getClass().getResourceAsStream("/Cloudy_Day.png", "image/png"))));
like image 64
Paul Samsotha Avatar answered Oct 12 '22 17:10

Paul Samsotha


You can't access resources inside a JAR file as a File, only read them as an InputStream: getResourceAsStream().

As the MimeBodyPart has no attach() method for an InputStream, the easiest way should be to read your resources and write them to temp files, then attach these files.

like image 27
Thomas Stets Avatar answered Oct 12 '22 18:10

Thomas Stets