Files and resources in Java
Your file is located inside the classpath. This is a special location within your source-code (here in package utils.emailTemplate.EmailVerificationTemplate
). So we call it a classpath resource or simply resource.
Classpath resources
Usually those resources are destined to be published with your code, although they are actually not code.
In the Maven standard directory layout you would put them inside the special src/main/resources
folder, separated from code.
Locating and reading resources
Resources are located relative from classpath using the classpath:
schema. Since they are part of the sources, package-tree you can also locate them relative to one of your classes.
From your SendEmail
class, the given template has relative path ../
. So you can instantiate it as Resource
building the URL using this.getClass().getResource(Stirng relativePath)
from within your SendEmail
class:
class SendEmail {
private final String relativePath = "../emailTemplate/EmailVerificationTemplate/verification.html";
// build the URL for the resource relative from within your class
public URL getVerificaitonEmailTemplateUrl() {
URL templateResourceUrl = this.getClass().getResource(relativePath);
return templateResourceUrl;
}
// load the resource
public InputStream getVerificaitonEmailTemplateStream() {
InputStream is = this.getClass().getResourceAsStream(relativePath);
return is;
}
}
Load a resource as input-stream getResourceAsStream(String name)
using the relative path from inside your class.
Alternative using Spring's special-purpose extension ClassPathResource
:
private final String relativePath = "../emailTemplate/EmailVerificationTemplate/verification.html";
public String loadContentAsFile() {
ClassPathResource resource = new ClassPathResource(relativePath);
File file resource.getFile();
String content = new String(Files.readAllBytes(file.toPath()));
return content;
}
public InputStream getContentAsStream() {
ClassPathResource resource = new ClassPathResource(relativePath);
InputStream is resource.getInputStream();
return is;
}
Attention: This reading from a file works only if your resource is inside the file system. Not if your resource is inside a JAR:
This implementation returns a File reference for the underlying class path resource, provided that it refers to a file in the file system.
A safer and more robust way to read from the ClassPathResource
is resource.getInputStream()
.
From InputStream to String
To fix your method, you could simply exchange the File
related parts to InputStream
:
public String readHTML(InputStream is) throws IOException {
String emailContent = "";
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
while ((emailContent = bufferedReader.readLine()) != null) {
stringBuilder.append(emailContent);
}
return stringBuilder.toString();
}
Or even simpler (see Baeldung's tutorial linked below):
String text = new BufferedReader(
new InputStreamReader(inputStream, StandardCharsets.UTF_8)) // choose the encoding to fit
.lines()
.collect(Collectors.joining("\n"));
Then re-use it to read from any stream (e.g. a File
, a Resource
, ClassPathResource
, even a URL
). For example:
public String loadTemplate(String relativeResourcePath) throws IOException {
InputStream inputStream = this.getClass().getResourceAsStream(relativeResourcePath)
String text = new BufferedReader(
new InputStreamReader(inputStream, StandardCharsets.UTF_8))
.lines()
.collect(Collectors.joining("\n"));
return text;
}
See also