This is an automated email from the ASF dual-hosted git repository. tv pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-jcs.git
commit e5c331dcf746c3425dfedb5831ea7f7292d2552e Author: Thomas Vandahl <[email protected]> AuthorDate: Tue Apr 14 15:44:02 2026 +0200 JCS-247: Allow CacheMonitor to survive RuntimExceptions --- .../auxiliary/AbstractAuxiliaryCacheMonitor.java | 11 ++- .../auxiliary/lateral/LateralCacheMonitor.java | 2 +- .../jcs4/auxiliary/remote/RemoteCacheMonitor.java | 2 +- .../remote/http/client/RemoteHttpCacheMonitor.java | 2 +- .../AbstractAuxiliaryCacheMonitorUnitTest.java | 89 ++++++++++++++++++++++ .../lateral/socket/tcp/TestTCPLateralUnitTest.java | 2 +- 6 files changed, 102 insertions(+), 6 deletions(-) diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/AbstractAuxiliaryCacheMonitor.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/AbstractAuxiliaryCacheMonitor.java index b5b0bd04..87136fe1 100644 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/AbstractAuxiliaryCacheMonitor.java +++ b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/AbstractAuxiliaryCacheMonitor.java @@ -88,7 +88,7 @@ public abstract class AbstractAuxiliaryCacheMonitor extends Thread /** * do actual work */ - protected abstract void doWork(); + protected abstract void doWork() throws Exception; /** * Notifies the cache monitor that an error occurred, and kicks off the error recovery process. @@ -162,7 +162,14 @@ public abstract class AbstractAuxiliaryCacheMonitor extends Thread log.debug( "Cache monitor running." ); - doWork(); + try + { + doWork(); + } + catch (Exception e) + { + log.error("Cache monitor loop threw exception", e); + } try { diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/lateral/LateralCacheMonitor.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/lateral/LateralCacheMonitor.java index deec07d0..4f92a8bb 100644 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/lateral/LateralCacheMonitor.java +++ b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/lateral/LateralCacheMonitor.java @@ -108,7 +108,7 @@ public class LateralCacheMonitor extends AbstractAuxiliaryCacheMonitor * Main processing method for the LateralCacheMonitor object */ @Override - public void doWork() + public void doWork() throws Exception { // Monitor each cache instance one after the other. log.info( "Number of caches to monitor = " + caches.size() ); diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/RemoteCacheMonitor.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/RemoteCacheMonitor.java index ae3dca4b..47d01729 100644 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/RemoteCacheMonitor.java +++ b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/RemoteCacheMonitor.java @@ -79,7 +79,7 @@ public class RemoteCacheMonitor extends AbstractAuxiliaryCacheMonitor // just skip the monitoring until the next round. /** Main processing method for the RemoteCacheMonitor object */ @Override - public void doWork() + public void doWork() throws Exception { // Monitor each RemoteCacheManager instance one after the other. // Each RemoteCacheManager corresponds to one remote connection. diff --git a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/http/client/RemoteHttpCacheMonitor.java b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/http/client/RemoteHttpCacheMonitor.java index e135cd75..4de784b2 100644 --- a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/http/client/RemoteHttpCacheMonitor.java +++ b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/auxiliary/remote/http/client/RemoteHttpCacheMonitor.java @@ -68,7 +68,7 @@ public class RemoteHttpCacheMonitor extends AbstractAuxiliaryCacheMonitor // just skip the monitoring until the next round. /** Main processing method for the RemoteHttpCacheMonitor object */ @Override - protected void doWork() + protected void doWork() throws Exception { // If no factory has been set, skip if (factory == null) diff --git a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/AbstractAuxiliaryCacheMonitorUnitTest.java b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/AbstractAuxiliaryCacheMonitorUnitTest.java new file mode 100644 index 00000000..86f0352c --- /dev/null +++ b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/AbstractAuxiliaryCacheMonitorUnitTest.java @@ -0,0 +1,89 @@ +package org.apache.commons.jcs4.auxiliary; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +/** + * Basic unit tests for the cache monitor. + */ +class AbstractAuxiliaryCacheMonitorUnitTest +{ + /** + * Test that the cache monitor survives runtime exceptions in doWork() + * + * @throws Exception + */ + @Test + void testCacheMonitorResilience() throws Exception + { + // reduce the monitor idle period between 'fix' attempts for testing purposes + MockCacheMonitor.setIdle(100L); + + final MockCacheMonitor monitor = new MockCacheMonitor(); + monitor.start(); + monitor.notifyError(); + Thread.sleep(200L); + monitor.notifyError(); + Thread.sleep(200L); + + // verify that the monitor has been called multiple times + assertTrue(1 < monitor.doWorkCalls, "Should have multiple calls " + monitor.doWorkCalls); + + monitor.notifyShutdown(); + Thread.sleep(200L); + // verify that the monitor shutdown has been called once + assertEquals(1, monitor.disposeCalls, "Should have one call"); + } + + // used to reduce the monitor idle period between 'fix' attempts for testing purposes + private static class MockCacheMonitor extends AbstractAuxiliaryCacheMonitor + { + protected int doWorkCalls = 0; + protected int disposeCalls = 0; + + public static void setIdle(long idlePeriod) + { + AbstractAuxiliaryCacheMonitor.idlePeriod = idlePeriod; + } + + public MockCacheMonitor() + { + super("test"); + } + + @Override + protected void dispose() + { + disposeCalls++; + } + + @Override + protected void doWork() throws Exception + { + doWorkCalls++; + throw new NullPointerException("test"); + } + } +} diff --git a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/lateral/socket/tcp/TestTCPLateralUnitTest.java b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/lateral/socket/tcp/TestTCPLateralUnitTest.java index fe03f324..6f743625 100644 --- a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/lateral/socket/tcp/TestTCPLateralUnitTest.java +++ b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/lateral/socket/tcp/TestTCPLateralUnitTest.java @@ -406,7 +406,7 @@ class TestTCPLateralUnitTest } @Override - protected void doWork() + protected void doWork() throws Exception { // nothing to do }
