The biggest thing in your scenario is to know that a WebAppContext *must* (according to the servlet spec) follow a set of very strict classloader hierarchy rules. You are constantly bumping your head into this low door frame without realizing it.
To simplify these rules (this is a gross oversimplification of the actual behavior).
Default java rules are to check the parent classloader first.
Default servlet rules are to check the webapps classloader first.
Server (implementation) classes are not to be exposed to webapp.
There are 2 approaches to resolving this.
- Tell the WebAppClassloader to always use the server side classloader of specific classes
webapp.addSystemClass("org.slf4j.");
webapp.addSystemClass("ch.qos.logback."); - Tell the WebAppClassloader to always search the server side classloader before the WebAppClassloader
webapp.setParentLoaderPriority(true);
Since you are an embedded user, you'll have to pick and choose what is most appropriate for you.
The addSystemClass() approach is best for maintaining this WebAppClassloader isolation but tweaking it slightly, especially useful if you have multiple WebApps in your environment that might have conflicting WEB-INF/lib contents.