On Dec 13, 2012, at 1:53 PM, David Blevins <david.blev...@gmail.com> wrote:
> > On Dec 13, 2012, at 1:17 PM, "Howard W. Smith, Jr." <smithh032...@gmail.com> > wrote: > >> David, >> >> 1. definitely not using @Asynchronous; that was no good at all >> >> 2. Actually, it was 2 seconds on the Windows Server 2008 64-bit 16GB RAM... >> always >> >> 3. Always 5 to 10 minutes to process 1 or 2 emails on Windows Server 2003 >> 32-bit 4GB RAM > > Good info thanks. > >> 4. As noted on the JIRA, I tried the TransactionAttribute NEVER and >> REQUIRES_NEW on @Stateless EJB that was all invoked via @Schedule, and same >> test results, which are.... The EJB timer rolls back the transaction, and >> every database operation that the EmailStatelessBean completed...prior to >> @Schedule rolling back the transaction. > > Right, that suggestion was never implemented as it was intended. Changing > the TransactionAttribute alone will do nothing. What we need is to 1) > prevent a transaction from being started and 2) creating a new and smaller > transaction scope through a small code rework. > > The ApplicationScoped check backfired because it has the effect of locking > tables for much longer. We want to process each "email" in an individual > transaction and move away from one big transaction. This is really the most > critical step to take, no other steps or workarounds matter at this phase of > the problem. > > Let's try this: > > - Go back to the very original 5-10 minutes 32-bit code > > - Split EmailSessionBean into two beans > > - EmailSessionBean > - will be marked @TransactionAttribute(NEVER) > - will no longer have an @PersistenceContext EntityManager reference > - AirportShuttleRequestProcessorBean > - will be marked @TransactionAttribute(REQUIRES_NEW) > - will have only one public method, `createOrderForAirportShuttle` > - will do all persistence processing > > The EmailSessionBean will have an @EJB reference to the new > AirportShuttleRequestProcessorBean. Effectively, we're splitting the code > that does the contacting the of the email server from the code that contacts > the database and we're creating several much smaller transactions. And one more tweak. Let's change the EmailSessionBean to type @Singleton and add @Lock(WRITE) to our `getEmails()` method. We're doing this to ensure that two `getEmail()` invocations cannot possibly happen at the same time. This is not necessarily the case now, but this can easily occur if the `getEmails()` method takes longer than the configured time of every 10 minutes. It can also occur if the time gets shorted, to say 2 minutes. With switching our EmailSessionBean bean to type @Singleton and ensuring @Lock(WRITE) on the `getEmails()` method, once things are working well we could effectively dramatically reduce the delay between firings to something far more aggressive than 10 minutes (say 2 or 5 minutes) and still be safe. The combination of @Singleton/@Lock(WRITE) guarantees that method will only ever be active one-at-a-time in the entire application. -David