Getting ClassNotFound when class is in the application when creating unmanaged threads or using java.util.Timer, or registering Message Listeners

Solution Verified - Updated

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 8
    • 7
    • 6
    • 5
    • 4

Issue

We are getting a ClassNotFoundException for a class that is in the application when we create our own threads from the application.

java.lang.NoClassDefFoundError: com/jboss.examples/Example
  at com.jboss.examples.ExampleService.invoke(ExampleService.java:123)
  ...
  at com.jboss.examples.thread.ExampleThread$ExampleThreadRunnable.run(ExampleThread.java:123)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  at java.lang.Thread.run(Thread.java:750)
Caused by: java.lang.ClassNotFoundException: com.jboss.examples.Example from [Module "deployment.application.ear.web.war" from Service Module Loader]
  at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255)
  at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
  at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
  at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
  ... 17 more

Resolution

The container (JBoss EAP) will set the thread content classloader (TCCL) for managed threads (threads created by JBoss EAP). If you create unmanaged threads, then JBoss EAP is not involved and thus your application should set the thread context classloader.

Creating Threads

If your application needs to create threads, it should use the spec EE Concurrency Utilities [1], creating the threads via the Concurrency Utilities creates a managed thread and setting the TCCL would be handled automatically by JBoss EAP.

If you do not use the Concurrency Utils to create managed threads, then you will need to wrap your code inside of the run method with setting the TCCL and setting it back to its previous value as the end of the method such as:

public void run() {
  ClassLoader previous = Thread.currentThread().getContextClassLoader();
  try {
     Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

     // Do the work here

  } finally {
    Thread.currentThread().setContextClassLoader(previous);
  }
}

java.util.Timer

If you use the JDK java.util.Timer, it also will create threads , these threads will be unmanaged. You can use EE EJB Timers instead of the JDK Timer, and then the container (JBoss EAP) will take care of setting the TCCL. Otherwise you will need to wrap your code inside of the TimerTask run method, for example:

    TimerTask task = new TimerTask() {
        public void run() {

          ClassLoader previous = Thread.currentThread().getContextClassLoader();
          try {
            Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

            // Do the work here

          } finally {
            Thread.currentThread().setContextClassLoader(previous);
          }
        }
    };

MessageListener

If your application is implementing a MessageListener and registering it, then it would need to set the TCCL. The recommended approach would be to instead add @MessageDriven or using the ejb-jar.xml to make your class that implements MessageListener a Message Driven Bean EJB, where in then the container (JBoss EAP) would take care of managing setting the TCCL automatically.

If you are not going to use it as a MDB, then you would need to set/reset the TCCL such as :

public void onMessage(Message message) {
  ClassLoader previous = Thread.currentThread().getContextClassLoader();
  try {
     Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

     // Do the work here

  } finally {
    Thread.currentThread().setContextClassLoader(previous);
  }
}
Components

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.