Remove notifications from queue when associated project or task deleted

Prevents a HibernateObjectRetrievalFailureException from being thrown when a scheduled email notification
job attempts to send a notification associated to a project or task that was deleted prior to
the scheduled job running.

Fixes #4
This commit is contained in:
lmann99 2017-01-21 22:50:13 -05:00
parent 2b1a91a9f6
commit b101d18e9e
7 changed files with 144 additions and 1 deletions

View file

@ -23,8 +23,12 @@ import org.hibernate.criterion.Restrictions;
import org.libreplan.business.common.daos.GenericDAOHibernate;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.planner.entities.TaskElement;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
//import java.util.ArrayList;
import java.util.List;
/**
@ -50,6 +54,22 @@ public class EmailNotificationDAO
.list();
}
@Override
public List<EmailNotification> getAllByProject(TaskElement taskElement) {
return getSession()
.createCriteria(EmailNotification.class)
.add(Restrictions.eq("project", taskElement))
.list();
}
@Override
public List<EmailNotification> getAllByTask(TaskElement taskElement) {
return getSession()
.createCriteria(EmailNotification.class)
.add(Restrictions.eq("task", taskElement))
.list();
}
@Override
public boolean deleteAll() {
List<EmailNotification> notifications = list(EmailNotification.class);
@ -89,4 +109,26 @@ public class EmailNotificationDAO
.uniqueResult() == null;
}
@Override
public boolean deleteByProject(TaskElement taskElement) {
List<EmailNotification> notifications = getAllByProject(taskElement);
for (Object item : notifications){
getSession().delete(item);
}
return getAllByProject(taskElement).isEmpty();
}
@Override
public boolean deleteByTask(TaskElement taskElement) {
List<EmailNotification> notifications = getAllByTask(taskElement);
for (Object item : notifications){
getSession().delete(item);
}
return getAllByTask(taskElement).isEmpty();
}
}

View file

@ -22,6 +22,8 @@ package org.libreplan.business.email.daos;
import org.libreplan.business.common.daos.IGenericDAO;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.planner.entities.TaskElement;
import java.util.List;
@ -36,9 +38,18 @@ public interface IEmailNotificationDAO extends IGenericDAO<EmailNotification, Lo
List<EmailNotification> getAllByType(EmailTemplateEnum enumeration);
List<EmailNotification> getAllByProject(TaskElement taskElement);
List<EmailNotification> getAllByTask(TaskElement taskElement);
boolean deleteAll();
boolean deleteAllByType(EmailTemplateEnum enumeration);
boolean deleteById(EmailNotification notification);
boolean deleteByProject(TaskElement taskElement);
boolean deleteByTask(TaskElement taskElement);
}

View file

@ -39,6 +39,7 @@ import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;
import org.libreplan.business.common.daos.IntegrationEntityDAO;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.email.daos.IEmailNotificationDAO;
import org.libreplan.business.expensesheet.daos.IExpenseSheetLineDAO;
import org.libreplan.business.labels.entities.Label;
import org.libreplan.business.orders.entities.Order;
@ -46,6 +47,7 @@ import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.SchedulingDataForVersion;
import org.libreplan.business.orders.entities.TaskSource;
import org.libreplan.business.planner.daos.ITaskSourceDAO;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.resources.entities.Criterion;
import org.libreplan.business.templates.entities.OrderElementTemplate;
import org.libreplan.business.workingday.EffortDuration;
@ -84,6 +86,9 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement> implemen
@Autowired
private ITaskSourceDAO taskSourceDAO;
@Autowired
private IEmailNotificationDAO emailNotificationDAO;
@Override
public List<OrderElement> findWithoutParent() {
return getSession()
@ -142,6 +147,9 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement> implemen
@Override
public void remove(Long id) throws InstanceNotFoundException {
OrderElement orderElement = find(id);
removeNotifications(orderElement);
removeTaskSourcesFor(this.taskSourceDAO, orderElement);
for (WorkReport each : getWorkReportsPointingTo(orderElement)) {
@ -151,6 +159,17 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement> implemen
super.remove(id);
}
public void removeNotifications(OrderElement orderElement) {
List<SchedulingDataForVersion> allVersions = orderElement.getSchedulingDataForVersionFromBottomToTop();
for (TaskSource each : taskSourcesFrom(allVersions)) {
TaskElement taskElement = each.getTask();
if ( taskElement != null) {
emailNotificationDAO.deleteByTask(taskElement);
}
}
}
public static void removeTaskSourcesFor(ITaskSourceDAO taskSourceDAO, OrderElement orderElement)
throws InstanceNotFoundException {

View file

@ -22,6 +22,7 @@ package org.libreplan.web.email;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.email.daos.IEmailNotificationDAO;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.planner.entities.TaskElement;
@ -68,6 +69,17 @@ public class EmailNotificationModel implements IEmailNotificationModel {
return emailNotificationDAO.getAllByType(enumeration);
}
@Override
@Transactional
public List<EmailNotification> getAllByProject(TaskElement taskElement) {
return emailNotificationDAO.getAllByProject(taskElement);
}
@Override
@Transactional
public List<EmailNotification> getAllByTask(TaskElement taskElement) {
return emailNotificationDAO.getAllByTask(taskElement);
}
@Override
@Transactional
public boolean deleteAll() {
@ -85,6 +97,18 @@ public class EmailNotificationModel implements IEmailNotificationModel {
return emailNotificationDAO.deleteById(notification);
}
@Override
@Transactional
public boolean deleteByProject(TaskElement taskElement) {
return emailNotificationDAO.deleteByProject(taskElement);
}
@Override
@Transactional
public boolean deleteByTask(TaskElement taskElement) {
return emailNotificationDAO.deleteByTask(taskElement);
}
@Override
public void setType(EmailTemplateEnum type) {
this.emailNotification.setType(type);
@ -110,11 +134,12 @@ public class EmailNotificationModel implements IEmailNotificationModel {
this.emailNotification.setProject(project);
}
@Override
public EmailNotification getEmailNotification() {
return emailNotification;
}
@Override
public void setNewObject(){
this.emailNotification = new EmailNotification();
}

View file

@ -21,6 +21,7 @@ package org.libreplan.web.email;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.resources.entities.Resource;
@ -41,12 +42,20 @@ public interface IEmailNotificationModel {
List<EmailNotification> getAllByType(EmailTemplateEnum enumeration);
List<EmailNotification> getAllByProject(TaskElement taskElement);
List<EmailNotification> getAllByTask(TaskElement taskElement);
boolean deleteAll();
boolean deleteAllByType(EmailTemplateEnum enumeration);
boolean deleteById(EmailNotification notification);
boolean deleteByProject(TaskElement taskElement);
boolean deleteByTask(TaskElement taskElement);
void setType(EmailTemplateEnum type);
void setUpdated(Date date);
@ -60,4 +69,5 @@ public interface IEmailNotificationModel {
EmailNotification getEmailNotification();
void setNewObject();
}

View file

@ -47,6 +47,7 @@ import org.libreplan.business.common.daos.IConfigurationDAO;
import org.libreplan.business.common.entities.Configuration;
import org.libreplan.business.common.entities.EntityNameEnum;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO;
import org.libreplan.business.externalcompanies.entities.EndDateCommunication;
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
@ -60,6 +61,7 @@ import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderLineGroup;
import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.planner.entities.PositionConstraintType;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.qualityforms.daos.IQualityFormDAO;
import org.libreplan.business.qualityforms.entities.QualityForm;
import org.libreplan.business.requirements.entities.DirectCriterionRequirement;
@ -84,6 +86,7 @@ import org.libreplan.business.users.entities.UserRole;
import org.libreplan.web.calendars.BaseCalendarModel;
import org.libreplan.web.common.IntegrationEntityModel;
import org.libreplan.web.common.concurrentdetection.OnConcurrentModification;
import org.libreplan.web.email.IEmailNotificationModel;
import org.libreplan.web.logs.IIssueLogModel;
import org.libreplan.web.logs.IRiskLogModel;
import org.libreplan.web.orders.files.IOrderFileModel;
@ -181,6 +184,9 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
@Autowired
private IIssueLogModel issueLogModel;
@Autowired
private IEmailNotificationModel emailNotificationModel;
private List<Order> orderList = new ArrayList<>();
@Override
@ -522,6 +528,8 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
public void remove(Order detachedOrder) {
Order order = orderDAO.findExistingEntity(detachedOrder.getId());
removeNotifications(order);
removeFiles(order);
removeLogs(order);
@ -542,6 +550,18 @@ public class OrderModel extends IntegrationEntityModel implements IOrderModel {
orderFileModel.findByParent(order).forEach(orderFile -> orderFileModel.delete(orderFile));
}
private void removeNotifications(Order order) {
for ( Scenario scenario: currentAndDerivedScenarios()) {
order.useSchedulingDataFor(scenario.getOrderVersion(order));
TaskElement taskElement = order.getTaskElement();
if ( taskElement != null) {
emailNotificationModel.deleteByProject(taskElement);
}
}
}
private void removeVersions(Order order) {
Map<Long, OrderVersion> versionsRemovedById = new HashMap<>();
List<Scenario> currentAndDerived = currentAndDerivedScenarios();

View file

@ -2,7 +2,9 @@ package org.libreplan.web.test.ws.email;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.libreplan.business.common.Registry;
@ -167,6 +169,20 @@ public class EmailTest {
assertTrue(EmailConnectionValidator.exceptionType instanceof MessagingException);
}
@Test
@Transactional
public void testDDeleteEmailNotification() {
EmailTemplate emailTemplate = createEmailTemplate();
emailTemplateDAO.save(emailTemplate);
EmailNotification emailNotification = createEmailNotification();
emailNotificationDAO.save(emailNotification);
emailTemplateDAO.delete(emailTemplate);
boolean result = emailNotificationDAO.deleteByProject(emailNotification.getProject());
assertTrue(result);
}
private EmailTemplate createEmailTemplate() {
EmailTemplate emailTemplate = new EmailTemplate();
emailTemplate.setType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START);