Read file from Springboot Resources in Docker Container - spring-boot

I am trying to send email with inline image in the email body. The code is working fine when I am running it locally from eclipse. But when it's getting dockerized and deployed to Kubernetes cluster it's unable to read the png file.
I am getting the error "java.io.FileNotFoundException: class path resource [External_Files/email_template.png] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/app.jar!/BOOT-INF/classes!/External_Files/email_template.png"
Project structure screen shot
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromEmail));
message.setSubject(AppConstants.EMAIL_SUBJECT);
MimeMultipart multipart = new MimeMultipart(AppConstants.RELATED);
MimeBodyPart messageBodyPart = new MimeBodyPart();
String html = AppConstants.EMAIL_HTML_PART_1 + recepientName +
AppConstants.EMAIL_HTML_PART_2
+ fromName + AppConstants.EMAIL_HTML_PART_3 + appProperties.getEmailOnboardPage()
+ AppConstants.EMAIL_HTML_PART_4 + appProperties.getEmailHelpPage()
+ AppConstants.EMAIL_HTML_PART_5;
messageBodyPart.setContent(html, AppConstants.TEXT_HTML);
multipart.addBodyPart(messageBodyPart);
MimeBodyPart messageBodyPart2 = new MimeBodyPart();
DataSource fds = new FileDataSource(ResourceUtils.getFile(src/main/resources/External_Files/email_template.png));
messageBodyPart2.setDataHandler(new DataHandler(fds));
messageBodyPart2.setHeader(AppConstants.CONTENT_ID, AppConstants.IMAGE_HEADER);
multipart.addBodyPart(messageBodyPart2);
message.setContent(multipart);
message.setHeader(AppConstants.X_PRIORITY, AppConstants.ONE);
message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient));
log.info("executing Transport.send");
Transport.send(message);
png

#Indranil Halder I know it's late to answer but for others who have this problem finding this issue would be useful
you can use ResourceLoader to find classpath in spring jar file
#Autowired
ResourceLoader resourceLoader;
Resource resource = resourceLoader.getResource("classpath:External_Files/email_template.png");

Related

Image is not loading until restart application

After upload an image to location dataBaseTest\src\main\resources\static\uploads\ I can't display it on webpage, until application is restarted. I know it's because folder static is loaded only when server is starting, but how can it be solved? I've tried to upload image directly to \dataBaseTest\target\classes\static\uploads\ and it is working fine (loading immedietaly after upload), but it's just not seems to be correct. Also I tried to add
<configuration>
<addResources>true</addResources>
</configuration>
to "pom.xml" but nothing has changed.
I've also tried to use addResourceHandlers but whole folder static seems to stop working.
I'm using Spring boot dev Tools, so the app is restarting automatically, but I'm trying to solve it without any restart.
~ edit
error code
~ edit 2
I'm running this app in intellij Tomcat.
this is my FileUploadService
public String uploadImage(MultipartFile multipartFile) throws IOException {
String fileName = multipartFile.getOriginalFilename();
Path uploadDirectory = Paths.get("src/main/resources/static/uploads/");
//Path uploadDirectory = Paths.get("target\\classes\\static\\uploads\\");
try (InputStream inputStream = multipartFile.getInputStream()) {
String path = UUID.randomUUID()+ "-" + fileName;
Path filePath = uploadDirectory.resolve(path);
Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);
return path;
} catch (IOException ioException){
throw new IOException("Error saving uploaded file: " + fileName, ioException);
}
}
this is controller
public String displayArticles(Model model){
final String currentName = SecurityContextHolder.getContext().getAuthentication().getName();
System.out.println(currentName);
model.addAttribute("currentUser", currentName);
model.addAttribute("articles", repoArticle.findAll());
model.addAttribute("comments", commentService.findAll());
model.addAttribute("likes", repoLikes.findByUsername(currentName));
return "display_articles";
}
this is html
<div class="image">
<img th:src="'../uploads/' + ${article.path}" alt="">
</div>
folder tree
This should save your image directly to /target folder and thus make it immediately available (note that both the application resources and code are stored in /target when the app is running)
//use the class loader to get the resource path, rather than hardcoding it
final String uploadLocation = getClass().getClassLoader().getResource("static/uploads").toString();
//we should get rid of file:/, hence the substring
final Path uploadDirectory = Paths.get(uploadLocation.substring(6, uploadLocation.length()) );
The rest of the code can remain the same.
Alternatively, you can specify your own upload folder. For instance,
application.properties
#user home should be present on any computer
files.upload.location=${user.home}/myApp/fileUpload
You would then simply retrive it in your controller,
#Autowired
private Environment environment;
...
final String uploadLocation = environment.getProperty("files.upload.location");
Hope this helps.

Spring Boot load another file from app.properties

