# pf4j-spring
**Repository Path**: sunflower-git/pf4j-spring
## Basic Information
- **Project Name**: pf4j-spring
- **Description**: Plugin Framework for Spring (PF4J - Spring Framework integration)
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 2
- **Created**: 2019-01-15
- **Last Updated**: 2021-06-03
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
PF4J - Spring Framework integration
=====================
[](https://travis-ci.org/pf4j/pf4j-spring)
[](http://search.maven.org/#search|ga|1|pf4j-spring)
This project is a proof of concept related to how you can integrate [PF4J](https://github.com/pf4j/pf4j) with Spring Framework.
Components
-------------------
- **ExtensionsInjector** allows PF4J's extensions to be expose as Spring beans.
- **SpringPlugin** your plugin extends this class if your plugin contains Spring beans
- **SpringExtensionFactory** use this ExtensionFactory in your PluginManager if you have SpringPlugins
- **SpringPluginManager** a Spring aware PluginManager
Using Maven
-------------------
In your pom.xml you must define the dependencies to PF4J-Spring artifact with:
```xml
org.pf4j
pf4j-spring
${pf4j-spring.version}
```
where ${pf4j-spring.version} is the last pf4j-spring version.
You may want to check for the latest released version using [Maven Search](http://search.maven.org/#search%7Cga%7C1%7Cpf4j-spring)
Also you can use the latest SNAPSHOT via the Sonatype Maven Repository. For this, you must add above lines in your `pom.xml`:
```xml
sonatype-nexus-snapshots
https://oss.sonatype.org/content/repositories/snapshots
false
true
```
How to use
-------------------
Create the Spring configuration (declare some beans) using annotations with:
```java
@Configuration
public class SpringConfiguration {
@Bean
public SpringPluginManager pluginManager() {
return new SpringPluginManager();
}
@Bean
@DependsOn("pluginManager")
public Greetings greetings() {
return new Greetings();
}
}
```
`SpringExtensionFactory` creates a new extension instance every time a request is done.
If you want a singleton extension instance please use `SingletonSpringExtensionFactory` that always returns a specific instance. Optional you can specify the extension classes for which you want singletons.
Start your application (plain java code):
```java
public class Boot {
public static void main(String[] args) {
// retrieves the Spring application context
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
// retrieves automatically the extensions for the Greeting.class extension point
Greetings greetings = applicationContext.getBean(Greetings.class);
greetings.printGreetings();
// stop plugins
PluginManager pluginManager = applicationContext.getBean(PluginManager.class);
/*
// retrieves manually the extensions for the Greeting.class extension point
List greetings = pluginManager.getExtensions(Greeting.class);
System.out.println("greetings.size() = " + greetings.size());
*/
pluginManager.stopPlugins();
}
}
```
Consume the PF4J extensions as Spring beans:
```java
public class Greetings {
@Autowired
private List greetings;
public void printGreetings() {
System.out.println(String.format("Found %d extensions for extension point '%s'", greetings.size(), Greeting.class.getName()));
for (Greeting greeting : greetings) {
System.out.println(">>> " + greeting.getGreeting());
}
}
}
```
The output is:
```
Found 2 extensions for extension point 'org.pf4j.demo.api.Greeting'
>>> Welcome
>>> Hello
```
Bellow I present you a more complex example where a plugin (see demo plugin2 - HelloPlugin) uses Spring Framework internally.
First, create an interface `MessageProvider` with an implementation class `HelloMessageProvider`
```java
public interface MessageProvider {
String getMessage();
}
public class HelloMessageProvider implements MessageProvider {
@Override
public String getMessage() {
return "Hello";
}
}
```
Declare the plugin's beans via Spring Configuration
```java
@Configuration
public class SpringConfiguration {
@Bean
public MessageProvider messageProvider() {
return new HelloMessageProvider();
}
}
```
Create my (Spring) plugin
```java
public class HelloPlugin extends SpringPlugin {
public HelloPlugin(PluginWrapper wrapper) {
super(wrapper);
}
@Override
public void start() {
System.out.println("HelloPlugin.start()");
}
@Override
public void stop() {
System.out.println("HelloPlugin.stop()");
super.stop(); // to close applicationContext
}
@Override
protected ApplicationContext createApplicationContext() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.setClassLoader(getWrapper().getPluginClassLoader());
applicationContext.register(SpringConfiguration.class);
applicationContext.refresh();
return applicationContext;
}
@Extension
public static class HelloGreeting implements Greeting {
@Autowired
private MessageProvider messageProvider;
@Override
public String getGreeting() {
// return "Hello";
// complicate a little bit the code
return messageProvider.getMessage();
}
}
}
```
Ready, your extension is available in your application via `PluginManager` or `Spring Autowire`.
For more details please see the demo application.
Implementation details
-------------------
__ExtensionsInjector__ injects each PF4J's extension as a bean in Spring Framework. For example if you run the demo application
you will see these lines in log:
```
2014-06-16 16:40:36,573 DEBUG org.pf4j.spring.ExtensionsInjector - Registering extensions of the plugin 'welcome-plugin' as beans
2014-06-16 16:40:36,586 DEBUG org.pf4j.spring.ExtensionsInjector - Register extension 'org.pf4j.demo.welcome.WelcomePlugin$WelcomeGreeting' as bean
2014-06-16 16:40:36,589 DEBUG org.pf4j.spring.ExtensionsInjector - Registering extensions of the plugin 'hello-plugin' as beans
2014-06-16 16:40:36,589 DEBUG org.pf4j.spring.ExtensionsInjector - Register extension 'org.pf4j.demo.hello.HelloPlugin$HelloGreeting' as bean
```
The bean name is the extension class name (for example 'org.pf4j.demo.welcome.WelcomePlugin$WelcomeGreeting').
For more information please see the demo sources.
Demo
-------------------
I have a tiny demo application. The demo application is in demo package.
Run the pf4j-spring demo (Boot class contains the main method) from IDE (IntelliJ in my case) with these arguments as VM options:
```
-Dpf4j.mode=development
```
and working directory:
```
pf4j-spring/demo/app
```