Extending applications with PF4J plugins
This repository provides a tutorial and an example on how to use PF4J to develop an application that supports extension through the development of third-party plugins.
User Stories:
Initially, we focus on the minimum amount of code to create a java applicaiton with plugin support.
Story 01 | Should be able to add functionality via plugin |
---|---|
As an | Application Developer |
I need to | support plugins in my applications |
So that | they can be extended by third-party collaborators |
Then, we extend the functionality to include container and plugins built with Spring boot
Story 02 | Should be able to use Spring boot in container and plugins |
---|---|
As an | Spring boot Developer |
I need to | support plugins written based on Spring |
So that | I can use Spring functionality such as dependency injection in my plugins |
Next, we add a new Restful endpoint using an annotated class
Story 03 | Should be able to add to Restful endpoints from plugin |
---|---|
As an | Spring boot Developer |
I need to | be able to add new endpoints via the plugin |
So that | provide access to the extended functionality via RESTful interfaces |
Finally, we add a reactive Restful endpoint using a Router Function
Story 04 | Should be able to add reactive endpoints from plugin |
---|---|
As an | Spring boot Developer |
I need to | be able to add reactive endpoints via the plugin |
So that | provide the benefits of reactive programing with my plugins |
Contents
Overview ………………….. Explains the reasons behind creation of this repository
Shared Interface…………. Allows plugins to interact with the container and eachother
Baremetal Plugin…………. Minimal java code that creates a functioning plugin
Baremetal Container……. Minimal java code that creates standalone plugin container
Spring boot Plugin………… A plugin that uses Spring boot for DI and adds endpoints created with annotated classes or router functions.
Spring boot Container…… A Spring boot app with plugin support and reactive Restful service
Overview
Plugins are pieces of software, developed by a third-party, that extend the functionality of a given application. There are many benefits to an application that supports plugins, such as flexibility to accommodate new requirements, extensibility to integrate in new environments, and suitability in being able to create tailored solutions by including only the functionality required for a specific use case.
There are multiple ways of adding plugin support to a Java application. The powerful, age-old and very complex OSGI network to the use of simple and limited-functionality mechanisms inherent in Java 8. One good mid-way compromise which is neither too simplistic nor too complicated is Pf4J, although by no means this is to claim that it is the only or even the best solution for the problem.
PF4J is a plugin framework for Java, that allows third party developers to extend the functionality of an application by adding a zip file to the plugins folder that will be loaded at runtime. Extensions can also be added to the application jar file if needed. the PF4J Github repository has an example of how to develop such an application, along with comprehensive documentation on the framework. While these should certainly be studied, in our experience understanding the examples was not easy for the average developers and we decided to contribure by creating this tutorial.
This project demonstrates the same concepts in a more practical way. Three separate maven projects are created, and a scenario is presented on how the solution will be created and deployed.
Actors
In the plugin management system, two main actors are at play. the application owner, who creates the application which accepts the plugin, and published the interfaces that the second actor, the plugin developer, implements to develop extended functionality.
Artifacts
The solution involves three components. the first component is in the form of a java interface, which is developed by the application owner and consists of a series of mehtods that plugin developer implements to extend the application. This component should be typically published in maven repository or some similar place and is added to the other two components as a dependency.
the second component is the container, which is also developed by the application owner. Once started, the plugin container scans the plugins folder and reads and unzips the plugins in that folder, loading the classes and starting and stopping the plugins.
the third component is the plugin itself. it is developed by the plugin developer and implements some of the shared interfaces defined in the first component and together with its own dependencies resides as a zip file in the plugins directory where the container will be looking for it.
The following table summarizes the above concepts
Artifact | Actor | Description |
---|---|---|
Container | Application Owner | the main application, scans a directory that contains plugins as zip files, decompresses and imports them into the application |
Shared Interfaces | Application Owner | the collection of interfaces that plugins implement. published by the application owner and included as a dependency by both the plugin-container and the plugin |
Plugin | Plugin Developer | the implementation of one or more interfaces defined in Shared-Plugin-Interfaces. deployed as a zip file of classes and their dependencies inside the plugins directory of the Plugin-Container |