Project status

100 views
Skip to first unread message

Decebal Suiu

unread,
Oct 19, 2018, 2:00:03 PM10/19/18
to pf4j
Hi,

In the last period of time, the PF4J project entered in a kind of maintenance period because:
- no real issues (only enhanced proposals in https://github.com/pf4j/pf4j/issues)
- no entries in https://github.com/pf4j/pf4j/issues/182 (What you want to see in next version(s)?)

My philosophy related to PF4J (and in general) is to add only real features, features that are used day by day. I don't want to inject in this project features that are cool only.
I prefer to review, test and improve parts from project that are not clear or that are not performing well.

Of course, now, I am only the initiator of this project and one of committers, PF4J is not anymore a personal project so I present you only my opinion.

Any idea, contribution about future of this project is very welcome.

Thanks!

dmitry.t...@gmail.com

unread,
Feb 20, 2019, 6:35:21 AM2/20/19
to pf4j
Hi Decebal,

Thank you for the library and good supportive documentation, it is very helpful to get started! I am a totally new PF4J user, currently evaluating if it will work in our application. I've built a couple of prototypes with the help of your library and would like to share some feedback from a new user perspective that might hopefully be useful to determine 3.0 scope. Below is the list of suggestions that we would be happy to see in future library implementations:

1. It would be wonderful if PluginManager methods threw exceptions in case they cannot complete successfully. Error messages with explanations of the cause would also help. For example, PluginManager#loadPlugin may return null, requiring the clients to handle that with no extra information on why the plugin manager failed to load the plugin. I must add, though, that the logs are very nice and do provide that information. However, if more events happen before the problem manifests in the application, the user will have to search the logs for the cause.
The other issue where an exception would be preferable is described below.

2. Support loading of multiple versions of the same plugin. PF4J does not seem to place any restrictions on the type and the number of extensions in a plugin, and also has a notion of dependencies between plugins. Therefore, some users might want to load and run several versions of the same plugin.
Currently, if one tries to load two plugins "foo" of versions 1.0 and 2.1, the PluginManager will load both with no exception but it will not allow to start/stop/unload both, because the operations accept only pluginId "foo". Here are the logs of such failed attempt: https://github.com/DENMROOT/dynamic-services/pull/1#issue-251949832

3. Support loading of plugins coming from different vendors. The applications do not often control which names (pluginIds) plugins can have, and plugins might come from unrelated vendors. Thus, it seems sensible to allow to load plugins "foo" coming from "com.acme" and "com.example" at the same time. An IDE user that wants to load "code-stats" plugins from two different providers is an example where such feature is useful.

4. As a generalization/enabler of (2) and (3), it may be sensible to use a trio of "groupId:pluginId:version" to identify a plugin at runtime (not necessarily as a String, it might be a PluginId class).

5. Documentation — it would be awesome to keep the information related only to present capabilities of the library and push the information about previous versions to changelogs/migration guides.

Luckily for us, none of these issues proved to be blockers for our project. Meanwhile, I believe, the above-mentioned features will improve the quality of UX and make the library more attractive for other users as well.

I hope that this feedback could be of use to your team in improving and promoting your product and wish you good luck in moving it forward.

Cheers,
Dmitry

Decebal Suiu

unread,
Feb 20, 2019, 1:38:06 PM2/20/19
to dmitry.t...@gmail.com, pf4j
Thank you very much for your feedback. Your feedback is valuable. I will analyze it in detail and I will come back with a complete response.

--
You received this message because you are subscribed to the Google Groups "pf4j" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pf4j+uns...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Decebal Suiu

unread,
Feb 21, 2019, 3:48:14 PM2/21/19
to dmitry.t...@gmail.com, pf4j
Hi Dmitry,

I think that now I am able to respond you. I will respond you inline for each question.

On Wed, Feb 20, 2019 at 1:35 PM <dmitry.t...@gmail.com> wrote:
Hi Decebal,

Thank you for the library and good supportive documentation, it is very helpful to get started! I am a totally new PF4J user, currently evaluating if it will work in our application. I've built a couple of prototypes with the help of your library and would like to share some feedback from a new user perspective that might hopefully be useful to determine 3.0 scope. Below is the list of suggestions that we would be happy to see in future library implementations:

    1. It would be wonderful if PluginManager methods threw exceptions in case they cannot complete successfully. Error messages with explanations of the cause would also help. For example, PluginManager#loadPlugin may return null, requiring the clients to handle that with no extra information on why the plugin manager failed to load the plugin. I must add, though, that the logs are very nice and do provide that information. However, if more events happen before the problem manifests in the application, the user will have to search the logs for the cause.
The other issue where an exception would be preferable is described below.

Probably some PluginManager methods could threw exceptions. But the question is what methods.
You gave as example PluginManager#loadPlugin. The implementation of this method catch PluginException, log this exception and return null. See [1] for code.
We can easy add "throws PluginException" in signature of PluginManager#loadPlugin but the question is what do you want to do with this exception? The typical use case in my mind to deal with this exception is to display the exception's message in UI. It's clear that you cannot recover from this error.
But they are other methods from PluginManager like loadPlugins and startPlugins were I think that is not OK to throw an exception if a plugin or more cannot be loaded or started.
Maybe it's a good idea to make a list of all the methods we intend to throw an exception to and to discuss on this list.
Other discussion is what kind of exception we prefer: checked or unchecked (runtime)  exception. Is it a good to create a PluginRuntimeException? For example PluginManager#loadPlugin will throw PluginException or PluginRuntimeException?

 
    2. Support loading of multiple versions of the same plugin. PF4J does not seem to place any restrictions on the type and the number of extensions in a plugin, and also has a notion of dependencies between plugins. Therefore, some users might want to load and run several versions of the same plugin.
Currently, if one tries to load two plugins "foo" of versions 1.0 and 2.1, the PluginManager will load both with no exception but it will not allow to start/stop/unload both, because the operations accept only pluginId "foo". Here are the logs of such failed attempt: https://github.com/DENMROOT/dynamic-services/pull/1#issue-251949832.


    3. Support loading of plugins coming from different vendors. The applications do not often control which names (pluginIds) plugins can have, and plugins might come from unrelated vendors. Thus, it seems sensible to allow to load plugins "foo" coming from "com.acme" and "com.example" at the same time. An IDE user that wants to load "code-stats" plugins from two different providers is an example where such feature is useful.

    4. As a generalization/enabler of (2) and (3), it may be sensible to use a trio of "groupId:pluginId:version" to identify a plugin at runtime (not necessarily as a String, it might be a PluginId class).

Here a convention outside of PF4J is better than a configuration.
For example, in my projects where I use PF4J, I declare in the plugin's pom.xml (I use Maven) file the plugin descriptor attributes using maven properties.
Something like:

 <properties>
    <plugin.id>${project.artifactId}</plugin.id>
    <plugin.version>${project.version}</plugin.version>
    <plugin.provider>${project.groupId}</plugin.provider>
    <plugin.class>com.acme.MyPlugin</plugin.class>
</properties>

I think that you can extract majority of the plugin's properties (plugin.id, plugin.version, plugin.propvider) in a master pom.xml, the root of all your plugins if you follow the directory layout used by me in demo project.

Using this approach you can customize very easy the plugin.id for your application, as example with something like "${project.groupId}:${project.artifactId}:${project.version}".
Related to multiple plugins with same id/name ("code-stats" in your example) from different providers, I think that is a very bad idea to duplicate the id/name of plugin and this practice must be discouraged. It's about branding and identity, I don't want to use name PF4J for my project if I know that a project with this name already exists.


    5. Documentation — it would be awesome to keep the information related only to present capabilities of the library and push the information about previous versions to changelogs/migration guides.

Did you encountered this situation in the current documentation available at pf4j.org?
 

Luckily for us, none of these issues proved to be blockers for our project. Meanwhile, I believe, the above-mentioned features will improve the quality of UX and make the library more attractive for other users as well.

I hope that this feedback could be of use to your team in improving and promoting your product and wish you good luck in moving it forward.

I hope that we, the community, can improve this project for the benefit of all.
 
Thank you again for your feedback. Any idea, advice, criticism in a constructive form is very welcome :)

