I am using JBoss 7 (dependency loading was changed in this version).
My war-application uploads to server jars and need to use classes inside of them, but it gets ClassNotFoundException
.
So I can't find a way to add jar-dependencies to modules dynamically - MANIFEST.MF
, jboss-deployment-structure.xml
are static way of doing this.

- 43,948
- 41
- 217
- 277

- 121
- 1
- 6
-
1You mention that dependency loading was changed for JBoss 7. Have you done this using earlier versions of JBoss? Can you describe your previous approach? – GargantuChet Jan 02 '13 at 19:24
-
I presume that [this documentation](https://community.jboss.org/wiki/ModuleCompatibleClassloadingGuide) can be helpful – higuaro Jan 07 '13 at 16:24
3 Answers
Just rephrasing the question to make sure I it correctly;
You want to be able to upload an arbitrary jar file to the server and then use the contained classes/resources in the JVM? Without restarting the JVM and/or editing your configuration ofcourse.
If that's the case, then you should load the jar into a classloader (chaining your current classloader if needed) and then load the class from there.
Assuming you store the jar-file physically on the server you could for example do something like:
public static Class<?> loadClass(String className, String jarFileLocation)
throws MalformedURLException, ClassNotFoundException {
URL jarUrl = new File(jarFileLocation).toURI().toURL();
ClassLoader classLoader = new URLClassLoader(new URL[] {jarUrl }, MyClass.class.getClassLoader());
return classLoader.loadClass(className);
}
public static Object executeMethodOndClass(String methodName, Class<?>[] parameterTypes,
Object[] parameters, String className, String jarFileLocation)
throws MalformedURLException, ClassNotFoundException, IllegalAccessException, InstantiationException,
NoSuchMethodException, InvocationTargetException {
Class<?> loadedClass = loadClass(className, jarFileLocation);
Method method = loadedClass.getMethod(methodName, parameterTypes);
Object instance = loadedClass.newInstance();
return method.invoke(instance, parameters);
}
Ps. this is crude code, I didn't even compile or test it; it should work, but nothing more then that and there is the chance I overlooked something or made a typo ;-)
Pps. allowing custom jar files to be uploaded and classes from it to be executed does bring a number of (security) risks with it.

- 176
- 1
- 6
-
I like this answer but doesn't -quite- address the question. The difference ultimately between setting a dependency in jboss via manfiest/jboss-deployment-structure.xml is that it implicitly makes all the classes you depend on available in your application classloader, without you needing to explicitly name them or classload them separately. This has the benefit of ensuring that any blackbox systems you hand control over to (dispatching to jsp handler, etc) will also have access to those classes (if they're started with the same application classloader of the deployment). – Rhys Jan 10 '13 at 10:10
@Rage: This question on stackoverflow asked earlier might give you some inputs how to organize jars: be it your own or third-party jars.
Try this (I've grabbed it somewhere on the Internet):
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class ClassPathHacker {
private static final Class<?>[] PARAMS = new Class<?>[] { URL.class };
private static final Logger LOG_CPH = LoggerFactory.getLogger(ClassPathHacker.class);
private ClassPathHacker() {}
public static void addFile(final String pFileName) throws IOException {
final File myFile = new File(pFileName);
ClassPathHacker.addFile(myFile);
}
public static void addFile(final File pFile) throws IOException {
ClassPathHacker.addURL(pFile.toURI().toURL());
}
public static void addURL(final URL pFileUrl) throws IOException {
/* variables definition */
final URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
final Class<?> sysClass = URLClassLoader.class;
try {
final Method myMethod = sysClass.getDeclaredMethod("addURL", PARAMS);
myMethod.setAccessible(true);
myMethod.invoke(sysLoader, new Object[] { pFileUrl });
} catch (final Exception exc) {
ClassPathHacker.LOG_CPH.error(exc.getLocalizedMessage(), exc);
throw new IOException(exc.getLocalizedMessage());
}
}
}
Together with this method:
private static void hackClassPath(final File myData) {
if (myData.isDirectory()) {
/* block variables */
final File[] myList = myData.listFiles();
/* hacking classpath... */
for (final File tmp : myList) {
try {
ClassPathHacker.addFile(tmp.getAbsolutePath());
MainApplication.MAIN_LOG.trace("{} added to classpath",
tmp.getAbsolutePath());
} catch (final IOException iOE) {
MainApplication.MAIN_LOG.error(iOE.getLocalizedMessage(),
iOE);
}
}
}
}
And with this sample call:
MainApplication.hackClassPath(new File("test/data"));
MainApplication.hackClassPath(new File("data"));
A bit hacky, but maybe it works... it runtime adds all JAr files available in the data or test/data directory to the running classpath.

- 142
- 1
- 10