0

I have a class like this :

@Stateless
@Lock(LockType.READ)
public class MessageProcessor {

    @EJB
    private LetterRepository letterRepository;

    @Schedule(second = "*/2", minute = "*", hour = "*")
    public void execute() {
        System.out.println(">>>> Execute ...");
        List<Letter> letterList = letterRepository.selectByStatus(LetterStatus.RECEIVED);
        if (letterList.size() > 0) {
            letterList.stream()
                    .peek(this::changeStatus)
                    .forEach(this::sendMessage);
        }
    }

    private Letter changeStatus(Letter letter) {
        letter.setStatus(LetterStatus.RECEIVED_PROCESS);
        System.out.println("Change Status : " + letter.getId() + " -> " + letter.getStatus());
        letterRepository.update(letter);

        // Simulate Response time with sleep
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return letter;
    }

    private void sendMessage(Letter letter) {
        System.out.println("Send Message : " + letter.getId() + " -> " + letter.getStatus());
    }
}

Note : I simulate database response time with sleep in changeStatus method .
My problem is schedule call execute method every 2 second and database response time is about 10 second (Simulated). so ,letterStatus not updated for next execute .

I receive this exception :

04-Jul-2017 23:48:28.009 WARNING [EjbTimerPool - 2] org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion Unexpected exception from beforeCompletion; transaction will roll back
 javax.persistence.OptimisticLockException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.hibernate.internal.ExceptionConverterImpl.wrapStaleStateException(ExceptionConverterImpl.java:212)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:86)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1441)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3201)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2411)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.beforeCompletion(JtaTransactionCoordinatorImpl.java:320)
    at org.hibernate.resource.transaction.backend.jta.internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47)
    at org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:527)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:511)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforePrepare(TransactionImpl.java:413)
    at org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:262)
    at org.apache.geronimo.transaction.manager.TransactionManagerImpl.commit(TransactionManagerImpl.java:252)
    at org.apache.openejb.core.timer.EjbTimerServiceImpl.ejbTimeout(EjbTimerServiceImpl.java:836)
    at org.apache.openejb.core.timer.EjbTimeoutJob.execute(EjbTimeoutJob.java:39)
    at org.apache.openejb.quartz.core.JobRunShell.run(JobRunShell.java:202)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:67)
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:54)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:46)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3188)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3067)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3447)
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:145)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:589)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1435)
    ... 18 more

04-Jul-2017 23:48:28.012 WARNING [EjbTimerPool - 2] org.apache.openejb.core.timer.EjbTimerServiceImpl.ejbTimeout Exception occured while completing container transaction
 javax.transaction.RollbackException: Unable to commit: transaction marked for rollback
    at org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:272)
    at org.apache.geronimo.transaction.manager.TransactionManagerImpl.commit(TransactionManagerImpl.java:252)
    at org.apache.openejb.core.timer.EjbTimerServiceImpl.ejbTimeout(EjbTimerServiceImpl.java:836)
    at org.apache.openejb.core.timer.EjbTimeoutJob.execute(EjbTimeoutJob.java:39)
    at org.apache.openejb.quartz.core.JobRunShell.run(JobRunShell.java:202)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.geronimo.transaction.manager.SetRollbackOnlyException: setRollbackOnly() called.  See stacktrace for origin
    at org.apache.geronimo.transaction.manager.TransactionImpl.setRollbackOnly(TransactionImpl.java:126)
    at org.apache.geronimo.transaction.manager.TransactionManagerImpl.setRollbackOnly(TransactionManagerImpl.java:243)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionAdapterTransactionManagerImpl.markRollbackOnly(JtaTransactionAdapterTransactionManagerImpl.java:100)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl$TransactionDriverControlImpl.markRollbackOnly(JtaTransactionCoordinatorImpl.java:430)
    at org.hibernate.engine.transaction.internal.TransactionImpl.setRollbackOnly(TransactionImpl.java:143)
    at org.hibernate.Transaction.markRollbackOnly(Transaction.java:68)
    at org.hibernate.internal.AbstractSharedSessionContract.markForRollbackOnly(AbstractSharedSessionContract.java:357)
    at org.hibernate.internal.ExceptionConverterImpl.handlePersistenceException(ExceptionConverterImpl.java:271)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:87)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1441)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491)
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3201)
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2411)
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467)
    at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.beforeCompletion(JtaTransactionCoordinatorImpl.java:320)
    at org.hibernate.resource.transaction.backend.jta.internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47)
    at org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:527)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:511)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforePrepare(TransactionImpl.java:413)
    at org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:262)
    ... 7 more
Caused by: javax.persistence.OptimisticLockException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.hibernate.internal.ExceptionConverterImpl.wrapStaleStateException(ExceptionConverterImpl.java:212)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:86)
    ... 21 more
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:67)
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:54)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:46)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3188)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3067)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3447)
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:145)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:589)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1435)
    ... 18 more
mah454
  • 1,571
  • 15
  • 38
  • This is a common problem. There are some known solutions. Look at this: https://stackoverflow.com/questions/14402068/ejb-schedule-wait-until-method-completed – mnesarco Jul 04 '17 at 19:33
  • Ohh , Thank you men , I did not know what I search . – mah454 Jul 04 '17 at 19:39

0 Answers0