JPA and Threads in play framework
Update
This is neater than what's below:
JPAPlugin.startTx(false);
// Do your stuff
JPAPlugin.endTx(false);
Had similar problem today.
You have to create new EntityManager
and transaction for each thread and set it in JPA class.
Play uses ThreadLocal
to keep it's EntityManager
in JPA, so it's null for your created thread. Unfortunately you cannot use helper methods in JPA to do it (they are package private) and you have to use ThreadLocal
directly. Here's how you can do this:
class Runner extends Runnable {
@Override
public void run() {
if (JPA.local.get() == null) {
EntityManager em = JPA.newEntityManager();
final JPA jpa = new JPA();
jpa.entityManager = em;
JPA.local.set(jpa);
}
JPA.em().getTransaction().begin();
... DO YOUR STUFF HERE ...
JPA.em().getTransaction().commit();
}
}
I use it with single thread executor from java.util.concurrent without any problems.
Don't use plain thread, use jobs instead :
@OnApplicationStart
public class MainLoop extends Job {
public void doJob() {
new BallJob().now();
}
}
And BallJob :
public class BallJob extends Job {
public void doJob() {
List<Ball> balls;
new Ball(5,5,2,2,10,15);
while (true){
balls = Ball.all().fetch();
for (Iterator iterator = balls.iterator(); iterator.hasNext();) {
Ball ball = (Ball) iterator.next();
ball.applyForces();
}
}
}