2

I have an event-driven application based on MDB, spring integration and JPA for persistence. The application is deployed on weblogic 10.3 with a max-pool-size default value (16).

My application need to handle some messages that modfies DB. Imagine that I have use case where I have to handle some messages that for their logic need to insert a domain object if it does not exist or update it if it exists.

So my component that modifes the DB check if the object exists or not and then call the merge on JPA. Since two concurrent messages are executed in parallel when I call the merge on dao, JPA triggers two insert statement since the object is not yet persisted and so only one of them is correctly executed.

Is there a pattern to handle this kind of "race condition" in an event-driven application?

Kind regards Massimo

MaDa
  • 10,511
  • 9
  • 46
  • 84
Massimo Ugues
  • 4,373
  • 8
  • 43
  • 56

1 Answers1

1

The simplest solution is to catch the exception thrown by the second insert, then call merge again, which should perform the update.

Alternatively, you could try performing the merge in SERIALIZABLE transaction isolation, which should ensure that the second merge is blocked until the first one has completed, and the second one should then perform an update.

The main problem with this whole scenario is that if you have multiple concurrent events coming in which entail modifying a given entity, then how do you ensure that you're executing them in the correct sequence? Surely you need to process these sequentially, rather than concurrently? If you use concurrent event consumers, the order is going to be non-deterministic.

Gandhi
  • 11,875
  • 4
  • 39
  • 63
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • OK, nice shot. Do you know if the isolation level serializable is serializable fo node or for cluster? I have to deploy the application on a cluster with 2 nodes. Kind regards. Massimo – Massimo Ugues Jan 20 '12 at 15:21
  • @MassimoUgues: Depends on your transaction manager, but it's usually database-level isolation, so should be cluster-safe. – skaffman Jan 20 '12 at 15:47
  • I use the spring JTA, so it should be cluster-safe. I was thinking about the isolation=SERIALIZABLE that would be a big bottleneck. Since I have to handle this kind of concurrency only for those messages that affects some domain objects identified by the same id, I was thinking some kind of db-based monitor (e.g. some kind of select for update on that id). What do you think about it? – Massimo Ugues Jan 21 '12 at 09:23
  • @MassimoUgues: `SELECT FOR UPDATE` won't work if the row doesn't exist, that's why I suggested `SERIALIZABLE` isolation. You're right, though, it might hurt concurrency performance, so my first suggestion may be your best bet. – skaffman Jan 21 '12 at 10:09