Websphere App Server 7,EJB 3.0,OpenJPA EntityExistsException上的JMS JPA并发问题

时间:2012-08-31 20:05:07

标签: jpa jms ejb-3.0 openjpa

用例是发送带有由MDB处理的GPS信息的JMS消息的设备。如果数据库中不存在设备,则创建/插入设备并创建/插入GPS记录。在发送消息时处理消息时一切正常。当来自同一设备的消息建立并在彼此的毫秒内处理时,会出现此问题。似乎存在一个JMS消息进程在另一个JMS进程检查实体(并且它不存在)并尝试插入实体(并且它已经存在)之间插入实体的竞争条件。

该进程正在尝试多次插入Device实体,因为在某些时候进程发现没有记录存在。抛出以下异常,因为正在处理的上一条消息已插入记录。我已经尝试将IsolationLevels更改为每个值,直到SERIALIZABLE,没有运气。任何想法将不胜感激! WAS 7,OpenJPA 2.0.2,EJB3.0

[8/30/12 11:14:01:319 EDT] 0000002a RegisteredSyn E   WTRN0074E: Exception caught
  from before_completion synchronization operation:
  <openjpa-2.0.2-SNAPSHOT-r422266:1295351 fatal store error>
  org.apache.openjpa.persistence.EntityExistsException: The transaction has been
  rolled back. See the nested exceptions for details on the errors that occurred.

Caused by: <openjpa-2.0.2-SNAPSHOT-r422266:1295351 fatal store error>
  org.apache.openjpa.persistence.EntityExistsException: ORA-00001:
  unique constraint (SPW_OWN.PK_DEVICE) violated

执行此过程的SSB代码段:

                Device device = deviceManager.findDeviceByDeviceI(deviceString);

                //check to see if device entity exists
                if(device == null){
                    Log.logDebug(this, "device " + deviceString +" is null");

                    device.setDeviceI(deviceString);

                    //tried both create and update with no luck
                    //deviceManager.createDevice(device);

                    deviceManager.updateDevice(device);
                }

JPA SSB:

@Action(Action.ACTION_TYPE.UPDATE)
public String updateDevice(Device device) throws Exception {
    EntityManager em = getEntityManager();
    try {
        device = em.merge(device);
    } finally {
        em.close();
    }
    return "";
}

做一些测试我已经找到了一个体面的工作虽然我仍然不是100%满意。欢迎任何其他建议:

  • 将Bean管理事务类型设置为JMS MDB,并将其他后续SSB保持在Container模式下,这样我仍然可以将实际数据操作Container管理为回滚。
  • 在MDB中设置编程阈值以重试并处理消息X次。
  • 在调用SSB时捕获EJBTransactionRolledbackException(由EntityExistsException引起)
  • 重试使用阈值再次处理消息(在我的情况下,第二次成功,因为先前的事务已提交,并且重试发现实体存在并成功处理了消息)
  • 我以编程方式设置我的阈值,尝试将消息处理两次,然后再将其发送到错误队列。

我通常不喜欢将异常捕获用作控制流。我还想象有一种方法可以将JMS MDB保持为容器管理事务,并让Java EE服务器重新处理该消息。

0 个答案:

没有答案