# Tomcat, Exceptions beim redeploy



## akkie (7. Dez 2009)

Hi,

wenn ich meine Webanwendung über den Tomcat-Manager deploye bekomme ich ständig Exceptions dieser Art.


```
Exception in thread "ActiveMQ Session Task" java.lang.NoClassDefFoundError: net/project/chat/model/MessageService
        at net.project.chat.messaging.JMSTopicListener.onMessage(JMSTopicListener.java:55)
        at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1088)
        at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:127)
        at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:197)
        at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:122)
        at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:43)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:619)
14:07:59,424 INFO  [WebappClassLoader] Illegal access: this web application instance has been stopped already.  Could not load net.project.chat.model.MessageService.  The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
        at org.apache.catalina.loader.WebappClassLoader.loadClass(Unknown Source)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
        at net.project.chat.messaging.JMSTopicListener.onMessage(JMSTopicListener.java:55)
        at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1088)
        at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:127)
        at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:197)
        at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:122)
        at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:43)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:619)
```

oder


```
12:53:01,639 ERROR [ActiveMQMessageConsumer] ID:saturn.imaxx21.local-52799-1260185467494-2:0:1:1 Exception while processing message: java.lang.IllegalStateException: Timer already cancelled.
java.lang.IllegalStateException: Timer already cancelled.
	at java.util.Timer.sched(Timer.java:354)
	at java.util.Timer.schedule(Timer.java:170)
	at net.project.chat.ChatSessionMonitor.registerSession(ChatSessionMonitor.java:112)
	at net.project.chat.ChatSessionMonitor.keepSessionAlive(ChatSessionMonitor.java:150)
	at net.project.chat.ChatSessionMonitor.keepSessionAlive(ChatSessionMonitor.java:129)
	at net.project.chat.model.MessageService.handleSessionActiveMessage(MessageService.java:394)
	at net.project.chat.model.MessageService.handleMessage(MessageService.java:127)
	at net.project.chat.messaging.JMSTopicListener.onMessage(JMSTopicListener.java:56)
	at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1088)
	at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:127)
	at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:197)
	at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:122)
	at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:43)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
```

Die 1. Exception tritt nicht gleich nach dem redeploy auf sondern wenn ich mich wieder mit dem Client verbinde. Die 2. Exception sofort. Wobei dies auch nicht immer geschieht.

Hat jemand eine Idee wie ich das beheben kann?

Mfg Akkie


----------



## akkie (13. Jan 2010)

Hi,

das Problem besteht immer noch.

Zu der 2. Excpetion kann ich sagen das ich mehrere Timer zum Monitoren benutze. Beim undeploy werden diese aber nicht richtig beendet, so das sie beim deploy die Exception werfen. Ich benutze zwar einen ServletContextListener der die Timer beim undeploy canceled. Trotzdem scheinen sie noch weiter zu existieren. Wie kann ich die Timer beim undeploy richtig beenden?

Mfg Akkie


----------



## FArt (13. Jan 2010)

akkie hat gesagt.:


> Wie kann ich die Timer beim undeploy richtig beenden?
> 
> Mfg Akkie



Wie beendest du sie denn falsch?

Prinzipiell kann man sagen, dass du ALLE Ressourcen, die dein Webservice verwendet beim Beenden des Servlets auch freigegeben werden müssen. Unschön sind dabei: eigene Threads, Timer, eigene Sockets, statics, Singletons, ...

gemeine Vermutung: solche Probleme treten gerne auf, wenn man eigentlich einen Applicationserver für seine Anforderungen benötigen würde, aber man nur einen Tomcat benutzt und ein wenig versucht zu tricksen  ;-)


----------



## akkie (14. Jan 2010)

> Unschön sind dabei: eigene Threads, Timer, eigene Sockets, statics, Singletons, ...



Und ich denke da liegt genau mein Problem.

Die Monitor Klasse ist als Singleton implementiert.


```
public class ChatClientMonitor
{
	/**
	 * The instance of this class.
	 */
	private static ChatClientMonitor instance;
	
	/**
	 * Contains all registered clients and they corresponding timer tasks.
	 */
	private Hashtable<Integer, TimerTask> clients = new Hashtable<Integer, TimerTask>();
		
	/**
	 * The timer object which shedules the timer tasks for every client.
	 */
	private Timer timer = new Timer();
	
	/**
	 * Return a single instance of this class.
	 * 
	 * @return a single instance of this class
	 * @see [url=http://java.sun.com/developer/technicalArticles/Programming/singletons/]When is a Singleton not a Singleton?[/url]
	 */
	public static synchronized ChatClientMonitor getInstance()
	{
		if (instance == null) {
			instance = new ChatClientMonitor();
		}
		
		return instance;
	}
	
	/**
	 * Unregister all clients and unset the singelton instance.
	 */
	public static synchronized void finalizeInstance()
	{
		if (instance == null) {
			return;
		}
		
		instance.unregisterAll();
		instance = null;
	}
	
	/**
	 * Unregister all clients.
	 */
	public void unregisterAll()
	{
		Enumeration<Integer> keys = this.clients.keys();
		while (keys.hasMoreElements()) {
			int id = keys.nextElement();
			this.unregisterClient(id);
		}
		this.clients = new Hashtable<Integer, TimerTask>();
		this.timer.cancel();
	}
}
```

In meinem ContextListener rufe ich die Methode ChatClientMonitor.finalizeInstance() dann auf. Normalerweise sollte das doch ausreichen!?



> gemeine Vermutung: solche Probleme treten gerne auf, wenn man eigentlich einen Applicationserver für seine Anforderungen benötigen würde, aber man nur einen Tomcat benutzt und ein wenig versucht zu tricksen


Inwieweit wäre denn das Vorgehen bei einem Applicationserver  anders?

Mfg Akkie


----------



## FArt (14. Jan 2010)

Es sieht also so aus, als ob der Timer noch existiert (cancel wurde schon ausgeführt, also vermutlich der "alte" Timer) während schon neue Sessions (auf einem vermeintlich "neuen" Timer) sich nicht registrieren können.

Stelle sicher, dass die Ressourcen des alten Services auch ALLE weg sind. Wenn du den zeitlichen Ablauf nicht ganz verstehst, dann baue sinnvolles Logging ein und vieles wird klarer.

Ein Webserver ist prinzipiell dazu da Requests von außen zu beantworten. Über die Session hält er evtl. noch ein wenig Status, aber asynchrone Verarbeitung ist oft möglich, aber man muss eben wissen was man wann tut und sicherstellen, dass man die (z.B. Servlet-Spec) kennt und auch berücksichtigt.


----------

