Modularization without OSGI in Web project

2

I have a project that will be reasonably large, so it would be very interesting to modularize, I know, there is OSGi, but I found it very complex and I had difficulty adapting my application, the impression I had is that it will complicate more than facilitating the maintenance, is too much cage simply to use a class that is in a separate jar through an interface, so I am thinking of doing through ClassLoader, the framework I think is the following

Core Project

package core;

public interface IModulo {
<T> T getString();
}

Sample Module Project

package modulo1;

import core.IModulo;

public class Teste implements IModulo{

public <T> T getString() {
    return (T) "Hello";
}
}

Main project, where the modules will be "installed", this main project already has the Core project as dependency, ie the IModulo interface is already in the classpath, if I run through a simple main class, it works, but at least Tomcat does not, see the code snippet

  import core.IModulo;
   public class Main {
public static void main(String[] args) {

    try {
        String jarDoModulo = "C:\modulo1.jar";
        File file = new File(jarDoModulo);
        URL url;
        url = file.toURL();

        URL[] urls = new URL[] { url };
        ClassLoader cl = new URLClassLoader(urls);          
        Class<IModulo> cls = (Class<IModulo>) cl.loadClass("modulo1.Teste");
        IModulo modulo1 = cls.newInstance();
        System.out.println(modulo1.getString());

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

}

The error that appears is

Caused by: java.lang.ClassNotFoundException: core.IModulo
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
... 60 more
    
asked by anonymous 09.08.2014 / 01:22

1 answer

1

So I understand your requirement is basically to separate implementations of certain core interfaces. These implementations stay in jar projects apart from your main web project.

The problem you ran into happens because Tomcat has its own hierarchy of class loaders .

As your code has been written, within Tomcat IModulo will be managed by a WebappClassLoader and the Teste class with its URLClassLoader (which has no instance of IModulo loaded, so throws an exception).

There are two recommended paths here:

  • Put modulo1.jar in the WEB-INF/lib folder of your main project. That way your module classes will be available to the application and you will not have to mess with class loaders . Modularity is still maintained in the sense of being able to switch module implementation without changing the core application.

  • Use or write a% custom% (if you really want to leave your module in a non-standard place). Until Tomcat 7 you could use a VirtualWebappLoader for make your module jar available; from Tomcat 8 you can use the PreResources feature.

  • 09.08.2014 / 17:13