Play Framework 2.5中没有EntityManager错误接收另一个线程中的数据

时间:2016-11-24 17:33:51

标签: java multithreading hibernate playframework playframework-2.5

使用play Framework 2.5 for Java

我想创建一个使用ActiveMQ数据的应用程序,并从收到的消息中执行一个hibernate查询到数据库并存储一个对象User。 我已经简化了我的消费者类,以便在那里创建一个对象,同时调用持久性。

当我从接收测量的线程(或调用另一个类)调用持久性时,我的问题出现了。然后EntityManager不在那里,我不能创建一个新的,或坦率我不知道在Play中制作它。

package controllers;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

import models.User;
import play.Logger;
import play.db.jpa.JPA;

public class MessageConsumerController implements Runnable, ExceptionListener {
    private static final String TOPIC_NAME = "miguelTopic";
    private static Thread consumerService;

    public static synchronized void initService() {
        Logger.info("Message Consumer initialized");
        MessageConsumerController MessageConsumer = new MessageConsumerController();
        if (consumerService != null) {
            Logger.info("STOPPING MessageConsumer thread.");
            consumerService.interrupt();
        }
        Logger.info("Starting MessageConsumer thread.");
        consumerService = new Thread(MessageConsumer);
        consumerService.setDaemon(true);
        consumerService.setName("MessageConsumer Service");
        consumerService.start();
        Logger.info("MessageConsumer thread started.");
    }

    @Override
    public void run() {
        try {

            ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("admin", "admin",
                    "tcp://localhost:61616");

            Logger.info("Creating ActiveMQ connection");
            Connection connection = connectionFactory.createConnection();
            connection.start();
            connection.setExceptionListener(this);
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

            Logger.info("Connecting to topic " + TOPIC_NAME);
            Destination destination = session.createTopic(TOPIC_NAME);

            Logger.info("Creating consumer");
            MessageConsumer consumer = session.createConsumer(destination);

            while (!Thread.currentThread().isInterrupted()) {
                Logger.info("Wait for messages...");
                Message message = consumer.receive();

                if (message instanceof TextMessage) {
                    TextMessage textMessage = (TextMessage) message;
                    String text = textMessage.getText();
                    Logger.info("Received: " + text);
                    User user = new User();
                    user.setId(555);
                    user.setName("miguel");
                    user.setTime_of_start("time");
                    Logger.info("insert user");

                    //JPAApi jpa = Play.current().injector().instanceOf(JPAApi.class);

                    JPA.em().getTransaction().begin();
                    JPA.em().persist(user); // 
                    JPA.em().getTransaction().commit();



                } else {
                    Logger.info("Received: " + message.getClass().getSimpleName());
                }

            }
            Logger.info("Message consumer interrupted.");
            consumer.close();
            session.close();
            connection.close();
        } catch (Exception e) {
            if (e instanceof InterruptedException) {
                Logger.info("Message Consumer thread interrupted.");
            } else {
                Logger.error(e.getLocalizedMessage(), e);
            }
        }
    }

    public synchronized void onException(JMSException ex) {
        Logger.error("JMS Exception occured.  Shutting down client.");
        Logger.error("ErrorCode=" + ex.getErrorCode() + " , " + ex.getMessage(), ex);
    }

}

我曾尝试过注入JPaapi,以及更多不同的东西,但我几乎不熟悉Play Framework

1 个答案:

答案 0 :(得分:1)

首先,在Play Framework中,我建议使用Akka actor而不是传统的Java Threads。一开始看起来似乎很复杂,但是一旦掌握它就会节省大量的调试时间。 Akka已经集成在Play中,所以它应该不是问题。

现在,关于您的实体经理。首先,确保在sbt构建文件中有java JDBC:libraryDependencies += javaJdbc

接下来,在您的配置文件中,确保您配置了默认DS:db.default.jndiName=DefaultDS以及持久性单元(此处更多:https://www.playframework.com/documentation/2.5.x/JavaJPA

现在,你的控制器(我在你发布的代码中看不到实际的控制器)必须有@Transactional注释。