我正在从Play 2.3.x迁移到2.5.x,我遇到了从akka actor访问数据库的问题。我在应用程序启动期间将调度程序注入EagerSingleton,并从那里创建访问数据库的调度。
Actor在构造函数中接收JPAAPI来访问数据库但每次尝试访问数据库时都会收到以下错误。
有没有人解决这个问题?
我是否还应该注入HTTP上下文?我怎么能这样做?
2017-03-23 11:46:16.990 +0000 - DashboardMonitor.onReceive:73 - 检查状态
java.lang.RuntimeException:JPA事务失败
at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:198) 在actors.DashboardMonitor.onReceive(DashboardMonitor.java:77) at akka.actor.UntypedActor $$ anonfun $ receive $ 1.applyOrElse(UntypedActor.scala:165) at akka.actor.Actor $ class.aroundReceive(Actor.scala:484) at akka.actor.UntypedActor.aroundReceive(UntypedActor.scala:95) at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526) at akka.actor.ActorCell.invoke(ActorCell.scala:495) at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257) at akka.dispatch.Mailbox.run(Mailbox.scala:224) at akka.dispatch.Mailbox.exec(Mailbox.scala:234) 在scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) 在scala.concurrent.forkjoin.ForkJoinPool $ WorkQueue.runTask(ForkJoinPool.java:1339) 在scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) 在scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
引起:java.lang.RuntimeException:没有绑定到此线程的EntityManager。尝试在JPAApi.withTransaction中包装此调用,或确保在此线程上设置HTTP上下文。
at play.db.jpa.JPAEntityManagerContext.em(JPAEntityManagerContext.java:36) at play.db.jpa.JPA.em(JPA.java:75) 在models.Probe.getAllProbes(Probe.java:270) at utils.Utils.updatePlatformStatus(Utils.java:524) 在actors.DashboardMonitor.lambda $ onReceive $ 0(DashboardMonitor.java:78) at play.db.jpa.DefaultJPAApi.lambda $ withTransaction $ 2(DefaultJPAApi.java:194) at play.db.jpa.DefaultJPAApi.lambda $ withTransaction $ 3(DefaultJPAApi.java:211) at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:152) at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:210) at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:193) ......还有13个
这是我使用的代码:
@Singleton
public class DashboardMonitor extends UntypedActor {
private final JPAApi jpaApi;
@Inject
public DashboardMonitor(JPAApi jpaApi) {
this.jpaApi = jpaApi;
}
@Override
public void onReceive(Object message) throws Exception {
// check message type
if (message.equals("updateStatus")) {
try {
jpaApi.withTransaction(() -> {
Utils.updatePlatformStatus();
});
}catch (Exception e){
e.printStackTrace();
}
}
}
}
调度程序:
@Singleton
public class DashboardScheduler {
// Start aggregate session for aggregate probe
private Cancellable updateStatusSchedule = null;
@Inject
public DashboardScheduler(ApplicationLifecycle lifeCycle, ActorSystem system, @Named("dashboard-monitor") ActorRef dashboardActor) {
startUpdateStatus(system, dashboardActor);
initStopHook(lifeCycle);
}
/**
* Start probesTimedOutScheduler
*/
private void startUpdateStatus(ActorSystem system, ActorRef dashboardActor) {
if (updateStatusSchedule == null || updateStatusSchedule.isCancelled()) {
updateStatusSchedule = system.scheduler().schedule(
Duration.create(10, TimeUnit.SECONDS),
Duration.create((GlobalConfiguration.probeUpdateInterval), TimeUnit.SECONDS),
dashboardActor,
"updateStatus",
system.dispatcher(),
null);
}
}
}
注射模块:
public class GlobalBootstrapModule extends AbstractModule implements AkkaGuiceSupport {
@Override
protected void configure() {
bindActor(DashboardMonitor.class, "dashboard-monitor");
bind(DashboardScheduler.class).asEagerSingleton();
}
}