Setting the LockModeType is good.  Understand, though, that all the values in 
LockModeType are not guaranteed to be supported in all databases.

It doesn't address the core problem in that the transaction scope is likely too 
broad.  As a general rule *always* ensure your transactions are as *small* as 
possible.  In order to be very conscious about it it can help to actually 
document the code and justify why two or more operations need to be in the same 
transaction.  It'll force you to think about transactions more deliberately and 
ask yourself other questions like "where are my transactions starting and 
stopping in the first place".

In this particular situation, with default settings, you'll get one transaction 
started for you when the @Schedule method fires.  So essentially, you're batch 
processing unrelated data in one transaction.  If Joe and Jane both send email 
with data, you're processing Jane's data in Joe's transaction.  As as well your 
email fetching time is getting included in your transaction time.  If your 
email server hangs, your transaction hangs.

So instead of:

    // TRANSACTION START
    @Schedule(...)
    public void processPendingEmail() {
    
        List<Email> emails = fetchEmail();  
        for (Email email : emails) {
           // parse email and insert records
        }
    }
    // TRANSACTION END

You want:

    @Schedule(...)
    public void processPendingEmail() {
    
        List<Email> emails = fetchEmail();  
        for (Email email : emails) {
           // TRANSACTION START
           // parse email and insert records
           // TRANSACTION END
        }
    }

This can be as easy as marking the `processPendingEmail` as 
`@TransactionAttribute(NEVER)` then moving the insert logic to another EJB 
method.  Just make sure that if you move that logic to another method of the 
same EJB that you don't invoke that method with a `this` reference or you won't 
get container-managed transactions on that method call. (see this reference for 
why):

    
http://stackoverflow.com/questions/3381002/how-is-the-return-value-of-sessioncontext-getbusinessobject-different-from-th/3384128#3384128

Hope this helps!


-David

On Dec 11, 2012, at 12:21 PM, "Howard W. Smith, Jr." <smithh032...@gmail.com> 
wrote:

> Prior to adding this @Stateless EJB (that's invoked via @Schedule every 10
> minutes), my JSF web app has been running 100% okay without any deadlocks
> or anything else like that.
> 
> So, is it okay if I just add optimistic locking, em.lock(entity,
> LockType.Optimistic) before any/all em.persist(...) that I have in the
> @Stateless EJB?
> 
> JSF web app is working okay, because the JSF components call multiple
> @Stateless EJB that usually do any of the following, SELECT, UPDATE,
> DELETE,  on one table at time.
> 
> 
> 
> On Tue, Dec 11, 2012 at 2:35 PM, Howard W. Smith, Jr. <
> smithh032...@gmail.com> wrote:
> 
>> You're absolutely right, David. Thanks for the response.
>> 
>> It is a transaction issue and the @Stateless EJB is holding a transaction
>> open and writing into 6 to 10 tables in a single database, which is also
>> the database accessed by JSF components (by endusers). The @Stateless EJB
>> is on a timer ( @Schedule), checks email server for incoming requests from
>> customers, and takes that data and inserts it into database, so endusers
>> don't have to manually enter the data (that they receive from these
>> formmail results).
>> 
>> Below is the exception that I saw maybe an hour or two ago, and I
>> confirmed that it's a locking/transaction issue, and from the stacktrace,
>> it seems as though the JSF components cannot access the table, that is
>> evidently locked by @Stateless EJB. The @Stateless @EJB updated all tables
>> on my faster/dev/test server on average of 1 to 2 seconds, and/so in my
>> opinion, the data is not that much at all, maybe a few kbytes of data being
>> inserted into the database. Anyway, I've been reading up on pessismistic
>> and optimistic locking, and that's where I was in my reading before I
>> noticed your email. I really don't know what the database or JPA is
>> defaulting to, because honestly, I have no code that specifies any locks.
>> Recently, I only added query hint (readonly) to JPA queries. Personally, I
>> feel as though I can use 'no locking' for these inserts, since this is
>> brand new data, but the JSF components may be locking the entites/tables
>> during simple queries (SELECT statements).  Feel free to change this
>> email/topic to a more suitable topic/subject, if necessary. :)
>> 
>> 
>> 
>> 

Reply via email to