The use of plugins

Plugin, van Gogh

We decided to outsource services to plugins. We can of course load normal JARS at startup, but plugins have some advantages. So the application of the node is always the same - we load all node-specific functions via plugins. This comes into play in containers at the latest when plugins are loaded via a shared volume. One image, many nodes, and the behavior of the nodes is controlled by a list in the configuration. It couldn't be simpler. Well, we still have a few ideas, wait and see!

The question remains, what makes a JAR a plugin?

The Manifest of the JAR

To make the interface known to the kernel, it must be included in an entry in the manifest of the JAR.

This example shows the file "build.gradle" of the plugin project NY_GateKeeperPlugIn. This file takes care of the creation of a JAR.

plugins {
    id 'java'
}

group = 'net.nyssr'
description = 'NY_GateKeeperPlugIn'
version = project.jarversion
sourceCompatibility = 8
targetCompatibility = 8

jar {
    manifest {
        attributes(["Manifest-Version": "1.0"])
        attributes(["Implementation-Vendor": "sillysky software labs, Hohenwestedt, Germany"])
        attributes(["Implementation-URL": "www.sillysky.net"])
        attributes(["Implementation-Version": version])
        attributes(["Implementation-Title": "nyssr Gatekeeper PlugIn"])
        attributes(['PlugIn-Class': 'de.sillysky.nyssr.module.CModuleGateKeeper'], 'nyssr.net')
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation "org.jetbrains:annotations:23.0.0"
    implementation 'com.io7m.xom:xom:' + version_xom
    implementation project(':NY_Kernel')

    implementation project(':NY_GateKeeperAPI')
    implementation project(':NY_NetworkAPI')
}
task copyJar(type: Copy) {
    from jar
    into "${dirRun}/${project.projectDistributionDir}"
}
copyJar.dependsOn jar

Thereby a file META.INF/MANIFEST.MF is created in the JAR:

Manifest-Version: 1.0
Implementation-Vendor: sillysky software labs, Hohenwestedt, Germany
Implementation-URL: www.sillysky.net
Implementation-Version: 1.0.0
Implementation-Title: nyssr Gatekeeper PlugIn

Name: nyssr.net
PlugIn-Class: de.sillysky.nyssr.module.CModuleGateKeeper

The important line for loading the plugin is the last line ("PlugIn-Class: ..."). There the kernel takes the name of the class it calls for initialization when loading the plugin.

The called class in turn calls the individual ServiceStarter of the plugin. The ServiceStarter classes initialize the various packages of the plugin, register services, etc.

Start of the plugin

The interface IPlugIn contains only one method.

void startPlugin(@NotNull URL aUrl,
                 @NotNull ClassLoader aClassLoader,
                 @NotNull IServiceRegistry aServiceRegistry) throws CException;

The implementation of the GateKeeper therefore looks like this:

public final class CModuleGateKeeper implements IPlugIn
{
    @Override
    public void startPlugin(@NotNull final URL aUrl,
                            @NotNull final ClassLoader aClassLoader,
                            @NotNull final IServiceRegistry aServiceRegistry)
    {
        CVersionHelper.printJarVersion(aUrl);
        aServiceRegistry.addStarter(new CPackageGatekeeperRecords());
        aServiceRegistry.addStarter(new CPackageNetworkGatekeeper());
        aServiceRegistry.addStarter(new CPackageImplNetworkGatekeeperTarget());
    }
}

You can see well that in the module initialization nothing else happens than a multiple package initialization. This structure runs through all plugins from sillysky . How your implementation will look like is unfortunately beyond our knowledge ;-)

nyssr.net - Innovative Distributed System