Best regards,
Decebal

dmytro....@bitfury.com

unread,
Feb 25, 2019, 2:18:13 PM2/25/19
to pf4j
Hi Decebal,

Thank you very much for your detailed explanations! My responses are inline:

On Thursday, 21 February 2019 22:48:14 UTC+2, Decebal Suiu wrote:
> Hi Dmitry,
>
>
> I think that now I am able to respond you. I will respond you inline for each question.
>
>
> On Wed, Feb 20, 2019 at 1:35 PM <dmitry.t...@gmail.com> wrote:
> Hi Decebal,
>
>
>
> Thank you for the library and good supportive documentation, it is very helpful to get started! I am a totally new PF4J user, currently evaluating if it will work in our application. I've built a couple of prototypes with the help of your library and would like to share some feedback from a new user perspective that might hopefully be useful to determine 3.0 scope. Below is the list of suggestions that we would be happy to see in future library implementations:
>
>
>
>     1. It would be wonderful if PluginManager methods threw exceptions in case they cannot complete successfully. Error messages with explanations of the cause would also help. For example, PluginManager#loadPlugin may return null, requiring the clients to handle that with no extra information on why the plugin manager failed to load the plugin. I must add, though, that the logs are very nice and do provide that information. However, if more events happen before the problem manifests in the application, the user will have to search the logs for the cause.
>
> The other issue where an exception would be preferable is described below.
>
>
>
> Probably some PluginManager methods could threw exceptions. But the question is what methods.
> You gave as example PluginManager#loadPlugin. The implementation of this method catch PluginException, log this exception and return null. See [1] for code.
> We can easy add "throws PluginException" in signature of PluginManager#loadPlugin but the question is what do you want to do with this exception? The typical use case in my mind to deal with this exception is to display the exception's message in UI. It's clear that you cannot recover from this error.
>
> But they are other methods from PluginManager like loadPlugins and startPlugins were I think that is not OK to throw an exception if a plugin or more cannot be loaded or started.
> Maybe it's a good idea to make a list of all the methods we intend to throw an exception to and to discuss on this list.
>
> Other discussion is what kind of exception we prefer: checked or unchecked (runtime)  exception. Is it a good to create a PluginRuntimeException? For example PluginManager#loadPlugin will throw PluginException or PluginRuntimeException?
>


