JPA ticket registry cleaner fails to clean expired tickets

197 views
Skip to first unread message

Anitha C

unread,
Apr 12, 2022, 10:22:56 PM4/12/22
to CAS Community
Anyone ran into the following issue in CAS v6.5.0 that is configured to use JPA ticket registry and JPA ticket registry cleaner?

2022-04-12 15:50:27,090 ERROR [org.apereo.cas.ticket.registry.DefaultTicketRegistryCleaner] - <Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: update Postgres_Jpa_Ticket_Entity set body=?, creation_Time=?, parent_Id=?, principal_Id=?, type=? where id=?>
javax.persistence.OptimisticLockException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: update Postgres_Jpa_Ticket_Entity set body=?, creation_Time=?, parent_Id=?, principal_Id=?, type=? where id=?
    at org.hibernate.internal.ExceptionConverterImpl.wrapStaleStateException(ExceptionConverterImpl.java:238) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:93) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1705) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.apereo.cas.ticket.registry.JpaTicketRegistry.deleteTicketGrantingTickets(JpaTicketRegistry.java:227) ~[cas-server-support-jpa-ticket-registry-6.5.0.jar:6.5.0]
    at org.apereo.cas.ticket.registry.JpaTicketRegistry.lambda$deleteSingleTicket$1(JpaTicketRegistry.java:198) ~[cas-server-support-jpa-ticket-registry-6.5.0.jar:6.5.0]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.18.jar:5.3.18]
    at org.apereo.cas.ticket.registry.JpaTicketRegistry.deleteSingleTicket(JpaTicketRegistry.java:192) ~[cas-server-support-jpa-ticket-registry-6.5.0.jar:6.5.0]
    at org.apereo.cas.ticket.registry.AbstractTicketRegistry.deleteTicket(AbstractTicketRegistry.java:142) ~[cas-server-core-tickets-api-6.5.0.jar:6.5.0]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.18.jar:5.3.18]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.18.jar:5.3.18]
    at com.sun.proxy.$Proxy265.deleteTicket(Unknown Source) ~[?:?]
    at org.apereo.cas.ticket.registry.DefaultTicketRegistryCleaner.lambda$cleanTicket$0(DefaultTicketRegistryCleaner.java:56) ~[cas-server-core-tickets-api-6.5.0.jar:6.5.0]
    at org.jooq.lambda.Unchecked.lambda$supplier$38(Unchecked.java:1695) ~[jool-0.9.14.jar:?]
    at org.apereo.cas.util.lock.DefaultLockRepository.lambda$execute$0(DefaultLockRepository.java:33) ~[cas-server-core-api-util-6.5.0.jar:6.5.0]
    at java.util.Optional.map(Optional.java:265) ~[?:?]
    at org.apereo.cas.util.lock.DefaultLockRepository.execute(DefaultLockRepository.java:31) ~[cas-server-core-api-util-6.5.0.jar:6.5.0]
    at org.apereo.cas.ticket.registry.DefaultTicketRegistryCleaner.cleanTicket(DefaultTicketRegistryCleaner.java:48) ~[cas-server-core-tickets-api-6.5.0.jar:6.5.0]
    at java.util.stream.ReferencePipeline$4$1.accept(ReferencePipeline.java:212) ~[?:?]
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[?:?]
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[?:?]
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[?:?]
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[?:?]
    at java.util.Iterator.forEachRemaining(Iterator.java:133) ~[?:?]
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) ~[?:?]
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[?:?]
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[?:?]
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[?:?]
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:?]
    at java.util.stream.IntPipeline.reduce(IntPipeline.java:491) ~[?:?]
    at java.util.stream.IntPipeline.sum(IntPipeline.java:449) ~[?:?]
    at org.hibernate.query.spi.IntStreamDecorator.sum(IntStreamDecorator.java:185) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.apereo.cas.ticket.registry.DefaultTicketRegistryCleaner.cleanInternal(DefaultTicketRegistryCleaner.java:69) ~[cas-server-core-tickets-api-6.5.0.jar:6.5.0]
    at org.apereo.cas.ticket.registry.DefaultTicketRegistryCleaner.clean(DefaultTicketRegistryCleaner.java:39) ~[cas-server-core-tickets-api-6.5.0.jar:6.5.0]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.18.jar:5.3.18]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.18.jar:5.3.18]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.18.jar:5.3.18]
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.18.jar:5.3.18]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.18.jar:5.3.18]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.18.jar:5.3.18]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.18.jar:5.3.18]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.18.jar:5.3.18]
    at com.sun.proxy.$Proxy316.clean(Unknown Source) ~[?:?]
    at org.apereo.cas.config.CasCoreTicketsSchedulingConfiguration$TicketRegistryCleanerScheduler.run(CasCoreTicketsSchedulingConfiguration.java:94) ~[cas-server-core-tickets-6.5.0.jar:6.5.0]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.3.18.jar:5.3.18]
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.3.18.jar:5.3.18]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[?:?]
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) ~[?:?]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) ~[?:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[?:?]
    at java.lang.Thread.run(Thread.java:829) [?:?]
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; statement executed: update Postgres_Jpa_Ticket_Entity set body=?, creation_Time=?, parent_Id=?, principal_Id=?, type=? where id=?
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:67) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:54) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.checkRowCounts(BatchingBatch.java:151) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:126) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.doExecuteBatch(BatchingBatch.java:106) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.execute(AbstractBatchImpl.java:148) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:198) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:633) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[?:?]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:344) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:57) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1367) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.internal.SessionImpl.executeUpdate(SessionImpl.java:1471) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.doExecuteUpdate(AbstractProducedQuery.java:1714) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]
    at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1696) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]

Pablo Vidaurri

unread,
Apr 18, 2022, 1:51:31 PM4/18/22
to CAS Community, Anitha C
Are you running on multiple nodes? If so, do you have the register cleaner only running on a single node?

Petr Bodnár

unread,
Jul 29, 2025, 11:56:47 AM7/29/25
to CAS Community, Pablo Vidaurri, Anitha C
Hi there,

using CAS v6.6.15.2 here and we have run into the same problem. We are running just one CAS node and we upgraded from v6.2.8 - maybe we have missed something when upgrading? (the DB table postgres_jpa_ticket_entity contains just tickets created after the upgrade).

Wondering if no one else has got this problem and whether this was somehow resolved in a later version of CAS. Until then, it looks like we need to delete old tickets from the database manually once in a while.

Anthony Oslund

unread,
Aug 1, 2025, 1:14:09 PM8/1/25
to CAS Community, Petr Bodnár, Pablo Vidaurri, Anitha C
Ran into a similar problem with MFA cleanup with CAS 6.6.6 problem was caused by an improperly initialized expiration date on the record.  Been a while, but I believe it was inadvertently setting the expiration 100 years in the future.  In our case, added a flag field to the record structure and when records are created defaulted it to processed = 'N'.  Added a daily system process that would search for records with this flag and then set a proper expiration relative to the record creation date and then reset the flag.  Once the expiration date was set correctly, the cleanup process worked correctly.

We are using couchDb not postgress, but may very well be the same type of problem as the CAS persistence layers are "interesting" and I believe the initialization of this data takes place a layer above the persistence layer.
Reply all
Reply to author
Forward
0 new messages