User Tools

Site Tools


modules:intro

Modules is a simple module manager. The projects has to main goals: First, to reduce dependencies, I don't like it if simple and small apis have a lot of dependencies, so modules has zero dependencies. Second, it should be really easy to use.

Setup

To use modules you must add the provided maven repository to your build system. Artifacts Then you can simple add the module-manager dependency to your project.

compile group: 'com.thorstenmarx.modules', name: 'modules-manager', version: '0.21.0'

or, if you want to create a module.

provided group: 'com.thorstenmarx.modules', name: 'modules-api', version: '0.21.0'

Concept

Modules consists of four parts,

  • ModuleManager, is uses to load the modules and provides access to extensions
  • Module, a module is a provider for extensions
  • Extension, is an interface that describes a extension point
  • Service, for providing functionality between modules.

Make your application extendable

After you've decided to make you application extendable, is to define some extensions.

Define Extensions

In this example we create an abstract class as extension definition. It is also possible to use interfaces and extend ExtensionPoint instead of BaseExtension. But then you have to implement some more methods and in most cases the usage of BaseExtension is a good choice.

public abstract class TestExtension extends BaseExtension {
	public abstract String getName();
}

The extension is complete and should be in an extra jar, so that it can be used by modules. You can find this example in the repository under demo/test-api.

Implement the Extension

You just need to implement the abstract class and add the Extension annotation.

@Extension(TestExtension.class)
public class TestExtensionImpl extends TestExtension {
	public String getName() {
            return "Thorsten";
        }
}

See the test-module example in the repository for more information. The examples uses gradle with the helper script (https://bintray.com/artifact/download/thmarx/generic/gradle-modules/0.7.0/module-0.7.0.gradle). This script provides a task to generate the module.

ModuleManager

Now it's time to use the extensions.

List<String> apiPackages = new ArrayList<>();
apiPackages.add("com.thorstenmarx.modules.example.api");
// create module manager
ModuleManager manager = ModuleManager.create(new File("modules/"),new TestContext(), new ModuleAPIClassLoader(getClass().getClassLoader(), apiPackages));
// get all extensions for extension point
List<TestExtension> extensions = manager.extensions(TestExtension.class);
// or load only extensions of a single module
Module module = manager.module("module-id");
if (module.provides(TestExtension.class)) {
    extensions = module.extensions(TestExtension.class);
}

ModuleApiClassLoader is an custom classloader to hide the parent dependencies. You need to add you public api to the apiPackages list, to be able to access them in the module. The TestContext is a object that allows you to pass information or into your modules.

Advanced Usage

There are some topics that a for more advanced users, and might not interesting for most users.

Communication between Extensions

In some cases it would be necessary to communicate between modules or provide functionality to other modules. For this reason it is possible to create services that can be used by other modules. Another way to communicate between modules is the message bus. It allows you to send messages between modules and share information.

Providing functionality

Providing functionality to other modules is the first case we will look at. Imagine a module that provides a geo location service and a other modules should be possible to use this service. Simple create an api jar with the geo location service interface. The other module, which wants to use that service, must have the api as dependency. Another use case would be to make your module extendable. For example a report module could be extended to support more file formats.

Service provider

The provider of the implementation must register the implementation at the Services class

Services.register(GeoServiceInterface.class, new GeoServiceImpl());
Service consumer

The consumer of the service can get a single or all implementations.

// the single-method returns the first registered implementation via optional
GeoServiceInterface geoservice = Services.single(GeoServiceInterface.class).get();
// alternatively, get a list of all implementations
List<GeoServiceInterface> geoservice = Services.get(GeoServiceInterface.class);
modules/intro.txt · Last modified: 2017/11/06 09:54 (external edit)