I referred to PluginManager#loadPlugin because that's the one I bumped into :) It is specified to return `null` and the clients have to handle that to prevent NPEs. Consider the following example code:

void bootstrapApp() {
// …
// Load plugins
var pluginManager = new PluginManager();

List<Path> pluginPaths = …;

var loadedPluginIds = new ArrayList<String>();

for (Path pluginLocation : pluginPaths) {
var pluginId = pluginManager.loadPlugin(pluginLocation);
// Unless the client does check for `null`, this code will hide a potentional error
loadedPluginIds.add(pluginId);
}

// …
// There might be some operations between loading and starting,
// delaying the moment when the problem manifests

// Start plugins
for (String pluginId : loadedPluginIds) {
// It seems an IllegalArgumentException will occur when null is passed,
// but it won't contain information about which plugin failed to load.
pluginManager.startPlugin(pluginId);
}

// …
}

There might be some other methods that might benefit from early error reporting, but I haven't used them yet. Probably more experienced in/with PF4J developers could advise.

Regarding checked/unchecked, I don't have a strong opinion here, because I don't know all the possible errors that might occur. I agree that showing an error message in UI is one of the seemingly common ways to handle that. Also, if there are some 'required' for the system plugins then propagating an exception might be sensible.

>
>  
>     2. Support loading of multiple versions of the same plugin. PF4J does not seem to place any restrictions on the type and the number of extensions in a plugin, and also has a notion of dependencies between plugins. Therefore, some users might want to load and run several versions of the same plugin.
>
> Currently, if one tries to load two plugins "foo" of versions 1.0 and 2.1, the PluginManager will load both with no exception but it will not allow to start/stop/unload both, because the operations accept only pluginId "foo". Here are the logs of such failed attempt: https://github.com/DENMROOT/dynamic-services/pull/1#issue-251949832.
>
>
>
>     3. Support loading of plugins coming from different vendors. The applications do not often control which names (pluginIds) plugins can have, and plugins might come from unrelated vendors. Thus, it seems sensible to allow to load plugins "foo" coming from "com.acme" and "com.example" at the same time. An IDE user that wants to load "code-stats" plugins from two different providers is an example where such feature is useful.
>
>
>
>     4. As a generalization/enabler of (2) and (3), it may be sensible to use a trio of "groupId:pluginId:version" to identify a plugin at runtime (not necessarily as a String, it might be a PluginId class).
>
>
>
> Here a convention outside of PF4J is better than a configuration.
> For example, in my projects where I use PF4J, I declare in the plugin's pom.xml (I use Maven) file the plugin descriptor attributes using maven properties.
> Something like:
>
>
>  <properties>
>     <plugin.id>${project.artifactId}</plugin.id>
>
>     <plugin.version>${project.version}</plugin.version>
>     <plugin.provider>${project.groupId}</plugin.provider>
>     <plugin.class>com.acme.MyPlugin</plugin.class>
> </properties>
>
>
> I think that you can extract majority of the plugin's properties (plugin.id, plugin.version, plugin.propvider) in a master pom.xml, the root of all your plugins if you follow the directory layout used by me in demo project.
>
>
> Using this approach you can customize very easy the plugin.id for your application, as example with something like "${project.groupId}:${project.artifactId}:${project.version}".
> Related to multiple plugins with same id/name ("code-stats" in your example) from different providers, I think that is a very bad idea to duplicate the id/name of plugin and this practice must be discouraged. It's about branding and identity, I don't want to use name PF4J for my project if I know that a project with this name already exists.
>
>

