PF4J: Plugin Framework for Java. Plugin Systems for Backend

Transcript:

Let's address an elephant in the room. Backend development never ceases to amaze us. It's never what we think it is. For example, do you ever think that backend development is not only about service-oriented architecture, monoliths, or microservices, but can also be a system with plugins like your IDE?

About the Speaker and PF4J
Hi, my name is Pasha Finkelshteyn. I work as a developer advocate for BellSoft, and today we are diving into plugin systems for backend development. The tool we will be discussing is called PF4JPlugin Framework for Java. You might assume that a framework is something huge, like Spring Framework, but PF4J is actually very lightweight, only around 100kB.

What is a Plugin?
A plugin is a part of your application that can be developed by a third party. It doesn't matter whether the developer is within your organization or an external contributor. For example, imagine a web application that supports only Epub file uploads, but you want to allow others to add support for PDFs, Mobi, Markdown, etc. Instead of developing these features yourself, you create an extension point—a defined interface where custom code can be invoked.

Extension Points and Plugin Lifecycle
An extension point is simply an interface with specific methods, such as getPath(), that plugins must implement. But a plugin is more than just an extension point—it has a lifecycle: it loads, starts, runs, and shuts down. PF4J is built around three core concepts: extension points, plugins, and extensions.

PF4J and Spring
PF4J supports various technologies, including PF4J Spring, which allows integration with Spring application context. This means plugins can access and inject Spring beans. While PF4J itself is more suited for desktop applications, PF4J Spring makes it useful for web applications as well.

Code Example Overview
To demonstrate PF4J, I prepared a PF4J demo project containing:

  • A "commons" module, which defines an extension point interface called PhraseExtensionPoint.
  • Two plugins: "bye-plugin" and "hello-plugin", both implementing phraseOfTheDay(), returning "Bye!" and "Hello!" respectively.

Building and Packaging Plugins
Each plugin has a build.gradle.kts file specifying dependencies, including pf4j, annotation processing, and the "commons" module. The plugin metadata (e.g., Plugin-Id, Plugin-Version, Plugin-Provider) is stored in the manifest file. After building, plugins are packaged as JAR files and copied to a plugins directory.

Integrating Plugins in a Spring Application
The main Spring application includes:

  • PhraseController, which collects and returns phrases from all loaded plugins.
  • SpringPluginManager, which loads plugins and makes them Spring-aware.
  • The pluginManager ensures that all plugins are available before being accessed by the application.

Running the Application
Once the application starts, making a request to /phrase returns "Hello!" and "Bye!", proving that the plugins work as expected.

Conclusion
PF4J allows you to build flexible applications where you deploy only the necessary features while keeping a monolithic or modular codebase. Plugins can even include their own libraries and dependencies without breaking the main application. This makes it an excellent approach for scalable and customizable systems.

I hope you now have a basic understanding of PF4J. Feel free to ask any questions. See you next time!

Summary

PF4J (Plugin Framework for Java) is a lightweight framework that allows developers to create modular applications using plugins. It enables the integration of custom code into applications through extension points, with support for lifecycle management and Spring integration for dependency injection. PF4J is useful for both desktop and web applications, offering flexibility in scaling and extending functionality without altering the core system.

Social Media

Videos
card image
Oct 16, 2025
All 7 Java Garbage Collectors Explained

In this complete guide to Java garbage collection, you will learn how the JVM memory model works, understand the differences between the Serial, Parallel, G1, ZGC, Shenandoah, CMS, and Epsilon collectors, and determine which garbage collector is best suited for your application's performance — from single-threaded programs to massive terabyte-scale heaps.

Videos
card image
Oct 7, 2025
Master Java Profiling in 2025: Tools, Techniques, and Real-World Tips

In this complete guide to Java profiling, you will learn sampling and instrumentation techniques, compare the 7 best tools (JFR, VisualVM, Async Profiler, JProfiler, YourKit, Digma.ai, New Relic), and master how to detect memory leaks and analyze CPU usage.

Further watching

Videos
card image
Nov 6, 2025
Docker Container Image Security: 13 Best Practices

This video presents 13 practical recommendations for reducing your attack surface and detecting malicious activity more quickly. You’ll learn how to create simple, immutable, and deterministic images using multi-stage builds, distroless bases, and non-root users. We cover SBOM generation with Syft, provenance verification with Cosign, CVE scanning workflows, and secret management strategies. From choosing LTS base images like Alpaquita Linux to implementing host-level protections, these practices will help you confidently deliver secure containers. It’s ideal for Java developers, DevOps engineers, and architects building production-grade infrastructure.

Videos
card image
Oct 31, 2025
Vaadin Tutorial: From Spring Boot to Beautiful UI Fast

In this guide, I’ll show you how to build a fully functional Java application with authentication, data tables, filters, and a custom cyberpunk theme using Vaadin.

Videos
card image
Oct 23, 2025
Top 7 JavaFX Testing Mistakes You Need To Avoid!

Stop making these common JavaFX testing mistakes! No more random NullPointerExceptions or deadlocks — in this video, we’ll show you how to fix the 7 most frequent TestFX issues when testing JavaFX applications. Learn how to work with FX threads, integrate with Spring Boot, avoid event-queue race conditions, handle pixel-level test differences, set up headless continuous integration with Monocle, and properly separate business logic from UI tests.