Merge pull request 'custom exceptions added' (#8) from exception into master

Reviewed-on: #8
pull/10/head
commit 23ff720b71

@ -4,6 +4,8 @@ package entgra.mailsender.Controller;
import entgra.mailsender.DTO.MailModel; import entgra.mailsender.DTO.MailModel;
import entgra.mailsender.Service.MailService; import entgra.mailsender.Service.MailService;
import entgra.mailsender.exception.MailException; import entgra.mailsender.exception.MailException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException;
@RestController @RestController
@RequestMapping("/api/message-distribution/email") @RequestMapping("/api/message-distribution/email")
@ -21,6 +24,9 @@ public class MailController {
@Autowired @Autowired
public MailService mailService; public MailService mailService;
private static final Logger logger = LoggerFactory.getLogger(MailController.class);
@PostMapping @PostMapping
public ResponseEntity<String> sendEmail(@ModelAttribute MailModel emailModel) { public ResponseEntity<String> sendEmail(@ModelAttribute MailModel emailModel) {
String msg; String msg;
@ -30,11 +36,12 @@ public class MailController {
return ResponseEntity.ok(msg); return ResponseEntity.ok(msg);
} catch (MailException e) { } catch (MailException e) {
msg = "Invalid email address"; msg = "Invalid email address";
logger.error(msg, e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(msg); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(msg);
} catch (MessagingException | IOException exception) { } catch (MessagingException | SQLException | IOException exception) {
msg = "Failed to send email"; msg = "Failed to send email";
logger.error(msg, exception);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(msg + exception); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(msg + exception);
} }
} }
} }

