sbp (Spring Boot Plugin)
repository·master·Indexed 43 days ago
https://github.com/hank-cp/sbpA plugin-oriented programming framework for Spring Boot inspired by Pf4j. It enables the transformation of monolithic Spring Boot applications into modular systems where plugins can be installed, updated, started, or stopped on the fly. Supports Spring Boot 3.x (sbp version 18+) and Spring Boot 2.x.
What's inside sbp
- sbp is a plugin-oriented design capability for Spring Boot, inspired by and built upon the Pf4j project. It allows developers to transform a monolithic Spring Boot application into a modular, plugin-based architecture. This provides a middle ground between a standard monolithic Spring Boot application and a distributed Spring Cloud architecture, enabling features like online installation, upgrading, starting, and stopping of plugins without the complexity of full microservices (e.g., service discovery, traffic control).
Key features and benefits of sbp
mastersbp provides a lightweight, spiral expansion architecture for Spring Boot applications with the following capabilities:
- Plugin Lifecycle Management: Supports online installation, upgrading, starting, and stopping of plugins.
- Full-Stack Spring Boot Integration: Plugins can leverage the entire Spring Boot ecosystem, including:
- Controllers (
@Controller,@RestController) RouterFunctionand WebFlux- Static resource loading and template engines (Freemarker, Velocity, Thymeleaf)
- Persistence middleware (Spring Data, JPA, jOOQ, MyBatis Plain SQL)
- Spring Security and AOP
- Controllers (
- Development Workflow: Allows developing, debugging, and testing plugins within an independent, executable Spring Boot project.
- Low Learning Curve: Requires only Spring Boot knowledge; no additional framework expertise is needed.
- Configuration: Uses NO XML.
Approach 2: Share a single DataSource with multiple persistence middlewares (JPA + JDBC)
masterYou can mix JPA (Hibernate) with other tools like Jooq or Mybatis on a single
DataSource, but it requires careful transaction management.Without JTA/XA
If you use
DataSourceTransactionManagerin the app andJpaTransactionManagerin the plugin, you can inject them into their respectiveapplicationContexts. However, transactions cannot be joined across different transaction managers, meaning you lose ACID guarantees across the app/plugin boundary.With JTA/XA (Recommended for mixed environments)
To achieve atomic transactions across different persistence layers (e.g., JPA in a plugin and JDBC in the app), you must:
- Set up different
XADataSourceinstances for JPA and other middlewares. - Inject a
JtaTransactionManagerinto every pluginapplicationContext. - Use
SharedJtaSpringBootstrapto start the plugin. - Ensure
AtomikosDataSourceBeanis closed when the plugin stops.
- Set up different
Extend SBP with a custom PluginLoader
masterBy default, SBP loads plugin resources from the file system or a single JAR file. To load plugins from other formats (e.g., a fat-jar), provide a custom implementation of thePluginLoaderinterface via thespring.sbp.custom-plugin-loaderproperty. Your custom loader must have a constructor that accepts aPluginManagerinstance.Maintain consistent framework stacks between app and plugins
masterTo avoid classloading issues, use the same framework stack (libraries and versions) in both the main application and the plugins as much as possible. Introducing libraries with complex dependencies (such as Spring Data JPA) exclusively in a plugin can cause problems because the plugin and the app use different classloaders, making it difficult to ensure all dependent classes are loaded by the same classloader.Approach 1: Share a single DataSource with the same persistence middleware
masterThis is the simplest and recommended way to handle persistence in sbp. You can share a single
DataSourcefrom the main application to its plugins using sbp bean management. This provides local transaction support.Supported Middlewares:
JdbcTemplateJooqMybatis
Note: JPA/Hibernate is not a suitable option for this specific approach because of how it manages internal state and
EntityManagers.See SharedDataSourceSpringBootstrap for implementation details.Implement unified security control using Spring Security
masterThe sbp framework allows you to extend security control from the main application down to individual plugins. This enables the entire application to run under a unified security policy.
Because security requirements vary by use case, sbp does not provide a one-size-fits-all security implementation. Instead, it provides the infrastructure to integrate your own Spring Security configuration. A reference implementation can be found in the
demo-securityproject.Avoid package name conflicts with core libraries
masterWhen naming your plugin packages, ensure they do not start withorg.pf4j,java, orjavax. ThePluginClassLoadertreats these prefixes differently, which can lead to unexpected behavior. Additionally, always ensure your application package and plugin packages have distinct names to prevent the Spring context building process from failing.How to integrate third-party frameworks using IPluginConfigurer
masterTo use Spring Boot frameworks or libraries (like JPA, Quartz, etc.) within a plugin environment, you must make them dynamically registerable/unregisterable. This is achieved by extending
IPluginConfigurer.Configurers are invoked during the plugin's
ApplicationContextbootstrap process, allowing you to register or unregister plugin resources within the mainApplicationContext.public class LibraryPlugin extends SpringBootPlugin { public LibraryPlugin(PluginWrapper wrapper) { super(wrapper, // SbpWebConfigurer is mandatory, so it will be config automatically. new SbpJpaConfigurer(new String[] {"demo.sbp.library.model"}), new SbpSpringDocConfigurer() ); } }Deployment principles for SBP plugins
masterWhen deploying a plugin for SBP, the packaging format depends on whether your plugin has 3rd-party dependencies:
- No 3rd-party dependencies: A normal JAR is sufficient. However, you must sign the JAR manifest with the required plugin attributes.
- With 3rd-party dependencies: The "Fat-jar" format (a JAR inside a JAR, such as a standard Spring Boot executable JAR) is not supported. You must use one of two workarounds:
- Flat lib jar: Extract all classes and resources from your dependency JARs and pack them into a single, flat JAR file alongside your plugin classes.
- Zip format: Use the PF4J zip format. Place all 3rd-party dependency JARs under a
/libdirectory and your plugin classes under a/classesdirectory, then package everything into a.zipfile.
How sbp bootstraps plugin ApplicationContexts
masterThe sbp project extends the standard
SpringApplicationvia a class calledSpringBootstrap. This allows the system to bootstrap a dedicated pluginApplicationContextalongside the main application context.Note on Classloading: While sbp is based on pf4j, it implements a custom rewritten classloading behavior that differs significantly from the original pf4j implementation.
Understand the demo project structure and modules
masterThe demo project is organized into several modules that demonstrate different
sbpcapabilities:Core Modules
demo-shared: Contains shared code used by both application and plugin projects.demo-security: Demonstrates how to introduce Spring Security and secure APIs via AOP.demo-apis: Contains classes that must be declared as APIs to be shared between apps and plugins, or between different plugins.demo-app: The master project and entry point. It contains the two Spring Boot applications (DemoAppandDemoSecurityApp) and the following plugins:demo-plugin-admin: Demonstrates Spring Security integration within a plugin and support for Spring Boot profiles.demo-plugin-author: Demonstrates sharing resources (e.g.,DataSource,TransactionManager) between APIs and plugins.demo-plugin-library: Demonstrates usage of Spring Data/JPA.demo-plugin-shelf: Demonstrates API exposure and invocation between different plugins.
Specialized Starters
demo-jpa: Demonstrates using Spring Data/JPA via thesbp-spring-boot-jpa-starter.demo-webflux: Demonstrates using Spring WebFlux via thesbp-spring-boot-webflux-starter.