2011-01-25 35 views
10

Estoy tratando de crear un servidor de subprocesos múltiples. El problema es que me aparece el siguiente error: play.exceptions.JPAException: el contexto de JPA no se ha inicializado. JPA Entity Manager se inicia automáticamente cuando una o más clases anotadas con la anotación @ javax.persistence.Entity se encuentran en la aplicación.JPA e hilos en el marco de juego

Lo que estoy tratando de hacer es acceder a la base de datos del nuevo hilo aquí está el código

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(); 
     } 
    } 
} 
} 

¿Alguna idea?

Respuesta

12

No utilice hilo normal, utilice puestos de trabajo en su lugar:

@OnApplicationStart 
public class MainLoop extends Job { 
     public void doJob() { 
       new BallJob().now(); 
     } 
} 

Y 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(); 
     } 
    } 
} 
1

Supongo que el hilo se inicia antes de que Play tenga la oportunidad de iniciar el administrador de la entidad JPA.

Si su clase Model está anotada con @Entity, entonces se habría creado el administrador de entidades y su error no aparecería.

Entonces, usted tiene un par de opciones. O bien,

  1. Puede crear un PlayPlugin, con una prioridad menor que los procesos de Play estándar en ApplicationStart.
  2. Puede iniciar su hilo de un trabajo de arranque. Esto asegurará que Play haya tenido la oportunidad de iniciarse correctamente antes de comenzar a interactuar con el servidor. Para ver más acerca de los trabajos de rutina de carga, ver http://www.playframework.org/documentation/1/jobs#concepts

Personalmente, me gustaría ir con la opción 2. Es mejor documentado, y jugar plugins están diseñados más para la ampliación del marco en lugar de cambiar el orden de procesamiento.

4

actualización

Esto es más limpio que lo que hay a continuación:

JPAPlugin.startTx(false); 
// Do your stuff 
JPAPlugin.endTx(false); 

Tuve un problema similar hoy.

usted tiene que crear nueva EntityManager y transacción para cada hilo y ponerlo en APP clase.

Play utiliza para mantener ThreadLocal es EntityManager en APP, por lo que es nula para el hilo creado. Desafortunadamente no puede usar los métodos de ayuda en JPA para hacerlo (son paquetes privados) y tiene que usar ThreadLocal directamente. He aquí cómo usted puede hacer esto:

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(); 
    } 
} 

lo uso con el ejecutor de un solo hilo de java.util.concurrent sin ningún problema.

+2

Actualización: Puede eliminar todas las cosas de JPA y reemplazarlas con JPAPlugin.startTx y JPAPlugin.closeTx. –

+0

He editado su respuesta para incluir su comentario. – ripper234

+0

¿Cómo trabajar con JPA.local con Play Framework 1.4 ?, cambia completamente – javaboygo

Cuestiones relacionadas