我有一个我想要启动的ConsumerService的Play应用程序,让它在启动时侦听特定的RabbitMQ队列。在玩! 2.5,我的理解是现在通过指南模块完成,所以我在我的应用程序根目录中直接有一个Module.java类,如下所示:
public class Module extends AbstractModule {
@Override
protected void configure() {
bind(ConsumerService.class).asEagerSingleton();
}
}
这是我的ConsumerService类:
@Singleton
public class ConsumerService {
private static final String TASK_QUEUE_NAME = "queue";
private final JPAApi jpaApi;
@Inject
public ConsumerService(JPAApi api) throws Exception {
this.jpaApi = api;
pullMessages();
}
@Transactional
public void pullMessages() throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
final Connection connection = factory.newConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
Logger.info(" [*] Waiting for messagez. To exit press CTRL+C");
channel.basicQos(1);
final Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
try {
JPA.em();
} catch (Exception e) {
System.out.println("JPA.em() failed: " + e.getMessage());
}
try {
jpaApi.em();
} catch (Exception e) {
System.out.println("jpaApi.em() failed: " + e.getMessage());
}
}
};
channel.basicConsume(TASK_QUEUE_NAME, false, consumer);
}
}
将此服务明确地绑定为Eager Singleton有其缺点,因为尝试通过这些方法之一获取entityManager会引发异常。我的理解是,这是因为在Play初始化EntityManager工厂之前,这个类是绑定/加载的。基本上应用程序还没有开始。
请原谅我,但即使我已经使用JPA多年,我发现这非常令人困惑,并且不确定我应该解决基本问题的最佳方法:启动一个“监听器”,最终需要做一些消耗消息时的数据库操作。
我很好奇是否可以在事务中放置“handleDelivery”方法,或重新设计初始化流程,以便我可以干净地调用/注入jpaApi。
另外,有没有办法在Play 2.5中启动这个消费者,而不是我在这里做的方式?我找不到这个。
我查看了JPAApi.withTransaction文档,但我希望有一种更好的方法,我不知道。