Thank you, that would definitely work! I might have missed such a solution because I thought of pluginId as of artifactId in Maven. In my application I'd consider putting such a configuration in a Maven archetype that generates plugin template projects so that all plugins use this format for pluginId just in case.

However, such solution requires the user decision to pick a certain format for pluginId to ensure that they can load plugins from different vendors or of different versions at the same time; it does not work out of the box with the recommended interpretation of this attribute (correct me if I am wrong, but in most examples pluginId is artifactId). Also such a feature might be discovered rather late, when there is an immediate need to load plugins that you do not control.

Do you think PF4J shall use in its APIs some identifier that includes all coordinates of a plugin (pluginId, pluginProvider, version) and thus works in any case with no user knowledge? Or shall the documentation just mention something like "pluginId is a unique identifier of a plugin. It may contain any (?) ASCII characters. If your application might need to load plugins of different versions or from different third-parties, consider including the pluginProvider and version in pluginId to avoid conflicts."


>
>
>     5. Documentation — it would be awesome to keep the information related only to present capabilities of the library and push the information about previous versions to changelogs/migration guides.
>
>
>
> Did you encountered this situation in the current documentation available at pf4j.org?


I think I've seen it several times, on the front page at least ("Starting with version 0.9 …"). I've submitted a PR with some fixes: https://github.com/pf4j/pf4j.github.io/pull/24


>  
>
>
> Luckily for us, none of these issues proved to be blockers for our project. Meanwhile, I believe, the above-mentioned features will improve the quality of UX and make the library more attractive for other users as well.
>
>
>
> I hope that this feedback could be of use to your team in improving and promoting your product and wish you good luck in moving it forward.
>
>
>
> I hope that we, the community, can improve this project for the benefit of all.
>  
> Thank you again for your feedback. Any idea, advice, criticism in a constructive form is very welcome :)
>
>
> Best regards,
> Decebal
>
>
> [1] - https://github.com/pf4j/pf4j/blob/febdb302e7ca816b933daa75b5b46eb8bec31058/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java#L175 

Decebal, thank you for your help!

Cheers,
Dmitry
Reply all
Reply to author
Forward
0 new messages