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 fin
Try this
new MimeBodyPart().attachFile(new File(this.getClass().getClassLoader().getResource("resources/Cloudy_Day.png").toURI());
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 (As suggested by Bill Shannon, this is incorrect). As mentioned in his comment belowInputStream
"You can also attach the data using"
mbp.setDataHandler(new DataHandler(new ByteArrayDataSource(
this.getClass().getResourceAsStream("/Cloudy_Day.png", "image/png"))));
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.
I don't know if this will help anyone or not. But, I have a similar case as the OP and I solved the case by finding the file in the classpath using recursive function. The idea is so that when another developer decided to move the resources into another folder/path. It will still be found as long as the name is still the same.
For example, in my work we usually put our resources outside the jar, and then we add said resources path into our classpath, so here the classpath of the resources will be different depending on where it is located.
That's where my code comes to work, no matter where the file is put, as long as it's in the classpath it will be found.
Here is an example of my code in action:
import java.io.File;
public class FindResourcesRecursive {
public File findConfigFile(String paths, String configFilename) {
for (String p : paths.split(File.pathSeparator)) {
File result = findConfigFile(new File(p), configFilename);
if (result != null) {
return result;
}
}
return null;
}
private File findConfigFile(File path, String configFilename) {
if (path.isDirectory()) {
String[] subPaths = path.list();
if (subPaths == null) {
return null;
}
for (String sp : subPaths) {
File subPath = new File(path.getAbsoluteFile() + "/" + sp);
File result = findConfigFile(subPath, configFilename);
if (result != null && result.getName().equalsIgnoreCase(configFilename)) {
return result;
}
}
return null;
} else {
File file = path;
if (file.getName().equalsIgnoreCase(configFilename)) {
return file;
}
return null;
}
}
}
Here I have a test case that is coupled with a file "test.txt" in my test/resources folder. The content of said file is:
A sample file
Now, here is my test case:
import org.junit.Test;
import java.io.*;
import static org.junit.Assert.fail;
public class FindResourcesRecursiveTest {
@Test
public void testFindFile() {
// Here in the test resources I have a file "test.txt"
// Inside it is a string "A sample file"
// My Unit Test will use the class FindResourcesRecursive to find the file and print out the results.
File testFile = new FindResourcesRecursive().findConfigFile(
System.getProperty("java.class.path"),
"test.txt"
);
try (FileInputStream is = new FileInputStream(testFile)) {
int i;
while ((i = is.read()) != -1) {
System.out.print((char) i);
}
System.out.println();
} catch (IOException e) {
fail();
}
}
}
Now, if you run this test, it will print out "A sample file" and the test will be green.