I have a JSF/EJB/JPA application which uses container managed persistence. There is one case where a call is made to an external service via HTTP which has a cost, this cost being allocated back to the requesting user. In the current implementation the process of making the HTTP request is performed by a EJB timer method running periodically in the background.
The timer method may have to deal with a number of requests in one invocation, although each request needs to be treated independently, independently with respect to allocating the cost back to the user, that is. If user A doesn't have enough credit to purchase a book, this musn't prevent the successful purchase of a book by user B resulting in their balance being debited due to a rollback.
To provide control over the transaction demarcation for independent processing of each request I'm using bean managed transactions for the class in which the timer method resides. This is a java-pseudo-code version of what I've got now:
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class MessageTimer {
private void processMessages(UserMessage msg) {
tx.begin();
em.joinTransaction();
try {
userData = em.find(..., PESSIMISTIC_WRITE);
if(user has enough credit) {
debit cost from user;
status = make external http request to order book from supplier;
if(status == success) {
commit = true;
}
}
} catch(Exception) {
tx.rollback();
}
if(commit) {
tx.commit();
}
else {
tx.rollback();
}
}
}
So the idea is that I start a transaction, assume success and debit the cost from the user, call the http service and commit if it succeeds or rollback otherwise.
I have an uneasy feeling that I may not be anywhere near the right ballpark with this design, particularly having the lengthy http call (actually done using jax-rs) inside the pessimistic_write transaction. I wondered if I could firstly, within a transaction debit the user (begin/debit/commit), make http call, then credit the user if any error happens, but there's no transaction integrity.
This is new territory for me, can anyone point me in the right direction, is there an established way of doing what I'm trying to do?
Many Thanks.
p.s. I'm using a glassfish 3.1 stack with Seam 3