Is it possible to send email from the core module? I created entity listener so I want to send emails each time when the entity changes but I’m faced with Security Exception: No security context bound to the current thread
Tried setSecurityContext as well as annotation @Authenticated, but nothing helps. Any Ideas?
Here is the listener itself:
package com.company.tenderflow.listener;
import com.company.tenderflow.entity.Mailing;
import com.company.tenderflow.entity.Marketplace;
import com.company.tenderflow.entity.Tender;
import com.company.tenderflow.entity.TenderSearch;
import com.company.tenderflow.managedBeans.TenderSearchBean;
import com.company.tenderflow.managedBeans.TenderBean;
import com.company.tenderflow.managedBeans.DocumentBean;
import com.haulmont.cuba.core.EntityManager;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.app.EmailService;
import com.haulmont.cuba.core.global.EmailAttachment;
import com.haulmont.cuba.core.global.EmailInfo;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener;
import com.haulmont.cuba.core.sys.AppContext;
import com.company.tenderflow.parser.DataHelper;
import com.haulmont.cuba.core.sys.SecurityContext;
import com.haulmont.cuba.security.app.Authenticated;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.springframework.stereotype.Component;
import javax.inject.Inject;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Created by Liya.Azancheeva on 26.06.2018.
*/
@Component("tenderflow_TenderSearchEntityListener")
public class TenderSearchEntityListener implements BeforeUpdateEntityListener<TenderSearch> {
final SecurityContext securityContext = AppContext.getSecurityContext();
@Inject
protected EmailService emailService;
@Inject
private DocumentBean documentBean;
@Inject
private TenderBean tenderBean;
@Inject
private TenderSearchBean tenderSearchBean;
private DataHelper dh = new DataHelper();
@Inject
private Persistence persistence;
@Override
@Authenticated
public void onBeforeUpdate(TenderSearch entity, EntityManager entityManager) {
System.out.println("@@@!!!!!!!@@@!");
// If the user's "name" attribute has been changed
if (persistence.getTools().getDirtyFields(entity).contains("state") && entity.getState()) {
TimerTask task = new SearchTask(entity);
java.util.Timer timer = new java.util.Timer();
int period = Integer.parseInt(entity.getInterval().toString())*86400000 ;
timer.schedule( task, 0, period);
}
}
@Authenticated
private int startParse(TenderSearch tenderSearch) {
ArrayList<Tender> savedTenders = new ArrayList<>();
String[] keywords = tenderSearch.getKeyword().split("\\s*,\\s*");
DateFormat df = new SimpleDateFormat("dd.MM.yyyy");
Date publishDateFrom = tenderSearch.getPublishDateFrom();
Date updateDateFrom = tenderSearch.getUpdateDateFrom();
Date lastSearchDate = tenderSearch.getLastSearchDate();
String lastSearchDateString = tenderSearch.getLastSearchDate() != null ? df.format(lastSearchDate) : "";
String publishDateFromString = tenderSearch.getPublishDateFrom() != null ? df.format(publishDateFrom) : lastSearchDateString;
String updateDateFromString = tenderSearch.getUpdateDateFrom() != null ? df.format(updateDateFrom) : lastSearchDateString;
String priceFrom = tenderSearch.getPriceFrom()!= null ? tenderSearch.getPriceFrom().toString() : "";
String priceTo = tenderSearch.getPriceTo() != null ? tenderSearch.getPriceTo().toString() : "";
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
try {
Iterator<Marketplace> i = tenderSearch.getMarketplaces().iterator();
while (i.hasNext()) {
engine.eval(i.next().getScript());
Invocable invocable = (Invocable) engine;
for (String keyword : keywords) {
System.out.println(keyword);
invocable.invokeFunction("init", keyword, publishDateFromString, updateDateFromString, priceFrom, priceTo);
ArrayList<ScriptObjectMirror> result = (ArrayList<ScriptObjectMirror>) invocable.invokeFunction("searchTenders");
ArrayList<Tender> validTenders = dh.getTendersList(result, tenderSearch);
savedTenders = tenderBean.saveUnique(validTenders, tenderSearch);
}
tenderSearchBean.updateLastSearchDate(tenderSearch);
System.out.println("найдено новых тендеров: "+ savedTenders.size());
if (savedTenders.size()>0) {
//mailingService.sendByEmail(savedTenders, tenderSearch);
sendByEmail(savedTenders, tenderSearch);
}
}
} catch (ScriptException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return savedTenders.size();
}
@Authenticated
public void sendByEmail(List<Tender> tenders, TenderSearch tenderSearch) {
byte[] xls = documentBean.createXLS(tenders);
EmailAttachment xlsAttach = new EmailAttachment(xls, tenderSearch.getName()+".xls");
StringBuilder sb = new StringBuilder();
sb.append("По проекту \"" + tenderSearch.getName() + "\" найдены новые тендеры. ");
for (Mailing mail : tenderSearch.getMailings()) {
EmailInfo emailInfo = new EmailInfo(mail.getEmail(), tenderSearch.getName(), null, sb.toString(), xlsAttach);
emailService.sendEmailAsync(emailInfo);
}
}
private class SearchTask extends TimerTask {
TenderSearch tenderSearch;
public SearchTask (TenderSearch tenderSearch ){
this.tenderSearch=tenderSearch;
}
@Authenticated
public void run() {
AppContext.setSecurityContext(securityContext);
System.out.println("Запущен автоматический поиск тендеров по проекту \"" + tenderSearch.getName() + "\"");
int changed = startParse(tenderSearch);
System.out.println("Завершена работа над проектом \"" + tenderSearch.getName() + "\", изменено записей: " + changed);
tenderSearch.setLastSearchDate(new Date());
}
}
}