SLING-7628 Event support depends on Discovery Commons
* copy cleaned InitDelayingTopologyEventListener and test from Discovery Commons
* adjust JobManagerConfiguration and test
* remove dependency org.apache.sling.discovery.commons
diff --git a/pom.xml b/pom.xml
index db18566..927b74b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -264,12 +264,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.discovery.commons</artifactId>
- <version>1.0.20</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.serviceusermapper</artifactId>
<version>1.2.0</version>
diff --git a/src/main/java/org/apache/sling/event/impl/discovery/InitDelayingTopologyEventListener.java b/src/main/java/org/apache/sling/event/impl/discovery/InitDelayingTopologyEventListener.java
new file mode 100644
index 0000000..53afa8b
--- /dev/null
+++ b/src/main/java/org/apache/sling/event/impl/discovery/InitDelayingTopologyEventListener.java
@@ -0,0 +1,233 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+package org.apache.sling.event.impl.discovery;
+
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.sling.discovery.TopologyEvent;
+import org.apache.sling.discovery.TopologyEvent.Type;
+import org.apache.sling.discovery.TopologyEventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This listener facade applies a 'startup delay' to a topology event handler,
+ * that is, it allows to specify a startup time during which any topology events
+ * will be queued and processing only starts after this time.
+ *
+ * What happens aFter the startup time depends on what was received during the delay:
+ * <ul>
+ * <li>if no events were received then this is a no-op</li>
+ * <li>if the last event received was a CHANGING then this facade
+ * waits until it receives the next non-CHANGING event (which should
+ * be the very next), to then simulate an INIT event
+ * (as the discovery API says the first event received is an INIT event).
+ * </li>
+ * <li>if the last event received was not a CHANGING event
+ * (ie it was an INIT, CHANGED or PROPERTIES), then
+ * as soon as the startup time passes this facade will simulate
+ * an INIT event
+ * (again, as the discovery API says the first event received is an INIT event)
+ * </li>
+ * </ul>
+ * Note that users of this facade must call dispose to avoid any async calls
+ * to the delegate after startup, in case they themselves are deactivated!
+ *
+ * This class is a cleaned copy of <code>InitDelayingTopologyEventListener</code> from discovery commons.
+ *
+ **/
+public class InitDelayingTopologyEventListener implements TopologyEventListener {
+
+ /** the delegate which does the actual event processing after delaying **/
+ private final TopologyEventListener delegate;
+
+ /** the sync object used to guard asynchronous discovery events and scheduler callback **/
+ private final Object syncObj = new Object();
+
+ /** the guarded flag indicating whether this listener is active or disposed - used between scheduler callback and dispose **/
+ private final AtomicBoolean active = new AtomicBoolean(false);
+
+ /** flag indicating whether we're still delaying or not **/
+ private volatile boolean delaying = true;
+
+ /** the last pending delayed event - we only have to keep the last event to support all different cases **/
+ private volatile TopologyEvent pendingDelayedEvent;
+
+ private final Logger logger = LoggerFactory.getLogger(InitDelayingTopologyEventListener.class);
+
+ /**
+ * Creates a new init-delaying listener with the given delay and delegate.
+ * <p>
+ * For properly disposing the caller should use the dispose method!
+ * @param startupDelay The startup delay in seconds
+ * @param delegate The topology event listener
+ * @see #dispose()
+ */
+ public InitDelayingTopologyEventListener(final long startupDelay, final TopologyEventListener delegate) {
+
+ if ( delegate == null ) {
+ throw new IllegalArgumentException("delegate must not be null");
+ }
+ if ( startupDelay <= 0) {
+ throw new IllegalArgumentException("startupDelay must be greater than 0, not " + startupDelay);
+ }
+ this.delegate = delegate;
+
+ final Runnable r = new Runnable() {
+
+ @Override
+ public void run() {
+ if (InitDelayingTopologyEventListener.this.active.get()) {
+ // only call afterStartupDelay if we're active
+ // (to avoid this call if disposed in the meantime)
+
+ // and since after disposing this listener is no longer
+ // used - ie it is a throw-away - you can create
+ // such a listener on each activate and dispose it on
+ // deactivate and you'll be fine.
+
+ // in any case - time for calling afterStartupDelay here:
+ afterStartupDelay();
+ }
+ }
+ };
+
+ // mark this listener as active
+ this.active.set(true);
+
+ // schedule me
+ final Timer timer = new Timer();
+ final TimerTask task = new TimerTask() {
+
+ @Override
+ public void run() {
+ r.run();
+ }
+ };
+ timer.schedule(task, startupDelay * 1000);
+ // SLING-5560 : at this point either r is invoked immediately or scheduled after the delay
+ }
+
+ @Override
+ public void handleTopologyEvent(TopologyEvent event) {
+ synchronized ( syncObj ) {
+ if ( this.delaying ) {
+ // when we're delaying, keep hold of the last event
+ // as action afterStartupDelay depends on this last
+ // event
+ this.logger.debug("handleTopologyEvent: delaying processing of received topology event (startup delay active) {}", event);
+ this.pendingDelayedEvent = event;
+
+ // and we're delaying - so stop processing now and return
+ return;
+ } else if ( this.pendingDelayedEvent != null ) {
+ // this means that while we're no longer delaying we still
+ // have a pending delayed event to process.
+ // more concretely, it means that this event is a CHANGING
+ // event (as the others are treated via an artificial INIT event
+ // in afterStartupDelay).
+ // which means that we must now convert the new event into an INIT
+ // to ensure our code gets an INIT first thing
+
+ // paranoia check:
+ if ( event.getType() == Type.TOPOLOGY_CHANGING ) {
+ // this should never happen - but if it does, rinse and repeat
+ this.pendingDelayedEvent = event;
+ this.logger.info("handleTopologyEvent: ignoring received topology event of type CHANGING {}", event);
+ return;
+ } else {
+ // otherwise we now **convert** the event to an init event
+ this.pendingDelayedEvent = null;
+ this.logger.debug("handleTopologyEvent: first stable topology event received after startup delaying. "
+ + "Simulating an INIT event with this new view: {}", event);
+ event = new TopologyEvent(Type.TOPOLOGY_INIT, null, event.getNewView());
+ }
+ } else {
+ // otherwise we're no longer delaying nor do we have a pending-backlog.
+ // we can just pass the event through
+ this.logger.debug("handleTopologyEvent: received topology event {}", event);
+ }
+ }
+ // no delaying applicable - call delegate
+ this.delegate.handleTopologyEvent(event);
+ }
+
+ /**
+ * Marks this listener as no longer active - ensures that it doesn't call the delegate
+ * via any potentially pending scheduler callback.
+ * <p>
+ * Note that after dispose you can *still* call handleTopologyEvent and the events
+ * are passed to the delegate - but those are expected to be 'late' events and not
+ * really part of the normal game. Hence, the caller must also ensure that the
+ * handleTopologyEvent method isn't called anymore (which typically is automatically
+ * guaranteed since the caller is typically an osgi service that gets unregistered anyway)
+ */
+ public void dispose() {
+ this.active.set(false);
+ }
+
+ /**
+ * Called via the scheduler callback when the startup delay has passed.
+ * <p>
+ * Hence only called once!
+ */
+ private void afterStartupDelay() {
+ synchronized ( this.syncObj ) {
+ // stop any future delaying
+ this.delaying = false;
+
+ if ( this.pendingDelayedEvent == null ) {
+ // if no event received while we delayed,
+ // then we don't have to do anything later
+ this.logger.debug("afterStartupDelay: startup delay passed without any events delayed. "
+ + "So, ready for first upcoming INIT event");
+ } else if ( this.pendingDelayedEvent.getType() == Type.TOPOLOGY_CHANGING ) {
+ // if the last delayed event was CHANGING
+ // then we must convert the next upcoming CHANGED, PROPERTIES
+ // into an INIT
+
+ // and the way this is done in this class is by leving this
+ // event sit in this.pendingDelayedEvent, for grabs in handleTopologyEvent later
+ this.logger.debug("afterStartupDelay: startup delay passed, pending delayed event was CHANGING. "
+ + "Waiting for next stable topology event");
+ } else {
+ // otherwise the last delayed event was either an INIT, CHANGED or PROPERTIES
+ // - but in any case we definitely never
+ // processed any INIT - and our code expects an INIT
+ // as the first event ever..
+
+ // so we now convert the event into an INIT
+ final TopologyEvent artificialInitEvent =
+ new TopologyEvent(Type.TOPOLOGY_INIT, null, this.pendingDelayedEvent.getNewView());
+
+ this.logger.debug("afterStartupDelay: startup delay passed, last pending delayed event was stable ({}). "
+ + "Simulating an INIT event with that view: {}", this.pendingDelayedEvent, artificialInitEvent);
+ this.pendingDelayedEvent = null;
+
+ // call the delegate.
+ // we must do this call in the synchronized block
+ // to ensure any concurrent new event waits properly
+ // before the INIT is done
+ delegate.handleTopologyEvent(artificialInitEvent);
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/apache/sling/event/impl/jobs/config/JobManagerConfiguration.java b/src/main/java/org/apache/sling/event/impl/jobs/config/JobManagerConfiguration.java
index b633dc2..8322e1a 100644
--- a/src/main/java/org/apache/sling/event/impl/jobs/config/JobManagerConfiguration.java
+++ b/src/main/java/org/apache/sling/event/impl/jobs/config/JobManagerConfiguration.java
@@ -26,8 +26,8 @@
import org.apache.sling.discovery.TopologyEvent;
import org.apache.sling.discovery.TopologyEvent.Type;
import org.apache.sling.discovery.TopologyEventListener;
-import org.apache.sling.discovery.commons.InitDelayingTopologyEventListener;
import org.apache.sling.event.impl.EnvironmentComponent;
+import org.apache.sling.event.impl.discovery.InitDelayingTopologyEventListener;
import org.apache.sling.event.impl.jobs.tasks.CheckTopologyTask;
import org.apache.sling.event.impl.jobs.tasks.FindUnfinishedJobsTask;
import org.apache.sling.event.impl.jobs.tasks.UpgradeTask;
@@ -231,7 +231,7 @@
public void handleTopologyEvent(TopologyEvent event) {
doHandleTopologyEvent(event);
}
- }, logger);
+ });
} else {
logger.debug("activate: job manager will start without delay. ({}:{})", config.startup_delay(), this.startupDelay);
}
diff --git a/src/test/java/org/apache/sling/event/impl/discovery/InitDelayingTopologyEventListenerTest.java b/src/test/java/org/apache/sling/event/impl/discovery/InitDelayingTopologyEventListenerTest.java
new file mode 100644
index 0000000..83a3ac4
--- /dev/null
+++ b/src/test/java/org/apache/sling/event/impl/discovery/InitDelayingTopologyEventListenerTest.java
@@ -0,0 +1,313 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+package org.apache.sling.event.impl.discovery;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.sling.discovery.ClusterView;
+import org.apache.sling.discovery.InstanceDescription;
+import org.apache.sling.discovery.TopologyEvent;
+import org.apache.sling.discovery.TopologyEvent.Type;
+import org.apache.sling.discovery.TopologyEventListener;
+import org.apache.sling.discovery.TopologyView;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class InitDelayingTopologyEventListenerTest {
+
+ class TestListener implements TopologyEventListener {
+
+ private List<TopologyEvent> events = new LinkedList<TopologyEvent>();
+
+ @Override
+ public void handleTopologyEvent(TopologyEvent event) {
+ synchronized (events) {
+ events.add(event);
+ events.notifyAll();
+ }
+ }
+
+ public List<TopologyEvent> getEvents() {
+ synchronized (events) {
+ return events;
+ }
+ }
+
+ public void waitForEventCnt(int cnt, long timeout) throws InterruptedException {
+ final long start = System.currentTimeMillis();
+ synchronized (events) {
+ while (events.size() != cnt) {
+ final long now = System.currentTimeMillis();
+ final long remaining = (start + timeout) - now;
+ if (remaining > 0) {
+ events.wait(remaining);
+ } else {
+ fail("did not receive " + cnt + " events within " + timeout + " ms, "
+ + "but " + events.size());
+ }
+ }
+ }
+ }
+
+ public void assureEventCnt(int cnt, int timeout) throws InterruptedException {
+ final long start = System.currentTimeMillis();
+ synchronized (events) {
+ while (events.size() == cnt) {
+ final long now = System.currentTimeMillis();
+ final long remaining = (start + timeout) - now;
+ if (remaining > 0) {
+ events.wait(remaining);
+ } else {
+ // success
+ return;
+ }
+ }
+ fail("did not receive " + cnt + " events within " + timeout + " ms, "
+ + "but " + events.size());
+ }
+ }
+ }
+
+ @Test
+ public void testConstructor() throws Exception {
+ final TopologyEventListener delegate = new TopologyEventListener() {
+
+ @Override
+ public void handleTopologyEvent(TopologyEvent event) {
+ // nothing here atm
+ }
+ };
+ try {
+ new InitDelayingTopologyEventListener(-1, delegate);
+ fail("should complain");
+ } catch (IllegalArgumentException re) {
+ // ok
+ }
+ try {
+ new InitDelayingTopologyEventListener(0, delegate);
+ fail("should complain");
+ } catch (IllegalArgumentException re) {
+ // ok
+ }
+ try {
+ new InitDelayingTopologyEventListener(1, null);
+ fail("should complain");
+ } catch (IllegalArgumentException re) {
+ // ok
+ }
+ try {
+ new InitDelayingTopologyEventListener(-1, delegate);
+ fail("should complain");
+ } catch (IllegalArgumentException re) {
+ // ok
+ }
+ try {
+ new InitDelayingTopologyEventListener(0, delegate);
+ fail("should complain");
+ } catch (IllegalArgumentException re) {
+ // ok
+ }
+ try {
+ new InitDelayingTopologyEventListener(1, null);
+ fail("should complain");
+ } catch (IllegalArgumentException re) {
+ // ok
+ }
+ try {
+ new InitDelayingTopologyEventListener(-1, delegate);
+ fail("should complain");
+ } catch (IllegalArgumentException re) {
+ // ok
+ }
+ try {
+ new InitDelayingTopologyEventListener(0, delegate);
+ fail("should complain");
+ } catch (IllegalArgumentException re) {
+ // ok
+ }
+ try {
+ new InitDelayingTopologyEventListener(1, null);
+ fail("should complain");
+ } catch (IllegalArgumentException re) {
+ // ok
+ }
+ }
+
+ private TopologyView createView(boolean current) {
+ final TopologyView view = Mockito.mock(TopologyView.class);
+ Mockito.when(view.isCurrent()).thenReturn(current);
+ final InstanceDescription local = Mockito.mock(InstanceDescription.class);
+ Mockito.when(local.isLeader()).thenReturn(true);
+ Mockito.when(local.isLocal()).thenReturn(true);
+ Mockito.when(local.getSlingId()).thenReturn("id");
+
+ Mockito.when(view.getLocalInstance()).thenReturn(local);
+ final ClusterView localView = Mockito.mock(ClusterView.class);
+ Mockito.when(localView.getId()).thenReturn("1");
+ Mockito.when(localView.getInstances()).thenReturn(Collections.singletonList(local));
+ Mockito.when(view.getClusterViews()).thenReturn(Collections.singleton(localView));
+ Mockito.when(local.getClusterView()).thenReturn(localView);
+
+ return view;
+ }
+
+ private TopologyEvent createEvent(Type type) {
+ TopologyView oldView = createView(false);
+ TopologyView newView = createView(true);
+ switch (type) {
+ case TOPOLOGY_CHANGING: {
+ return new TopologyEvent(type, oldView, null);
+ }
+ case PROPERTIES_CHANGED:
+ case TOPOLOGY_CHANGED: {
+ return new TopologyEvent(type, oldView, newView);
+ }
+ case TOPOLOGY_INIT: {
+ return new TopologyEvent(type, null, newView);
+ }
+ default: {
+ throw new IllegalArgumentException("unknown type: " + type);
+ }
+ }
+ }
+
+ @Test
+ public void testDisposing() throws Exception {
+ final TestListener delegate = new TestListener();
+ InitDelayingTopologyEventListener listener = new InitDelayingTopologyEventListener(1, delegate);
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_INIT));
+ delegate.waitForEventCnt(1, 5000);
+ delegate.assureEventCnt(1, 500); // test framework testing :)
+
+ listener = new InitDelayingTopologyEventListener(1, delegate);
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_INIT));
+ listener.dispose();
+ delegate.assureEventCnt(1, 1000);
+ delegate.assureEventCnt(1, 500);
+ }
+
+ @Test
+ public void testNoEvents() throws Exception {
+ final TestListener delegate = new TestListener();
+ InitDelayingTopologyEventListener listener = new InitDelayingTopologyEventListener(1, delegate);
+ // no events:
+ delegate.assureEventCnt(0, 1500);
+
+ // then the first init is passed through
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_INIT));
+ delegate.waitForEventCnt(1, 5000);
+ assertEquals(delegate.getEvents().get(0).getType(), Type.TOPOLOGY_INIT);
+
+ doTestAdditionalEventsAfterInit(delegate, listener);
+ }
+
+ private void doTestAdditionalEventsAfterInit(final TestListener delegate, InitDelayingTopologyEventListener listener)
+ throws InterruptedException {
+ // 2nd one too
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGING));
+ delegate.waitForEventCnt(2, 5000);
+ assertEquals(delegate.getEvents().get(1).getType(), Type.TOPOLOGY_CHANGING);
+
+ // 3rd one too
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGED));
+ delegate.waitForEventCnt(3, 5000);
+ assertEquals(delegate.getEvents().get(2).getType(), Type.TOPOLOGY_CHANGED);
+
+ // 4th one too
+ listener.handleTopologyEvent(createEvent(Type.PROPERTIES_CHANGED));
+ delegate.waitForEventCnt(4, 5000);
+ assertEquals(delegate.getEvents().get(3).getType(), Type.PROPERTIES_CHANGED);
+
+ // 5th one too
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGING));
+ delegate.waitForEventCnt(5, 5000);
+ assertEquals(delegate.getEvents().get(4).getType(), Type.TOPOLOGY_CHANGING);
+
+ // 6th one too
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGED));
+ delegate.waitForEventCnt(6, 5000);
+ assertEquals(delegate.getEvents().get(5).getType(), Type.TOPOLOGY_CHANGED);
+
+ }
+
+ @Test
+ public void testChanging0() throws Exception {
+ final TestListener delegate = new TestListener();
+ InitDelayingTopologyEventListener listener = new InitDelayingTopologyEventListener(1, delegate);
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_INIT));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGING));
+ delegate.assureEventCnt(0, 1000);
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGED));
+ delegate.waitForEventCnt(1, 5000);
+ assertEquals(delegate.getEvents().get(0).getType(), Type.TOPOLOGY_INIT);
+
+ doTestAdditionalEventsAfterInit(delegate, listener);
+ }
+
+ @Test
+ public void testChanging1() throws Exception {
+ final TestListener delegate = new TestListener();
+ InitDelayingTopologyEventListener listener = new InitDelayingTopologyEventListener(1, delegate);
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_INIT));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGING));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGED));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGING));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGED));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGING));
+ delegate.assureEventCnt(0, 1000);
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGED));
+ delegate.waitForEventCnt(1, 5000);
+ assertEquals(delegate.getEvents().get(0).getType(), Type.TOPOLOGY_INIT);
+
+ doTestAdditionalEventsAfterInit(delegate, listener);
+ }
+
+ @Test
+ public void testChanged() throws Exception {
+ final TestListener delegate = new TestListener();
+ InitDelayingTopologyEventListener listener = new InitDelayingTopologyEventListener(1, delegate);
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_INIT));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGING));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGED));
+ delegate.waitForEventCnt(1, 5000);
+ assertEquals(delegate.getEvents().get(0).getType(), Type.TOPOLOGY_INIT);
+
+ doTestAdditionalEventsAfterInit(delegate, listener);
+ }
+
+ @Test
+ public void testProperties() throws Exception {
+ final TestListener delegate = new TestListener();
+ InitDelayingTopologyEventListener listener = new InitDelayingTopologyEventListener(1, delegate);
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_INIT));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGING));
+ listener.handleTopologyEvent(createEvent(Type.TOPOLOGY_CHANGED));
+ listener.handleTopologyEvent(createEvent(Type.PROPERTIES_CHANGED));
+ delegate.waitForEventCnt(1, 5000);
+ assertEquals(delegate.getEvents().get(0).getType(), Type.TOPOLOGY_INIT);
+
+ doTestAdditionalEventsAfterInit(delegate, listener);
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/event/impl/jobs/config/JobManagerConfigurationTest.java b/src/test/java/org/apache/sling/event/impl/jobs/config/JobManagerConfigurationTest.java
index fa5ccf6..a2e68cd 100644
--- a/src/test/java/org/apache/sling/event/impl/jobs/config/JobManagerConfigurationTest.java
+++ b/src/test/java/org/apache/sling/event/impl/jobs/config/JobManagerConfigurationTest.java
@@ -34,8 +34,8 @@
import org.apache.sling.discovery.TopologyEvent;
import org.apache.sling.discovery.TopologyEventListener;
import org.apache.sling.discovery.TopologyView;
-import org.apache.sling.discovery.commons.InitDelayingTopologyEventListener;
import org.apache.sling.event.impl.TestUtil;
+import org.apache.sling.event.impl.discovery.InitDelayingTopologyEventListener;
import org.junit.Test;
import org.mockito.Mockito;