You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-[How to load plugins from jar files](#how-to-load-plugins-from-jar-files)
13
+
-[How to load plugins from ClassLoader](#how-to-load-plugins-from-classloader)
14
+
-[Working with custom plugins](#working-with-custom-plugins)
15
+
-[A word about error management](#a-word-about-error-management)
16
+
-[Advanced usage](#advanced-usage)
17
+
-[Plugin registry](#plugin-registry)
18
+
-[Download plugins from a repository](#download-plugins-from-a-repository)
19
+
20
+
## Introduction
9
21
A plugin is a class that is loaded dynamically by an application to give extra functionalities or customization.
10
22
11
23
From the technical point of view, the plugin should implement an interface (or extends a class) defined by the application.
12
24
Usually, the plugin can be stored in a jar file, but you can imagine loading it from the network.
13
25
14
26
This library helps application developper's to manage plugins in their application.
15
-
It provides an abstraction of the process of loading plugins and a concrete implementation to load plugins stored in jar files.
27
+
It provides an abstraction of the process of loading plugins and concrete implementations to load plugins stored in jar files.
28
+
Unlike [java.util.ServiceLoader](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html), it allows to customize error management and how plugin classes are discovered and instantiated.
16
29
17
30
The [plugin-loader-example](https://github.com/fathzer/plugin-loader/tree/main/plugin-loader-example) folder contains an example of jar plugin implementation and loading.
18
31
19
-
It requires java 8+
32
+
## Requirements
33
+
It requires java 11+.
34
+
Nevertheless, a variant of this library is available for Java 8 users. They have to use the 'jdk8' [maven classifier](https://www.baeldung.com/maven-artifact-classifiers#bd-3-consuming-jar-artifact-of-a-specific-java-version) in their dependency. Only the [com.fathzer.plugin.loader.utils.AbstractPluginDownloader class](#download-plugins-from-a-repository) is not available in this variant.
20
35
21
-
## How to use the plugin loader with jar files
36
+
## How to load plugins from jar files
22
37
23
38
### First define an interface for your plugin.
24
39
@@ -27,6 +42,7 @@ It's a good practice to define this interface in a library different from the ap
27
42
Here is the example:
28
43
29
44
```java
45
+
packagecom.myapp;
30
46
publicinterfaceAppPlugin {
31
47
StringgetGreeting();
32
48
}
@@ -47,30 +63,101 @@ public class MyPlugin implements AppPlugin {
47
63
```
48
64
49
65
You should package the class in a jar file.
50
-
As the plugin can be complex, the jar file can contains many classes. So, you have to define which class implements the plugin interface in a manifest attribute of the jar.
51
-
By default *Plugin-Class* attribute is used. See [pom.xml of plugin example](https://github.com/fathzer/plugin-loader/blob/main/plugin-loader-example/plugin-loader-example-plugin/pom.xml) to view how to do it with Maven.
66
+
As the plugin can be complex, the jar file can contains many classes. So, you have to define which class implements the plugin interface. The standard way is to add a resource file in META-INF/services. In this example, its path should be META-INF/services/com.myapp.AppPlugin and it should contain the canonical name of every plugin implementation classes (see [ServiceLoader documentation](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html) to have the exact format of the file).
52
67
53
68
### Finally load the plugin in your application
54
69
55
-
The **JarPluginLoader** ([Javadoc is here](https://javadoc.io/doc/com.fathzer/plugin-loader)) class allow you to load the plugins contained in a local folder.
70
+
com.fathzer.plugin.loader.jar.JarPluginLoader will allow you to get the plugin in your application.
56
71
57
-
Here is an example:
72
+
Here is an example that loads the plugins contained in the *pluginFile* local jar file:
An usual need is to load all plugins in a local directory.
80
+
*com.fathzer.loader.utils.FileUtils.getJarFiles* method allows you to search for jar files in a directory.
81
+
You have then to iterate over the returned files.
82
+
83
+
## How to load plugins from ClassLoader
84
+
JarPluginLoader is not the only way to load plugins. *com.fathzer.plugin.loader.PluginLoader* is an abstract class that can have multiple implementations.
85
+
Another classical implementation provided by this library is *ClassLoaderPluginLoader*.
86
+
It allows you to search and load plugins through a class loader.
87
+
88
+
A typical use is to load the plugins available on the classpath. Here is the code to do that:
The default implementation works with plugin defined as services useable with [ServiceLoader documentation](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html), but you can change how the plugins are discovered or how they are instantiated.
96
+
97
+
The plugin class names are discovered by a ClassNameBuilder. You can change the default one using the PluginLoader.withClassNameBuilder.
98
+
Here is an example that use a predefined class name:
You can also change the way plugins are instantiated using the PluginLoader.withInstanceBuilder method. For instance to use a constructor with argument.
105
+
Here is an example that uses a constructor with a fixed string argument:
If a problem occurs during plugin instantiation, a *PluginInstantiationException* is throw. This is the default behaviour, but you prefer to log the error and continue to instantiate other plugins contained in a jar.
121
+
You can simply customize the exception management using the *PluginLoader.withExceptionConsumer* method as in the following example:
122
+
```java
123
+
newClassLoaderPluginLoader().withExceptionConsumer(e -> log.warn("An error occurred while loading plugins", e));
124
+
```
125
+
126
+
## Advanced usage
127
+
An usual need is to have a bunch of plugins that are selected by a key. For instance, you can imagine an interface that do *something* with an URI. You can have multiple implementations of the interface, one for each supported uri scheme.
128
+
129
+
### Plugin registry
130
+
The *com.fathzer.loader.utils.PluginRegistry* maps String keys to plugin instantiations. You can register plugins, then retrieve them from their keys, , etc...
131
+
132
+
### Download plugins from a repository
133
+
**Warning: This section is not available for java8 version of this library**.
134
+
135
+
Once you have a plugin registry, a basic way to populate it is to read plugins from a local jar directory.
136
+
It's simple ... but how to update this local directory when a new plugin is released?
137
+
138
+
The *com.fathzer.plugin.loader.utils.AbtractPluginDownloader* class allows you to define your own plugin remote repository and download the required jar to a local folder.
139
+
You can then use JarPluginLoader to load these plugins.
140
+
141
+
A repository is basically a map between a key and an URI where to download a jar.
142
+
This map should be available at an URI. Let's say for instance *https://com.myApp/AppPluginRepository*.
143
+
The format of serialization format of the map is free. The AbtractPluginDownloader is abstract because you have to implement the parsing of the repository URI. For the example, let say the map is stored in json format:
144
+
```json
145
+
{
146
+
"https":"https://com.myApp/AppPlugins/http.jar",
147
+
"sftp":"https://com.myApp/AppPlugins/sftp.jar"
148
+
}
149
+
```
150
+
151
+
Here is an implementation that uses jackson to parse the map:
0 commit comments