Reputation: 11
I am currently working with JPA. I’ve encountered an issue during development. Here’s the current situation:
itemService addItem: If the item is already owned, an exception is thrown. If the item is owned but the user is in the process of waiting for a specified time to own it, another exception is thrown. If the item is not owned, the item is successfully given to the user.
StoreService handleItem: This method gives the item to the user, and if the item is already owned but the user is waiting for a specified time to own it, it should be processed as an immediate gift.
I want to keep using the addItem method of itemService as it is, because it is used by my entire development team, not just by me.
Below is part of the code for StoreService:
@Transactional
protected void handleItem(User user, AssetItem assetItem) throws CustomCheckedException {
try {
itemService.addItem(user, assetItem);
} catch (CustomCheckedException e) {
if (e.getErrorCode() == ErrorCode.RECEIVING_IN_PROGRESS) {
Item item = (Item) e.getAdditionalData();
item.setStatusToOwned();
itemRepository.save(item);
itemRepository.flush();
} else {
throw e;
}
}
}
The reason for handling CustomCheckedException separately is that previously I encountered the error UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only. Since it was indicated that CheckedException would not trigger a rollback, I applied this approach.
My questions are as follows:
In the catch block, the itemRepository.save(item) is not working as expected, and the changes are not reflected in the database even though @Transactional is used. Why does the save method not work in the catch block?
To resolve the issue with UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only, I introduced CustomCheckedException (since CheckedExceptions do not trigger rollback), along with the try-catch block. Is there a better way to handle this, without using these mechanisms?
What I tried:
What I expected:
Upvotes: 1
Views: 58
Reputation: 650
It should be something like:
public class StoreService {
...
@Autowired
ApplicationContext context;
...
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addItem((User user, AssetItem assetItem) throws CustomCheckedException {
itemService.addItem(user, assetItem);
}
@Transactional
public void handleItem((User user, AssetItem assetItem) throws CustomCheckedException {
try {
context.getBean(StoreService.class).addItem(user, assetItem);
} catch (CustomCheckedException e) {
if (e.getErrorCode() == ErrorCode.RECEIVING_IN_PROGRESS) {
Item item = (Item) e.getAdditionalData();
item.setStatusToOwned();
itemRepository.save(item);
itemRepository.flush();
} else {
throw e;
}
}
}
...
}
Upvotes: 0