Skip to content
Browse files

wicket-push-timer:

 - the cleanup background task is now unloaded on application shutdown


git-svn-id: file:///home/igor/dev/stuff/svnbackup/trunk@5670 ef7698a4-5110-0410-9fc6-c7eb3693863f
  • Loading branch information...
1 parent 47c74db commit b00dc54896b504486fff99cadd45d0306e04716a seb committed Dec 5, 2010
View
15 jdk-1.6-parent/push-parent/push-cometd/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,6 @@
-#Wed Oct 27 18:59:36 AST 2010
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.source=1.6
+#Tue Nov 02 12:44:35 CET 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
View
18 jdk-1.6-parent/push-parent/push-cometd/.settings/org.maven.ide.eclipse.prefs
@@ -1,9 +1,9 @@
-#Wed Oct 20 20:52:33 MDT 2010
-activeProfiles=
-eclipse.preferences.version=1
-fullBuildGoals=process-test-resources
-includeModules=false
-resolveWorkspaceProjects=true
-resourceFilterGoals=process-resources resources\:testResources
-skipCompilerPlugin=true
-version=1
+#Tue Nov 02 12:44:34 CET 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
View
44 ...6-parent/push-parent/push-core/src/main/java/org/wicketstuff/push/PushDetachListener.java
@@ -1,44 +0,0 @@
-/**
- *
- */
-package org.wicketstuff.push;
-
-import org.apache.wicket.Application;
-import org.apache.wicket.Component;
-import org.apache.wicket.IClusterable;
-import org.apache.wicket.IDetachListener;
-
-/**
- *
- * @author Rodolfo Hansen
- */
-public abstract class PushDetachListener implements IDetachListener, IClusterable
-{
- private static final long serialVersionUID = 1L;
-
- private IDetachListener chainedListener;
-
- protected PushDetachListener(final Application app)
- {
- this.chainedListener = app.getFrameworkSettings().getDetachListener();
- }
-
- public final void onDetach(Component component)
- {
- if (chainedListener != null)
- chainedListener.onDetach(component);
- }
-
- public final void onDestroyListener()
- {
- destroyService();
-
- if (chainedListener != null)
- chainedListener.onDestroyListener();
-
- chainedListener = null;
- }
-
- protected abstract void destroyService();
-
-}
View
15 jdk-1.6-parent/push-parent/push-examples/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,6 @@
-#Sun Oct 03 16:37:03 MDT 2010
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.source=1.6
+#Tue Nov 02 12:44:35 CET 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
View
18 jdk-1.6-parent/push-parent/push-examples/.settings/org.maven.ide.eclipse.prefs
@@ -1,9 +1,9 @@
-#Wed Dec 01 15:29:44 MST 2010
-activeProfiles=
-eclipse.preferences.version=1
-fullBuildGoals=process-test-resources
-includeModules=false
-resolveWorkspaceProjects=true
-resourceFilterGoals=process-resources resources\:testResources
-skipCompilerPlugin=true
-version=1
+#Tue Nov 02 12:44:34 CET 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
View
55 jdk-1.6-parent/push-parent/push-examples/src/test/java/org/wicketstuff/push/Start.java
@@ -0,0 +1,55 @@
+package org.wicketstuff.push;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.bio.SocketConnector;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+/**
+ * Starts Jetty for demos
+ */
+public class Start
+{
+ public static void main(final String[] args) throws Exception
+ {
+ final Server server = new Server();
+ final SocketConnector connector = new SocketConnector();
+
+ // Set some timeout options to make debugging easier.
+ connector.setMaxIdleTime(1000 * 60 * 60);
+ connector.setSoLingerTime(-1);
+ connector.setPort(8080);
+ server.setConnectors(new Connector[] { connector });
+
+ final WebAppContext bb = new WebAppContext();
+ bb.setServer(server);
+ bb.setContextPath("/");
+ bb.setWar("src/main/webapp");
+
+ // START JMX SERVER
+ // MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+ // MBeanContainer mBeanContainer = new MBeanContainer(mBeanServer);
+ // server.getContainer().addEventListener(mBeanContainer);
+ // mBeanContainer.start();
+
+ server.setHandler(bb);
+
+ try
+ {
+ System.out.println(">>> STARTING EMBEDDED JETTY SERVER, PRESS ANY KEY TO STOP");
+ server.start();
+ System.in.read();
+ System.out.println(">>> STOPPING EMBEDDED JETTY SERVER");
+ // while (System.in.available() == 0) {
+ // Thread.sleep(5000);
+ // }
+ server.stop();
+ server.join();
+ }
+ catch (final Exception e)
+ {
+ e.printStackTrace();
+ System.exit(100);
+ }
+ }
+}
View
19 jdk-1.6-parent/push-parent/push-timer/.settings/org.eclipse.jdt.core.prefs
@@ -1,13 +1,6 @@
-#Thu Dec 02 10:34:16 MST 2010
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.5
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
-org.eclipse.jdt.core.compiler.source=1.5
+#Tue Nov 02 12:44:35 CET 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
View
18 jdk-1.6-parent/push-parent/push-timer/.settings/org.maven.ide.eclipse.prefs
@@ -1,9 +1,9 @@
-#Wed Oct 20 20:54:17 MDT 2010
-activeProfiles=
-eclipse.preferences.version=1
-fullBuildGoals=process-test-resources
-includeModules=false
-resolveWorkspaceProjects=true
-resourceFilterGoals=process-resources resources\:testResources
-skipCompilerPlugin=true
-version=1
+#Tue Nov 02 12:44:34 CET 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
View
45 ...rent/push-timer/src/main/java/org/wicketstuff/push/timer/ApplicationShutdownListener.java
@@ -0,0 +1,45 @@
+/*
+ * 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.wicketstuff.push.timer;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.IDestroyer;
+import org.apache.wicket.IInitializer;
+
+/**
+ * @author <a href="http://sebthom.de/">Sebastian Thomschke</a>
+ */
+public class ApplicationShutdownListener implements IInitializer, IDestroyer
+{
+ /**
+ * {@inheritDoc}
+ */
+ public void destroy(final Application application)
+ {
+ final TimerPushService service = TimerPushService.INSTANCES.get(application);
+ if (service != null)
+ service.onApplicationShutdown();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void init(final Application application)
+ {
+
+ }
+}
View
39 ...nt/push-parent/push-timer/src/main/java/org/wicketstuff/push/timer/TimerPushBehavior.java
@@ -20,6 +20,7 @@
import java.util.Map;
import java.util.Map.Entry;
+import org.apache.wicket.Component;
import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.IHeaderResponse;
@@ -52,9 +53,8 @@
<EventType> TimerPushChannel<EventType> addPushChannel(
final IPushEventHandler<EventType> pushEventHandler, final Duration pollingInterval)
{
- if (pollingInterval.lessThan(getUpdateInterval())) {
- setUpdateInterval(pollingInterval);
- }
+ if (pollingInterval.lessThan(getUpdateInterval()))
+ setUpdateInterval(pollingInterval);
final TimerPushChannel<EventType> channel = new TimerPushChannel<EventType>(pollingInterval);
handlers.put(channel, pushEventHandler);
@@ -71,26 +71,22 @@ protected void onTimer(final AjaxRequestTarget target)
final WebRequest request = (WebRequest)RequestCycle.get().getRequest();
- if (request.getRequestParameters().getParameterValue("unload") != null) {
- // if the page is unloaded notify the pushService to disconnect all push channels
- for (final TimerPushChannel<?> channel : handlers.keySet()) {
- pushService.onDisconnect(channel);
- }
- } else {
- // retrieve all collected events and process them
- for (final Entry<TimerPushChannel, IPushEventHandler> entry : handlers.entrySet()) {
- for (final Object event : pushService.pollEvents(entry.getKey())) {
- try
+ if (request.getRequestParameters().getParameterValue("unload") != null)
+ // if the page is unloaded notify the pushService to disconnect all push channels
+ for (final TimerPushChannel<?> channel : handlers.keySet())
+ pushService.onDisconnect(channel);
+ else
+ // retrieve all collected events and process them
+ for (final Entry<TimerPushChannel, IPushEventHandler> entry : handlers.entrySet())
+ for (final Object event : pushService.pollEvents(entry.getKey()))
+ try
{
entry.getValue().onEvent(target, event);
}
catch (final RuntimeException ex)
{
LOG.error("Failed while processing event", ex);
}
- }
- }
- }
}
int removePushChannel(final IPushChannel<?> channel)
@@ -99,17 +95,16 @@ int removePushChannel(final IPushChannel<?> channel)
// adjust the polling interval based on the fastest remaining channel
Duration newPollingInterval = Duration.MAXIMUM;
- for (final TimerPushChannel chan : handlers.keySet()) {
- if (chan.getPollingInterval().lessThan(newPollingInterval)) {
- newPollingInterval = chan.getPollingInterval();
- }
- }
+ for (final TimerPushChannel chan : handlers.keySet())
+ if (chan.getPollingInterval().lessThan(newPollingInterval))
+ newPollingInterval = chan.getPollingInterval();
setUpdateInterval(newPollingInterval);
return handlers.size();
}
- public void renderHead(final IHeaderResponse response)
+ @Override
+ public void renderHead(final Component c, final IHeaderResponse response)
{
// install an onunload handler
response.renderJavascript("history.navigationMode = 'compatible';",
View
78 ...ent/push-parent/push-timer/src/main/java/org/wicketstuff/push/timer/TimerPushService.java
@@ -19,9 +19,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import java.util.Set;
-import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -40,14 +38,13 @@
import org.wicketstuff.push.IPushChannelDisconnectedListener;
import org.wicketstuff.push.IPushEventHandler;
import org.wicketstuff.push.IPushService;
-import org.wicketstuff.push.PushDetachListener;
/**
* @author <a href="http://sebthom.de/">Sebastian Thomschke</a>
*/
public class TimerPushService implements IPushService
{
- private static final class PushChannelState
+ private static final class PushChannelState
{
protected final TimerPushChannel<?> channel;
protected Time lastPolledAt = Time.now();
@@ -62,8 +59,8 @@ protected PushChannelState(final TimerPushChannel<?> channel)
private static final Logger LOG = LoggerFactory.getLogger(TimerPushService.class);
- private static final Map<Application, TimerPushService> INSTANCES =
- new WeakHashMap<Application, TimerPushService>(2);
+ static final ConcurrentHashMap<Application, TimerPushService> INSTANCES = new ConcurrentHashMap<Application, TimerPushService>(
+ 2);
public static TimerPushService get()
{
@@ -75,32 +72,22 @@ public static TimerPushService get(final Application application)
TimerPushService service = INSTANCES.get(application);
if (service == null)
{
- service = new TimerPushService(application);
- INSTANCES.put(application, service);
+ service = new TimerPushService();
+ final TimerPushService existingInstance = INSTANCES.putIfAbsent(application, service);
+
+ if (existingInstance == null)
+ /*
+ * If this is the first instance of this service for the given application, then
+ * schedule the cleanup task.
+ */
+ service.setCleanupInterval(Duration.seconds(60));
+ else
+ // If it is not the first instance, throw it away.
+ service = existingInstance;
}
return service;
}
- /**
- * Used to
- * @author Rodolfo Hansen
- */
- private final class TimerPushDetachListener extends PushDetachListener
- {
- private static final long serialVersionUID = 1L;
-
- private TimerPushDetachListener(Application app)
- {
- super(app);
- }
-
- @Override
- protected void destroyService()
- {
- _cleanupExecutor.shutdown();
- }
- }
-
private Duration _defaultPollingInterval = Duration.seconds(2);
private Duration _maxTimeLag = Duration.seconds(10);
@@ -111,6 +98,7 @@ protected void destroyService()
private ScheduledFuture<?> _cleanupFuture = null;
private final Runnable _cleanupTask = new Runnable()
{
+ @Override
public void run()
{
LOG.debug("Running timer push channel cleanup task...");
@@ -126,11 +114,9 @@ public void run()
}
};
-
- private TimerPushService(Application app)
+ private TimerPushService()
{
- app.getFrameworkSettings().setDetachListener(new TimerPushDetachListener(app));
- setCleanupInterval(Duration.seconds(60));
+ super();
}
private TimerPushBehavior _findPushBehaviour(final Component component)
@@ -149,7 +135,8 @@ private void _onConnect(final TimerPushChannel<?> pushChannel)
/**
* {@inheritDoc}
*/
- public void addPushChannelDisconnectedListener(final IPushChannelDisconnectedListener listener)
+ @Override
+ public void addPushChannelDisconnectedListener(final IPushChannelDisconnectedListener listener)
{
_disconnectListeners.add(listener);
}
@@ -185,7 +172,8 @@ public Duration getMaxTimeLag()
/**
* {@inheritDoc}
*/
- public <EventType> TimerPushChannel<EventType> installPushChannel(final Component component,
+ @Override
+ public <EventType> TimerPushChannel<EventType> installPushChannel(final Component component,
final IPushEventHandler<EventType> pushEventHandler)
{
return installPush(component, pushEventHandler, _defaultPollingInterval);
@@ -194,7 +182,8 @@ public Duration getMaxTimeLag()
/**
* {@inheritDoc}
*/
- public boolean isConnected(final IPushChannel<?> pushChannel)
+ @Override
+ public boolean isConnected(final IPushChannel<?> pushChannel)
{
if (pushChannel instanceof TimerPushChannel)
{
@@ -213,6 +202,15 @@ public boolean isConnected(final IPushChannel<?> pushChannel)
return false;
}
+ void onApplicationShutdown()
+ {
+ LOG.info("Shutting down timer push service...");
+ _cleanupFuture.cancel(false);
+ _cleanupFuture = null;
+ _cleanupExecutor.shutdown();
+ INSTANCES.remove(this);
+ }
+
void onDisconnect(final TimerPushChannel<?> pushChannel)
{
if (_channelStates.remove(pushChannel) != null)
@@ -258,7 +256,8 @@ void onDisconnect(final TimerPushChannel<?> pushChannel)
/**
* {@inheritDoc}
*/
- public <EventType> void publish(final IPushChannel<EventType> pushChannel, final EventType event)
+ @Override
+ public <EventType> void publish(final IPushChannel<EventType> pushChannel, final EventType event)
{
if (pushChannel instanceof TimerPushChannel)
{
@@ -281,7 +280,8 @@ void onDisconnect(final TimerPushChannel<?> pushChannel)
/**
* {@inheritDoc}
*/
- public void removePushChannelDisconnectedListener(
+ @Override
+ public void removePushChannelDisconnectedListener(
final IPushChannelDisconnectedListener listener)
{
_disconnectListeners.remove(listener);
@@ -315,7 +315,8 @@ public void setMaxTimeLag(final Duration maxTimeLag)
/**
* {@inheritDoc}
*/
- public void uninstallPushChannel(final Component component, final IPushChannel<?> pushChannel)
+ @Override
+ public void uninstallPushChannel(final Component component, final IPushChannel<?> pushChannel)
{
if (pushChannel instanceof TimerPushChannel)
{
@@ -328,5 +329,4 @@ public void uninstallPushChannel(final Component component, final IPushChannel<?
else
LOG.warn("Unsupported push channel type {}", pushChannel);
}
-
}
View
1 jdk-1.6-parent/push-parent/push-timer/src/main/resources/wicket.properties
@@ -0,0 +1 @@
+initializer=org.wicketstuff.push.timer.ApplicationShutdownListener

0 comments on commit b00dc54

Please sign in to comment.
Something went wrong with that request. Please try again.