Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA and Threads in play framework

I'm trying to create a multithreading server. The problem is that I get the following error: play.exceptions.JPAException: The JPA context is not initialized. JPA Entity Manager automatically start when one or more classes annotated with the @javax.persistence.Entity annotation are found in the application.

What I'm trying to do is access the db from the new thread here's the code

package controllers;
import java.util.Iterator;
import java.util.List;
import models.Ball;


public class MainLoop extends Thread {

@Override
public void run() {
    List<Ball> balls;
    new Ball(5,5,2,2,10,15);
    while (true){
        balls = Ball.all().fetch(); //Here throws an exception 

        for (Iterator iterator = balls.iterator(); iterator.hasNext();) {
            Ball ball = (Ball) iterator.next();
            ball.applyForces();
        }
    }
}
}

Any ideas?

like image 636
Maurizio Pozzobon Avatar asked Jan 25 '11 15:01

Maurizio Pozzobon


People also ask

What is JPA and how does it work?

JPA permits the developer to work directly with objects rather than with SQL statements. The JPA implementation is typically called persistence provider. The mapping between Java objects and database tables is defined via persistence metadata.

Is Play framework asynchronous?

Internally, Play Framework is asynchronous from the bottom up. Play handles every request in an asynchronous, non-blocking way. The default configuration is tuned for asynchronous controllers.

What is play framework used for?

Play is a high-productivity web application framework for programming languages whose code is compiled and run on the JVM, mainly Java and Scala. It integrates the components and APIs we need for modern web application development.

Is Play framework backend?

Play comes with two configurable server backends, which handle the low level work of processing HTTP requests and responses to and from TCP/IP packets. Starting in 2.6. x, the default server backend is the Akka HTTP server backend, based on the Akka-HTTP server. Prior to 2.6.


1 Answers

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.

like image 200
Marek Piechut Avatar answered Dec 01 '22 22:12

Marek Piechut