我有一个申请。在应用程序启动时,我每隔24秒唤醒我的akka演员。 Actor遍历JPA.withTransaction中的一些实体,做一些工作并向我的用户发送电子邮件。
当抛出运行时异常时,问题在JPA.withTransaction方法中调用render方法(用于呈现scala模板):此处没有Htto Context
[error] - akka.actor.OneForOneStrategy - JPA transaction failed
11:50:42 worker.1 | java.lang.RuntimeException: JPA transaction failed
11:50:42 worker.1 | at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:107) ~[play-java-jpa_2.11-2.4.6.jar:2.4.6]
11:50:42 worker.1 | at play.db.jpa.JPA.withTransaction(JPA.java:148) ~[play-java-jpa_2.11-2.4.6.jar:2.4.6]
11:50:42 worker.1 | at utils.MedicalValidityActor.onReceive(MedicalValidityActor.java:35) ~[classes/:na]
11:50:42 worker.1 | at akka.actor.UntypedActor$$anonfun$receive$1.applyOrElse(UntypedActor.scala:167) ~[akka-actor_2.11-2.3.13.jar:na]
11:50:42 worker.1 | at akka.actor.Actor$class.aroundReceive(Actor.scala:467) ~[akka-actor_2.11-2.3.13.jar:na]
11:50:42 worker.1 | at akka.actor.UntypedActor.aroundReceive(UntypedActor.scala:97) ~[akka-actor_2.11-2.3.13.jar:na]
11:50:42 worker.1 | at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516) [akka-actor_2.11-2.3.13.jar:na]
11:50:42 worker.1 | at akka.actor.ActorCell.invoke(ActorCell.scala:487) [akka-actor_2.11-2.3.13.jar:na]
11:50:42 worker.1 | at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238) [akka-actor_2.11-2.3.13.jar:na]
11:50:42 worker.1 | at akka.dispatch.Mailbox.run(Mailbox.scala:220) [akka-actor_2.11-2.3.13.jar:na]
11:50:42 worker.1 | at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397) [akka-actor_2.11-2.3.13.jar:na]
11:50:42 worker.1 | at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [scala-library-2.11.6.jar:na]
11:50:42 worker.1 | at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [scala-library-2.11.6.jar:na]
11:50:42 worker.1 | at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [scala-library-2.11.6.jar:na]
11:50:42 worker.1 | at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [scala-library-2.11.6.jar:na]
11:50:42 worker.1 | Caused by: java.lang.RuntimeException: There is no HTTP Context available from here.
11:50:42 worker.1 | at play.mvc.Http$Context.current(Http.java:57) ~[play_2.11-2.4.6.jar:2.4.6]
11:50:42 worker.1 | at play.mvc.Http$Context$Implicit.ctx(Http.java:308) ~[play_2.11-2.4.6.jar:2.4.6]
11:50:42 worker.1 | at play.core.j.PlayMagicForJava$.requestHeader(TemplateMagicForJava.scala:58) ~[play-java_2.11-2.4.6.jar:2.4.6]
11:50:42 worker.1 | at views.html.emailTemplateMedicalValidity_Scope0$emailTemplateMedicalValidity.apply(emailTemplateMedicalValidity.template.scala:77) ~[classes/:na]
11:50:42 worker.1 | at views.html.emailTemplateMedicalValidity_Scope0$emailTemplateMedicalValidity.render(emailTemplateMedicalValidity.template.scala:113) ~[classes/:na]
11:50:42 worker.1 | at views.html.emailTemplateMedicalValidity.render(emailTemplateMedicalValidity.template.scala) ~[classes/:na]
11:50:42 worker.1 | at utils.MedicalValidityActor$1.invoke(MedicalValidityActor.java:97) ~[classes/:na]
11:50:42 worker.1 | at play.db.jpa.DefaultJPAApi.lambda$withTransaction$1(DefaultJPAApi.java:103) ~[play-java-jpa_2.11-2.4.6.jar:2.4.6]
11:50:42 worker.1 | at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:136) ~[play-java-jpa_2.11-2.4.6.jar:2.4.6]
11:50:42 worker.1 | at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:102) ~[play-java-jpa_2.11-2.4.6.jar:2.4.6]
11:50:42 worker.1 | ... 14 common frames omitted
这是我的代码:
public class MedicalValidityActor extends UntypedActor {
@Inject
HttpExecutionContext ec;
@Transactional
public void onReceive(Object message) {
if (message instanceof CheckMedicalValidity) {
// START
JPA.withTransaction(new play.libs.F.Callback0() {
@Override
public void invoke() throws Throwable {
//Get today and add one month
Date todayPlusMonth = new Date();
todayPlusMonth = DateUtils.addMonths(todayPlusMonth, 1);
List<Organization> organizationList = Organization.findAll();
for(Organization organization : organizationList){
List<Player> playerList = PlayerManager.findAllActiveDomesticPlayersByOrganization(organization);
// List containing all players for specific organization that have invalid medical
ArrayList<Player> playersInvalidMedical = new ArrayList<>();
for(Player player : playerList){
System.out.println(organization.getName() + " " + player.getFirstName() + " " + player.getLastName() + " " + player.getMedicalValidityFormatted());
if(player.getMedicalValidity() != null && !player.isMedicalValid()) {
// Medical is not valid anymore
playersInvalidMedical.add(player);
} else if(player.getMedicalValidity() != null && todayPlusMonth.after(player.getMedicalValidity())) {
// Medical is not valid anymore
playersInvalidMedical.add(player);
player.setMedicalValid(false);
}
}
// send notification to users about medical validity
if(!playersInvalidMedical.isEmpty()) {
System.out.println("Potekli: " + playersInvalidMedical.size());
// Get recipients by organization
List<EndUser> endUsers = EndUserManager.findByOrganization(organization);
ArrayList<String> recipients = new ArrayList<>();
for(EndUser enduser : endUsers){
if(enduser.getRoles().get(0).getName().equals(SecurityRole.ADMINISTRATOR) ||
enduser.getRoles().get(0).getName().equals(SecurityRole.SECRETARY) ||
enduser.getRoles().get(0).getName().equals(SecurityRole.COACH) ||
enduser.getRoles().get(0).getName().equals(SecurityRole.HEAD)) {
// add recipients
recipients.add(enduser.getEmail());
}
}
System.out.println("1");
// Initialize now so it is not initialized every iteration
EmailUtilsMailGun mailGunUtils = new EmailUtilsMailGun();
System.out.println("2");
String emailTemplate = emailTemplateMedicalValidity.render(organization, playersInvalidMedical).toString();
System.out.println("3");
mailGunUtils.sendEmailToWithoutAttachmenet(emailTemplate, organization.getName(), organization.getEmail(),
"Potekli Zdravniški Pregledi", recipients);
System.out.println("4");
}
}
}
});
}
}
}