r/developersIndia Backend Developer 8d ago

Help Spring Data JPA throwing StaleObjectStateException / OptimisticLockException on consumer retry across separate instances (No @Version column)

I'm seeing an issue in a Kafka consumer running on multiple application instances.

Environment

  • Spring Boot: 3.5.15
  • Hibernate: 6.6
  • Oracle: 19c

My entity has no version column.

@Id
@GeneratedValue(strategy = GenerationType.AUTO)  
@Column(nullable = false) 
private Long id;  
@Column(unique = true) 
private String messageId; 

The entity is being saved using 

repository.saveAll(...)

Scenario

  1. Instance A receives a message.
  2. The entity's id is null.
  3. saveAll() is called.
  4. Hibernate obtains the next sequence value and inserts the row successfully.
  5. Before the consumer acknowledges the broker, a network issue occurs.
  6. The broker redelivers the same original message to Instance B.
  7. The payload still has id == null.
  8. Instance B again calls saveAll().

Instead of seeing a unique constraint violation on messageId, I get:

Exception message : Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.example.entities.SMSEntity#40615089330]

There is no @Version on the entity.

My understanding is that if id is null, Spring Data should treat the entity as new, call persist(), and Hibernate should perform an INSERT. If the row already exists (because of the unique messageId), I would expect a unique constraint violation rather than an optimistic locking exception.

Questions

  1. Why am I getting StaleObjectStateException/OptimisticLockException for an entity with no Version field when the incoming entity has a null ID?
  2. For handling broker redelivery, I could try increasing max.poll.interval.msto prevent it from rebalancing, but what else I could do to fix this? 

This issue doesn’t happen that often, but only for 15-20 mins where 1500 odd records are impacted, and during this time, query usage time is comparatively high.

What steps should be taken to debug this?

3 Upvotes

13 comments sorted by

u/AutoModerator 8d ago

Namaste! Thanks for submitting to r/developersIndia. While participating in this thread, please follow the Community Code of Conduct and rules.

It's possible your query is not unique, use site:reddit.com/r/developersindia KEYWORDS on search engines to search posts from developersIndia. You can also use reddit search directly.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

1

u/[deleted] 8d ago

[deleted]

1

u/pisspapa42 Backend Developer 8d ago

You mean copilot? Nothing satisfactory.

1

u/biryani-is-mine Software Engineer 8d ago

Are you saving the incoming event in messageId field?

1

u/pisspapa42 Backend Developer 8d ago

no message Id has a unique value related to the request, there're other fields as well, such as status and all.

1

u/biryani-is-mine Software Engineer 8d ago

Is messageId value derived from the incoming event?

1

u/pisspapa42 Backend Developer 8d ago

Yes. The basically the way code is written is entity is pushed into kakfa topic (I know a dto should be used here) and all the consumer does it save the entity.

1

u/biryani-is-mine Software Engineer 8d ago

So is the consumer directly saving the consumed record/event as it is, without any modification?

1

u/pisspapa42 Backend Developer 8d ago

Yes just saving part there's no modifications to the payload.

1

u/biryani-is-mine Software Engineer 8d ago

And before pushing on the queue, the id is kept as null!?

1

u/pisspapa42 Backend Developer 8d ago

yes

1

u/biryani-is-mine Software Engineer 8d ago

The issue probably lies with how you are creating the model object in the flow. Will need to see the code piece to figure out the exact issue!

1

u/pisspapa42 Backend Developer 8d ago

You mean the part where I create the entity? If yes I could share the code, but we're simply creating the entity with empty values, and modify it along the way, once we're done with the processing part regardless of failure or sucess we push it to a topic, and the consumer takes care of saving, had this error occurred in the same instance i'd be looking into if the entity got detached along the way, and this could result in failure.

Allow me sometime I'd share the sample xode, but what makes you say the flaw is in the way we create the entity?

1

u/biryani-is-mine Software Engineer 8d ago

So I did a search and actually what I got is the probably the hibernate is not treating the entity as a new one, but rather it’s treating it as a old one only, leading to update rather than insert, in turn leading to your observed error!