If your business logic catches (or creates) an application exception, throw it to the Container as the application exception
In bean code, if you catch an application exception thrown by other code (or you create the exception as part of your business logic), throw it to the Container exactly as-is. For example, if your bean code gets a FinderException while trying to look up another bean (in other words, while calling a finder method on another bean’s home interface), give the FinderException to the Container exactly as you got it. That means either declaring it (ducking it and letting it propagate back down the stack to the Container):
Or catching it and rethrowing it as-as:
If you catch an application exception, and find that you can’t continue the transaction, call setRollbackOnly() before throwing the exception to the Container.
Remember, the Container won’t rollback a transaction just because there’s an application exception. With an application exception, the Container assumes that the whole thing might be recoverable, and that the transaction can continue. Unless you find out, in your business logic, that committing would be a Really Bad Idea (it often is). What’s your option? Force the Container to rollback the transaction using setRollbackOnly() ...