Abr*_*ham 8 java jpa eclipselink entitylisteners glassfish-3
我有一个RESTful API,它使用了一个用@EntityListners注释的实体类.在EntityListner.java中,我有一个用@PostPersist注释的方法.因此,当该事件触发时,我想提取有关刚刚保存到数据库的实体的所有信息.但是,当我尝试这样做时,Glassfish正在生成异常,并且EntityListner类中的方法未按预期执行.这是代码
public class EntityListner {
private final static String QUEUE_NAME = "customer";
@PostUpdate
@PostPersist
public void notifyOther(Customer entity){
CustomerFacadeREST custFacade = new CustomerFacadeREST();
Integer customerId = entity.getCustomerId();
String custData = custFacade.find(customerId).toString();
String successMessage = "Entity added to server";
try{
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// channel.basicPublish("", QUEUE_NAME, null, successMessage .getBytes());
channel.basicPublish("", QUEUE_NAME, null, custData.getBytes());
channel.close();
connection.close();
}
catch(IOException ex){
}
finally{
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我发送注释掉的successMessage消息而不是custData,一切正常.
http://www.objectdb.com/java/jpa/persistence/event关于实体生命周期方法说了以下内容,我想知道这是否是这种情况.
为了避免与触发实体生命周期事件(仍在进行中)的原始数据库操作发生冲突,回调方法不应该调用EntityManager或Query方法,也不应该访问任何其他实体对象
有任何想法吗?
正如该段所述,该标准不支持从实体侦听器内部调用实体管理器方法.正如Heiko Rupp在他的回答中所说,我强烈建议custData从持久性实体构建.如果这不可行,请考虑:
public class EntityListener {
private final static String QUEUE_NAME = "customer";
private ScheduledExecutorService getExecutorService() {
// get asynchronous executor service from somewhere
// you will most likely need a ScheduledExecutorService
// instance, in order to schedule notification with
// some delay. Alternatively, you could try Thread.sleep(...)
// before notifying, but that is ugly.
}
private void doNotifyOtherInNewTransaction(Customer entity) {
// For all this to work correctly,
// you should execute your notification
// inside a new transaction. You might
// find it easier to do this declaratively
// by invoking some method demarcated
// with REQUIRES_NEW
try {
// (begin transaction)
doNotifyOther(entity);
// (commit transaction)
} catch (Exception ex) {
// (rollback transaction)
}
}
@PostUpdate
@PostPersist
public void notifyOther(final Customer entity) {
ScheduledExecutorService executor = getExecutorService();
// This is the "raw" version
// Most probably you will need to call
// executor.schedule and specify a delay,
// in order to give the old transaction some time
// to flush and commit
executor.execute(new Runnable() {
@Override
public void run() {
doNotifyOtherInNewTransaction(entity);
}
});
}
// This is exactly as your original code
public void doNotifyOther(Customer entity) {
CustomerFacadeREST custFacade = new CustomerFacadeREST();
Integer customerId = entity.getCustomerId();
String custData = custFacade.find(customerId).toString();
String successMessage = "Entity added to server";
try {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicPublish("", QUEUE_NAME, null, custData.getBytes());
channel.close();
connection.close();
}
catch(IOException ex){
}
finally {
}
}
}
public class EntityListener {
private final static String QUEUE_NAME = "customer";
private Transaction getTransaction() {
// get current JTA transaction reference from somewhere
}
private void doNotifyOtherInNewTransaction(Customer entity) {
// For all this to work correctly,
// you should execute your notification
// inside a new transaction. You might
// find it easier to do this declaratively
// by invoking some method demarcated
// with REQUIRES_NEW
try {
// (begin transaction)
doNotifyOther(entity);
// (commit transaction)
} catch (Exception ex) {
// (rollback transaction)
}
}
@PostUpdate
@PostPersist
public void notifyOther(final Customer entity) {
Transaction transaction = getTransaction();
transaction.registerSynchronization(new Synchronization() {
@Override
public void beforeCompletion() { }
@Override
public void afterCompletion(int status) {
if (status == Status.STATUS_COMMITTED) {
doNotifyOtherInNewTransaction(entity);
}
}
});
}
// This is exactly as your original code
public void doNotifyOther(Customer entity) {
CustomerFacadeREST custFacade = new CustomerFacadeREST();
Integer customerId = entity.getCustomerId();
String custData = custFacade.find(customerId).toString();
String successMessage = "Entity added to server";
try {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
channel.basicPublish("", QUEUE_NAME, null, custData.getBytes());
channel.close();
connection.close();
}
catch(IOException ex){
}
finally {
}
}
}
如果您使用的是Spring事务,那么代码将非常相似,只需更改一些类名.
一些指示:
ScheduledExecutorService Javadoc,用于触发异步操作.
Spring等价物:TransactionSynchronizationManager Javadoc和TransactionSynchronization Javadoc.
| 归档时间: |
|
| 查看次数: |
4621 次 |
| 最近记录: |