java - Why could I receive a ClassNotFoundException in a background thread created by me on Tomcat 8? -
i'm having issue micro-service deployed on tomcat 9 java 8. explaining better, have rest service webapp (war) deployed on tomcat 9, webapp has 2 parts:
- one rest service itself, once it's called, receive parameters , creates object mypackagedto (serializable) class them, calls rabbitmq queue , publish object queue, part works well.
- the second part conformed weblistener creates background thread connects queue on rabbitmq consumer. part failing when throws classnotfoundexception when dequeue object (mypackagedto) queued first part.
the thing is, packed on same jar. there classes of war packed on jar located on web-inf/lib, not unpacked on web-inf/classes. (i'm using maven "archiveclasses" true)
so, after reading while, found this post talk this, , i'm thinking problem related class-loader used thread created in weblistener @ application deploy.
it's little hard understand this, because inside same jar , same war, there's 1 tomcat server (only 1 jvm).
is there possibility setting class-loader new thread? or how create background thread on same class-loader webcontainer threads?
i'll doing test when home, if find root of issue or @ least work-around, i'll post it.
thanks lot.
===============
adding information:
i'm creating background thread in way:
@weblistener public class mainweblistener implements servletcontextlistener { private thread threadqueuelistener; private queuethreadlistener queuelistener; @override public void contextdestroyed(servletcontextevent arg0) { try { queuelistener.disconnectqueue(); thread.sleep(queuethreadlistener.queue_delivery_timeout + 20); } catch (throwable tt) { tt.printstacktrace(); } } @override public void contextinitialized(servletcontextevent arg0) { try { queuelistener = new queuethreadlistener(); threadqueuelistener = new thread(queuelistener); threadqueuelistener.setcontextclassloader(thread.currentthread().getcontextclassloader()); threadqueuelistener.start(); } catch (throwable tt) { tt.printstacktrace(); } } }
i've added line set classloader, i'm getting same error. classnotfoundexception.
this thread class:
public class queuethreadlistener implements runnable { public static final string queue_name = "mq_test_rest_queue"; public static final long queue_delivery_timeout = 2000; private boolean tobecontinued = true; private connection connection; @override public void run() { connectionfactory factory = new connectionfactory(); factory.sethost("127.0.0.1"); try { connection = factory.newconnection(); channel channel = connection.createchannel(); queueingconsumer consumer = new queueingconsumer(channel); channel.basicconsume(queue_name, true, consumer); while (tobecontinued) { try { queueingconsumer.delivery delivery = consumer.nextdelivery(queue_delivery_timeout); if (delivery != null) { infodto = (infodto)serializationutils.deserialize(delivery.getbody()); system.out.println("--> package received.. [name: " + to.getname() + " | age: " + to.getage()+"]"); } } catch (exception ee) { ee.printstacktrace(); } } connection.close(); } catch (timeoutexception t) { t.printstacktrace(); } catch (ioexception x) { x.printstacktrace(); } catch (shutdownsignalexception e) { e.printstacktrace(); } catch (consumercancelledexception e) { e.printstacktrace(); } } public void disconnectqueue() { tobecontinued = false; } }
method called disconnectqueue disconnect "gracefully" queue.
infodto pojo serializable:
public class infodto implements serializable { private static final long serialversionuid = 5274775183934376052l; private string name; private int age; public infodto(string name, int age) { super(); this.name = name; this.age = age; } public string getname() { return name; } public void setname(string name) { this.name = name; } public int getage() { return age; } public void setage(int age) { this.age = age; } }
============
this stack trace:
org.apache.commons.lang.serializationexception: java.lang.classnotfoundexception: com.guambo.test.rest.rabbit.dto.infodto @ org.apache.commons.lang.serializationutils.deserialize(serializationutils.java:165) @ org.apache.commons.lang.serializationutils.deserialize(serializationutils.java:192) @ com.guambo.test.rest.rabbit.listener.queuethreadlistener.run(queuethreadlistener.java:58) @ java.lang.thread.run(thread.java:745) caused by: java.lang.classnotfoundexception: com.guambo.test.rest.rabbit.dto.infodto @ java.net.urlclassloader.findclass(urlclassloader.java:381) @ java.lang.classloader.loadclass(classloader.java:424) @ java.lang.classloader.loadclass(classloader.java:357) @ java.lang.class.forname0(native method) @ java.lang.class.forname(class.java:348) @ java.io.objectinputstream.resolveclass(objectinputstream.java:626) @ java.io.objectinputstream.readnonproxydesc(objectinputstream.java:1613) @ java.io.objectinputstream.readclassdesc(objectinputstream.java:1518) @ java.io.objectinputstream.readordinaryobject(objectinputstream.java:1774) @ java.io.objectinputstream.readobject0(objectinputstream.java:1351) @ java.io.objectinputstream.readobject(objectinputstream.java:371) @ org.apache.commons.lang.serializationutils.deserialize(serializationutils.java:162)
thanks in advance.
Álvaro
the serializationutils class uses objectinputstream, requires serializationutils must have visibility infodto class deserializing. must either move serializationutils class war alongside infodto class (recommended) or move infodtd class same classpath serializationutils (not recommended).
Comments
Post a Comment