@ -4,12 +4,12 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import entgra.mailsender.DAO.MailDAO; import entgra.mailsender.DAO.MailDAO;
import entgra.mailsender.DTO.MailModel; import entgra.mailsender.DTO.MailModel;
import entgra.mailsender.exception.DatabaseAccessException;
import entgra.mailsender.exception.FileConversionException;
import entgra.mailsender.exception.MailProcessingException;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.File; import java.io.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@ -26,82 +26,83 @@ import java.util.logging.Logger;
@Component @Component
public class MailDAOImpl implements MailDAO { public class MailDAOImpl implements MailDAO {
Logger logger = Logger.getLogger(String.valueOf(MailDAOImpl.class)); Logger logger = Logger.getLogger(String.valueOf(MailDAOImpl.class));
private Connection getConnection() throws SQLException { private Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/email_sending", "root", "StrongPassword123!"); return DriverManager.getConnection("jdbc:mysql://localhost:3306/email_sending", "root", "StrongPassword123!");
} }
@Override @Override
public int addMail(MailModel mailModel){ public int addMail(MailModel mailModel) throws SQLException {
PreparedStatement stmt; try {
int generatedId = -1; PreparedStatement stmt;
int generatedId;
try { Connection conn = this.getConnection();
Connection conn = this.getConnection(); stmt = conn.prepareStatement("INSERT INTO email (EMAIL_ADDRESS, MSG_TEMPLATE, PRIORITY, ATTACHMENT, PARAMETERS, TIME, FILENAME, EXPIRY_AT) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", PreparedStatement.RETURN_GENERATED_KEYS);
stmt = conn.prepareStatement("INSERT INTO email (EMAIL_ADDRESS, MSG_TEMPLATE, PRIORITY, ATTACHMENT, PARAMETERS, TIME, FILENAME, EXPIRY_AT) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", PreparedStatement.RETURN_GENERATED_KEYS); Timestamp current_time = new Timestamp(System.currentTimeMillis());
Timestamp current_time = new Timestamp(System.currentTimeMillis()); String parametersJson = new ObjectMapper().writeValueAsString(mailModel.getParameters());
String parametersJson = new ObjectMapper().writeValueAsString(mailModel.getParameters()); stmt.setString(1, mailModel.getEmailAddress());
stmt.setString(1,mailModel.getEmailAddress()); stmt.setString(2, mailModel.getMsgTemplate());
stmt.setString(2,mailModel.getMsgTemplate()); stmt.setInt(3, mailModel.getPriority());
stmt.setInt(3,mailModel.getPriority()); stmt.setBytes(4, mailModel.getAttachment().getBytes());
stmt.setBytes(4,mailModel.getAttachment().getBytes());
stmt.setString(5, parametersJson); stmt.setString(5, parametersJson);
stmt.setTimestamp(6,current_time); stmt.setTimestamp(6, current_time);
String filename = mailModel.getAttachment().getOriginalFilename(); String filename = mailModel.getAttachment().getOriginalFilename();
stmt.setString(7,filename); stmt.setString(7, filename);
stmt.setDate(8,mailModel.getExpiry_at()); stmt.setDate(8, mailModel.getExpiry_at());
stmt.executeUpdate(); stmt.executeUpdate();
ResultSet rs = stmt.getGeneratedKeys(); ResultSet rs = stmt.getGeneratedKeys();
if (rs.next()) { if (rs.next()) {
generatedId = rs.getInt(1); generatedId = rs.getInt(1);
return generatedId;
}
} catch (SQLException e) {
logger.info(e.getMessage());
throw new SQLException("error processing sql !!", e);
} catch (IOException e) {
logger.info(e.getMessage());
throw new MailProcessingException("Error processing mailModel", e);
} }
logger.info("Stored successfully");
} catch (SQLException e) {
logger.info(e.getMessage());
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
return generatedId;
}
return 0;
}
@Override @Override
public List<MailModel> getUnsentMessages(){ public List<MailModel> getUnsentMessages() {
String sql = "SELECT * FROM email WHERE email_id NOT IN (SELECT email_id FROM sentEmail)"; String sql = "SELECT * FROM email WHERE email_id NOT IN (SELECT email_id FROM sentEmail)";
List<MailModel> unsentMails = new ArrayList<>(); List<MailModel> unsentMails = new ArrayList<>();
try(Connection connection = this.getConnection(); try (Connection connection = this.getConnection();
PreparedStatement statement = connection.prepareStatement(sql); PreparedStatement statement = connection.prepareStatement(sql);
ResultSet rs = statement.executeQuery()) { ResultSet rs = statement.executeQuery()) {
while (rs.next()){ while (rs.next()) {
MailModel mailModel = new MailModel(); MailModel mailModel = new MailModel();
mailModel.setEmailId(rs.getInt("email_id")); mailModel.setEmailId(rs.getInt("email_id"));
mailModel.setPriority(rs.getInt("priority")); mailModel.setPriority(rs.getInt("priority"));
mailModel.setExpiry_at(rs.getDate("expiry_at")); mailModel.setExpiry_at(rs.getDate("expiry_at"));
unsentMails.add(mailModel); unsentMails.add(mailModel);
}
} catch (SQLException e) {
logger.info(e.getMessage());
throw new DatabaseAccessException("Error accessing database", e);
} }
} catch (SQLException e) { return unsentMails;
throw new RuntimeException(e);
}
return unsentMails;
} }
@Override @Override
public MailModel getMailDetails(Integer mail_id){ public MailModel getMailDetails(Integer mail_id) {
String sql = "SELECT * FROM email WHERE email_id = ?"; String sql = "SELECT * FROM email WHERE email_id = ?";
MailModel mailModel = new MailModel(); MailModel mailModel = new MailModel();
try { try {
Connection conn = this.getConnection(); Connection conn = this.getConnection();
try(PreparedStatement stmt = conn.prepareStatement(sql)) { try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setInt(1,mail_id); stmt.setInt(1, mail_id);
try(ResultSet rs = stmt.executeQuery()) { try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()){ while (rs.next()) {
mailModel.setEmailId(rs.getInt("email_id")); mailModel.setEmailId(rs.getInt("email_id"));
mailModel.setEmailAddress(rs.getString("email_address")); mailModel.setEmailAddress(rs.getString("email_address"));
mailModel.setMsgTemplate(rs.getString("msg_template")); mailModel.setMsgTemplate(rs.getString("msg_template"));
@ -111,38 +112,38 @@ public MailModel getMailDetails(Integer mail_id){
List<MailModel.Parameter> parameters = parseJsonParameters(jsonData); List<MailModel.Parameter> parameters = parseJsonParameters(jsonData);
mailModel.setParameters(parameters); mailModel.setParameters(parameters);
String filename = rs.getString("filename"); String filename = rs.getString("filename");
mailModel.setFilename(filename); mailModel.setFilename(filename);
Blob blob = rs.getBlob("attachment"); Blob blob = rs.getBlob("attachment");
File file = convertBlobToFile(blob,filename); File file = convertBlobToFile(blob, filename);
mailModel.setFile(file); mailModel.setFile(file);
} }
return mailModel; return mailModel;
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); logger.info(e.getMessage());
throw new MailProcessingException("Error processing mail", e);
} }
} }
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e); logger.info(e.getMessage());
throw new DatabaseAccessException("Error accessing database", e);
} }
} }
private List<MailModel.Parameter> parseJsonParameters(String parametersJson) { private List<MailModel.Parameter> parseJsonParameters(String parametersJson) {
try { try {
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(parametersJson, new TypeReference<>() { return objectMapper.readValue(parametersJson, new TypeReference<>() {
}); });
} catch (IOException e) { } catch (IOException e) {
logger.info(e.getMessage());
throw new IllegalArgumentException("Error parsing parameters JSON", e); throw new IllegalArgumentException("Error parsing parameters JSON", e);
} }
} }
public static File convertBlobToFile(Blob blob, String fileName) throws IOException, SQLException { public static File convertBlobToFile(Blob blob, String fileName) throws IOException, SQLException {
File file = new File(fileName); File file = new File(fileName);
try (FileOutputStream outputStream = new FileOutputStream(file)) { try (FileOutputStream outputStream = new FileOutputStream(file)) {
InputStream inputStream = blob.getBinaryStream(); InputStream inputStream = blob.getBinaryStream();
@ -150,31 +151,25 @@ public static File convertBlobToFile(Blob blob, String fileName) throws IOExcept
while (inputStream.read(buffer) > 0) { while (inputStream.read(buffer) > 0) {
outputStream.write(buffer); outputStream.write(buffer);
} }
} catch (IOException e) {
throw new FileConversionException("Error converting Blob to File", e);
} }
return file; return file;
} }
public void addToSentMail(Integer mail_id){ public void addToSentMail(Integer mail_id) {
PreparedStatement stmt; try {
PreparedStatement stmt;
try { Connection connection = this.getConnection();
Connection connection = this.getConnection(); stmt = connection.prepareStatement("INSERT INTO sentEmail (email_id,sent_time) VALUE (?,?)");
stmt = connection.prepareStatement("INSERT INTO sentEmail (email_id,sent_time) VALUE (?,?)"); stmt.setInt(1, mail_id);
stmt.setInt(1,mail_id);
stmt.setDate(2, Date.valueOf(LocalDate.now())); stmt.setDate(2, Date.valueOf(LocalDate.now()));
stmt.execute(); stmt.execute();
logger.info("added to sent_email successfully"); } catch (SQLException e) {
logger.info(e.getMessage());
} catch (SQLException e) { throw new DatabaseAccessException("Error accessing database", e);
throw new RuntimeException(e); }
} }
}
}
}