I am new to Spring Boot. I have this emailprop.properties in src/main/resource:
//your private key
mail.smtp.dkim.privatekey=classpath:/emailproperties/private.key.der
But I am getting the error as
classpath:\email properties\private.key.der (The filename, directory
name, or volume label syntax is incorrect)
How do I properly load this file?
Update-1
my java code is
dkimSigner = new DKIMSigner(emailProps.getProperty("mail.smtp.dkim.signingdomain"), emailProps.getProperty("mail.smtp.dkim.selector"),
emailProps.getProperty("mail.smtp.dkim.privatekey"));
its working as "D:\\WorkShop\\MyDemoProj\\EmailService\\src\\main\\resources\\private.key.der"Instead of emailProps.getProperty("mail.smtp.dkim.privatekey")
Update-2
i have tried java code is
String data = "";
ClassPathResource cpr = new ClassPathResource("private.key.der");
try {
byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
data = new String(bdata, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
dkimSigner = new DKIMSigner(emailProps.getProperty("mail.smtp.dkim.signingdomain"), emailProps.getProperty("mail.smtp.dkim.selector"),data);
Error is : java.io.FileNotFoundException: class path resource [classpath:private.key.der] cannot be resolved to URL because it does not exist
Tried Code is :
ClassPathResource resource = new ClassPathResource(emailProps.getProperty("mail.smtp.dkim.privatekey"));
File file = resource.getFile();
String absolutePath = file.getAbsolutePath();
Still same error..
please update the answer..
If you want to load this file runtime then you need to use ResourceLoader please have a look here for the documentation - section 8.4.
Resource resource = resourceLoader.getResource("classpath:/emailproperties/private.key.der");
Now if you want to keep this exact path in properties file you can keep it there and then load it in your Autowired constructor/field like that:
#Value("${mail.smtp.dkim.privatekey}") String pathToPrivateKey
and then pass this to the resource loader.
Full example you can find here. I don't want to copy paste it.
If your file is located here:
"D:\\WorkShop\\MyDemoProj\\EmailService\\src\\main\\resources\\private.key.der"
then it should be:
mail.smtp.dkim.privatekey=classpath:private.key.der
EDIT:
I see now, you are using DKIMSigner, which expects file-path string,
Try changing your code like this:
ClassPathResource resource = new ClassPathResource(emailProps.getProperty("mail.smtp.dkim.privatekey"));
File file = resource.getFile();
String absolutePath = file.getAbsolutePath();
dkimSigner = new DKIMSigner(emailProps.getProperty("mail.smtp.dkim.signingdomain"), emailProps.getProperty("mail.smtp.dkim.selector"),absolutePath
);

Spring Boot and ConfigServer

We have a SpringBoot application which is successfully comunicating with config server.
The question I have is... say we have a application properties file and a csv file in config server.
when application starts if we want to get the contents of csv file too whats the better approach.
We are able to get it by doing a direct http connection to configserver and retreive the csv file contents
String url = configServerURL+"/*/*/*/example.csv";
byte[] encoded = Base64.encode((uname + ":" + password).getBytes());
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestProperty("Authorization", "Basic "+encoded);
int responseCode = con.getResponseCode();
wanted to check what options are there.

write file into spring boot folder

my spring boot project structure is like this
src
|-main
|--|-java
|--|-resources
static
|-css
|-images
|-js
now I want to write a file into the static/images folder
I tried to new File like
BufferedOutputStream stream =new BufferedOutputStream(new FileOutputStream(new File("static/images")));it will throw "No such file or directory" exception
but in other html file I can get the js by "js/jsFile.js"
new File("static/images") is right
I used new File("/static/images") so I got an Exception
I was in the situation where using Spring Boot I had to save the image into one directory which is accessed statically.
Below code worked perfect
byte[] imageByteArray ....
String fileName = "image.png";
String fileLocation = new File("static\\images").getAbsolutePath() + "\\" + fileName;
FileOutputStream fos = new FileOutputStream(fileLocation);
fos.write(imageByteArray);
fos.close();
Hope it helped.
#zhuochen shen is correct.
The thing is to happen me is Eclipse doesn't show write file. So I looked at file explore. File is writing correctly.
try {
Path path=Paths.get("static/images/"+productDto.getImage().getOriginalFilename());
Files.write(path,productDto.getImage().getBytes());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
enter image description here
enter image description here

Sending Images to the client from tomcat server

I am building a framework for e-commerce site. I have used jersey to create REST APIs. I need to send images to the clients as per the request.
How can I do so from my application server as Tomcat and jersey as REST API?
Since I am new to this, I have no clue how to send images to an Android client when they are shown as item.
Every resource is identified by the URI, client will ask for a particular image or a bunch of images by quering the URL, So you just need to expose a service, following service is an example to send single image to client.
#GET
#Path("/images/{imageId}")
#Produces("image/png")
public Response downloadImage(#PathParam("imageId") String imageId) {
MultiMediaDB imageDb = new MultiMediaDB();
String filePath = imageDb.getImage(imageId);
File file = new File(filePath);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition",
"attachment; filename=\"fileName.png\"");
return response.build();
}
MultiMediaDB is my custom class to get the file location from the DB, you can hardcode it as of now for testing purpose like D:\server_image.png.
You need to mention Content-Disposition as an attachment so that file will not be downloaded, instead attached to the form. In android you just need to read inputstream from a HttpURLConnection object and send that to bitmap as shown below
URL url = new URL(BaseUrl + "/images/" + imageId);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
iStream = urlConnection.getInputStream();
bitmap = BitmapFactory.decodeStream(iStream);
The you can set that bitmap to imageview or what ever you have as a container.

Resources