The entry point of the API is the ContainerManager
, it will enable
you to define what is the Shared
classloader and to create children:
try (final ContainerManager manager = new ContainerManager( (1)
ContainerManager.DependenciesResolutionConfiguration.builder() (2)
.resolver(new MvnDependencyListLocalRepositoryResolver("META-INF/talend/dependencies.list"))
.rootRepositoryLocation(new File(System.getProperty("user.home", ".m2/repository"))
.create(),
ContainerManager.ClassLoaderConfiguration.builder() (3)
.parent(getClass().getClassLoader())
.classesFilter(name -> true)
.parentClassesFilter(name -> true)
.create())) {
// create plugins
}
-
the
ContainerManager
is anAutoCloseable
so you can use it in a try/finally block if desired. NOTE: it is recommended to keep it running if you can reuse plugins to avoid to recreate classloaders and to mutualize them. This manager has two main configuration entries: how to resolve dependencies for plugins from the plugin file/location and how to configure the classloaders (what is the parent classloader, how to handle the parent first/last delegation etc…). -
the
DependenciesResolutionConfiguration
enables to pass a customResolver
which will be used to build the plugin classloaders. For now the library only providesMvnDependencyListLocalRepositoryResolver
which will read the output ofmvn dependencies:list
put in the plugin jar and will resolve from a local maven repository the dependencies. Note thatSNAPSHOT
are only resolved based on their name and not from metadata (only useful in development). To continue the comparison to a Servlet server, you can easily implement an unpacked war resolver if you want. -
the
ClassLoaderConfiguration
is configuring how the whole container/plugin pair will behave: what is the shared classloader?, which classes are loaded from the shared loader first (intended to be used for API which shouldn’t be loaded from the plugin loader), which classes are loaded from the parent classloader (useful to exclude to load a "common" library from the parent classloader for instance, can be neat for guava, commons-lang3 etc…).
Once you have a manager you can create plugins:
final Container plugin1 = manager.create( (1)
"plugin-id", (2)
new File("/plugin/myplugin1.jar")); (3)
-
to create a plugin
Container
just use thecreate
method of the manager -
you can give an explicit id to the plugin (or if you bypass it, the manager will use the jar name)
-
you specify the plugin root jar
To create the plugin container, the Resolver
will resolve the dependencies needed for the plugin, then the manager will
create the plugin classloader and register the plugin Container
.
It is common to need to do some actions when a plugin is registered/unregistered. For that purpose ContainerListener
can be used:
public class MyListener implements ContainerListener {
@Override
public void onCreate(final Container container) {
System.out.println("Container #" + container.getId() + " started.");
}
@Override
public void onClose(final Container container) {
System.out.println("Container #" + container.getId() + " stopped.");
}
}
They are registered on the manager directly:
final ContainerManager manager = getContainerManager();
final ContainerListener myListener = new MyListener();
manager.registerListener(myListener); (1)
// do something
manager.unregisterListener(myListener); (2)
-
registerListener
is used to add the listener from now on, it will not get any event for already created containers. -
you can remove a listener with
unregisterListener
at any time.