@ -2,11 +2,12 @@ package entgra.mailsender.DAO;
import entgra.mailsender.DTO.MailModel; import entgra.mailsender.DTO.MailModel;
import java.sql.SQLException;
import java.util.List; import java.util.List;
public interface MailDAO { public interface MailDAO {
int addMail(MailModel mailModel); int addMail(MailModel mailModel) throws SQLException;
MailModel getMailDetails(Integer mail_id); MailModel getMailDetails(Integer mail_id);

@ -6,6 +6,7 @@ import entgra.mailsender.Service.MailQueueService;
import entgra.mailsender.Service.MailService; import entgra.mailsender.Service.MailService;
import entgra.mailsender.exception.BadRequestException; import entgra.mailsender.exception.BadRequestException;
import entgra.mailsender.exception.MailException; import entgra.mailsender.exception.MailException;
import entgra.mailsender.exception.QueueException;
import entgra.mailsender.util.PriorityQueueHolder; import entgra.mailsender.util.PriorityQueueHolder;
import jakarta.annotation.PreDestroy; import jakarta.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -13,6 +14,7 @@ import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -26,7 +28,6 @@ public class MailServiceImpl implements MailService {
@Autowired @Autowired
private MailQueueService mailQueueService; private MailQueueService mailQueueService;
@PreDestroy @PreDestroy
public void shutdown() { public void shutdown() {
shutdownRequested = true; shutdownRequested = true;
@ -39,16 +40,14 @@ public class MailServiceImpl implements MailService {
@Autowired @Autowired
private MailDAO mailDAO; private MailDAO mailDAO;
public void sendEmail(MailModel emailModel) throws MailException, SQLException {
public void sendEmail(MailModel emailModel) throws MailException {
if (shutdownRequested) { if (shutdownRequested) {
String msg = "Server is shutting down. SMS requests will not be accepted."; String msg = "Server is shutting down. SMS requests will not be accepted.";
logger.warning(msg); logger.warning(msg);
throw new BadRequestException(msg); throw new BadRequestException(msg);
} }
if (isValidEmailAddress(emailModel.getEmailAddress())){ if (isValidEmailAddress(emailModel.getEmailAddress())) {
String msg = "Invalid Email address"; String msg = "Invalid Email address";
logger.warning(msg); logger.warning(msg);
throw new BadRequestException(msg); throw new BadRequestException(msg);
@ -64,13 +63,14 @@ public class MailServiceImpl implements MailService {
try { try {
mailQueueService.enqueMails(mailModels); mailQueueService.enqueMails(mailModels);
} catch (Exception e){ } catch (Exception e) {
throw new RuntimeException(e); logger.info(e.getMessage());
throw new QueueException("Error processing Queue", e);
} }
//send the high priority mail //send the high priority mail
while (PriorityQueueHolder.getInstance().getPriorityQueue().peek() != null){ while (PriorityQueueHolder.getInstance().getPriorityQueue().peek() != null) {
MailModel prioritizedMail =mailQueueService.getHighPriorityMail(); MailModel prioritizedMail = mailQueueService.getHighPriorityMail();
javaMailSender.send(mimeMessage -> { javaMailSender.send(mimeMessage -> {
@ -101,25 +101,25 @@ public class MailServiceImpl implements MailService {
} }
} }
public boolean isValidEmailAddress(String email){ public boolean isValidEmailAddress(String email) {
String regex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$"; String regex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
return !email.matches(regex); return !email.matches(regex);
} }
public void syncMailWithDB(){ public void syncMailWithDB() {
try { try {
List<MailModel> mailModels = mailDAO.getUnsentMessages(); List<MailModel> mailModels = mailDAO.getUnsentMessages();
if (!mailModels.isEmpty()){ if (!mailModels.isEmpty()) {
mailQueueService.enqueMails(mailModels); mailQueueService.enqueMails(mailModels);
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); logger.info(e.getMessage());
throw new QueueException("Error processing Queue", e);
} }
while(PriorityQueueHolder.getInstance().getPriorityQueue().peek() != null) { while (PriorityQueueHolder.getInstance().getPriorityQueue().peek() != null) {
MailModel prioritizedMail = mailDAO.getMailDetails(mailQueueService.getHighPriorityMail().getEmailId()); MailModel prioritizedMail = mailDAO.getMailDetails(mailQueueService.getHighPriorityMail().getEmailId());
javaMailSender.send(mimeMessage -> { javaMailSender.send(mimeMessage -> {
@ -145,10 +145,10 @@ public class MailServiceImpl implements MailService {
// Append text to email body // Append text to email body
mimeMessageHelper.setText(emailBody.toString(), false); mimeMessageHelper.setText(emailBody.toString(), false);
// Append attachments to email body // Append attachments to email body
mimeMessageHelper.addAttachment(prioritizedMail.getFilename(), prioritizedMail.getFile()); mimeMessageHelper.addAttachment(prioritizedMail.getFilename(), prioritizedMail.getFile());
//Store the sent mail to the table //Store the sent mail to the table
mailDAO.addToSentMail(prioritizedMail.getEmailId()); mailDAO.addToSentMail(prioritizedMail.getEmailId());
@ -158,5 +158,4 @@ public class MailServiceImpl implements MailService {
} }
}
}

@ -6,10 +6,11 @@ import entgra.mailsender.exception.MailException;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException;
public interface MailService { public interface MailService {
void sendEmail(MailModel emailModel) throws MessagingException, IOException, BadRequestException, MailException; void sendEmail(MailModel emailModel) throws MessagingException, IOException, BadRequestException, MailException, SQLException;
boolean isValidEmailAddress(String email); boolean isValidEmailAddress(String email);

@ -0,0 +1,11 @@
package entgra.mailsender.exception;
public class DatabaseAccessException extends RuntimeException{
public DatabaseAccessException(String message) {
super(message);
}
public DatabaseAccessException(String message, Throwable cause) {
super(message, cause);
}
}

@ -0,0 +1,11 @@
package entgra.mailsender.exception;
public class FileConversionException extends RuntimeException{
public FileConversionException(String message) {
super(message);
}
public FileConversionException(String message, Throwable cause) {
super(message, cause);
}
}

@ -0,0 +1,11 @@
package entgra.mailsender.exception;
public class MailProcessingException extends RuntimeException{
public MailProcessingException(String msg){
super(msg);
}
public MailProcessingException(String msg, Throwable cause){
super(msg,cause);
}
}

@ -0,0 +1,11 @@
package entgra.mailsender.exception;
public class QueueException extends RuntimeException{
public QueueException(String message){
super(message);
}
public QueueException(String message, Throwable cause) {
super(message, cause);
}
}
Loading…
Cancel
Save