pf4j-spring icon indicating copy to clipboard operation
pf4j-spring copied to clipboard

Info/Demo needed : @Controller / @Service integration

Open Julieng50 opened this issue 7 years ago • 16 comments

Does anyone found a proper way to include @Component (@Controller / @Service) in a plugin ?

Julieng50 avatar Dec 18 '17 21:12 Julieng50

Maybe below links can help you:

  • HelloPlugin
  • https://github.com/decebals/pf4j/issues/126#issuecomment-281388628

decebals avatar Dec 18 '17 21:12 decebals

I already tried that, but my class annotated @Controller is not working. This is not very clear on how to implement Component with PF4J, in particular for @Controller (with @RequestMapping).

If someone got a working project to show us how you did that, maybe we could do a easier way to use PF4J with Spring.

Julieng50 avatar Dec 19 '17 12:12 Julieng50

The idea is that PF4J loads each plugin with different Java class loader. So, it's important to know in what Spring (application) context your controller is defined. Is defined in the plugin's application context or in the big application context?

decebals avatar Dec 19 '17 14:12 decebals

I have controller in both, but the one that does not work is in the plugin, so defined in with de plugin's application context. The thing that I'm trying to do : make my big application loads dynamically Controllers (from plugins).

Julieng50 avatar Dec 19 '17 15:12 Julieng50

Spring comes with an hierarchically application context concept. In your case, the beans registered via plugin's application context is not visible in the big application context and vice versa. In my example with HelloPlugin, I set the big application context as parent for the plugin application context. In this mode I have access from plugin to the beans defined in the big application context. The pf4j-spring library exports extensions as beans. After this, you can use autowire to inject extensions in a spring aware class (see https://github.com/decebals/pf4j-spring/blob/scope/demo/app/src/main/java/org/pf4j/demo/Greetings.java#L30). I don't know what can I say about your use case.

decebals avatar Dec 19 '17 19:12 decebals

Ok, I finally find a way to do that : In API :

public interface GenericController extends ExtensionPoint {
}

In Plugin :

@Extension
@RestController
public class PluginController implements GenericController {

    @GetMapping("/abc")
    public Object home() {
        return "OK";
    }

}

No need to add applicationContext.register(PluginController.class); in the createApplicationContext() in the plugin.

If someone find a way to do it wihtout @Extension... :)

Edit : I wrote this before your reply, I understand now that Extensions are injected in spring beans and using "register" does not work as I expected, thanks :)

Julieng50 avatar Dec 19 '17 20:12 Julieng50

I have the same requirements

fhchina avatar Jan 23 '18 02:01 fhchina

A good introduction to the problem (Spring and modularity) you can find in A Modular Architecture with Spring Boot. In that article you can read about hierarchical application context and that a child context can access bean from the parent context but not vice versa. You can see the @Exported annotation from that article like something similar with @Extension annotation from PF4J (both annotations register an object as singleton bean in the parent context).

The solution of @Julieng50 with @Extension on the controller class seems to be good and natural for me. In the end your controller implementation is an extension of controller extension point. Maybe @Julieng50 can show us a functional demo application that integrate Spring (MVC or Boot) and PF4J.

decebals avatar Jan 23 '18 09:01 decebals

In the end if you don't use the extension mechanism from PF4J, what are you using from PF4J, only the plugin mechanism (load and start plugins)? I think that would be possible in the future to use the @Controller, @Service, @Component annotations from Spring, with PF4J-Spring without to use the @Extension annotation from PF4J.

I wish to write below some theoretical aspects related to this subject. In Spring we can have hierarchical application context, you can visualize these contexts as nodes in a tree (a hierarchy), a node (application context) could have one parent, siblings and children. In PF4J each plugin contain other plugins as dependencies and also it can be a dependency for other plugins. You can visualize these plugins as node in a (directed) graph. I think in the end that it's possible to traverse the dependencies graph from PF4J (it's available), and to create a Spring hierarchical application context for each Spring plugin (node) from the graph. We can add the application context of dependency plugin as parent context and the application context of dependent plugin (other plugins that depends on our plugin) as children context. It's a problem here that in Spring hierarchical application context we cannot have multiple parents.

Example: P1 -> P2 -> P3 (plugin P1 is a dependency for P2 and P2 is a dependency for P3). Each plugins is a Spring plugin (it comes with an application context). When we instantiate P3 we can specify that it application context has as parent the application context of P2, in this mode, all beans defined in P2 are available for P3 (but not vice versa).

decebals avatar Jan 23 '18 10:01 decebals

@Julieng50 Can you share the source code of your plugin and Spring application or atleast the main class?

laurentkvb avatar May 04 '18 09:05 laurentkvb

Hi,

yes, it would be cool if @Julieng50 shared the project (or a working sample). I am using that approach and the constructor of my RestController is being executed, but then when I type the URL in the browser I get a 404 error, so I guess I'm missing something :-D.

Anybody else is having the same issue?

llatasa avatar May 13 '18 22:05 llatasa

Can we close this issue?

decebals avatar Jul 20 '18 10:07 decebals

I haven't been able to get it working. I used @Julieng50 comment but I always get a 404 error.

I would like to use the framework in my projects and use the new version is l of spring boot, but it is not easy to get a project with a data source in the main context, rest controllers in the plugins and so on.

Do you plan to publish a whole example?

Regards :-)

llatasa avatar Jul 20 '18 10:07 llatasa

Maybe the same problem is encountered in https://github.com/pf4j/pf4j-spring/issues/18. I see people that use PF4J with Spring (Boot) but I don't know why people using these two projects not share knowledge/projects . I don't use Spring in my projects, so I cannot help more in this field. Maybe someone with strong Spring knowledge will help us to move this module (pf4j-spring) forward. I hope 😄 .

decebals avatar Jul 20 '18 11:07 decebals

Hi, I am able to share some of the used source code to make the controllers work in Spring Boot. I'll get back at it. Maybe it can be used as a new sub project of the PF4J especially for Spring Boot.

laurentkvb avatar Jul 28 '18 22:07 laurentkvb

EDIT: moved to #27

An example how to use @Entity annotated (JPA/Hibernate) POJO classes in a plugin while the main app is a spring boot application (auto configuration; see JpaBaseConfiguration#getPackagesToScan() would be nice, too.

Cause as my plugin has different package names and another class loader they won't be picked up by getPackagesToScan I guess you need to create your own LocalContainerEntityManagerFactoryBean bean to call setPackagesToScan yourself. But how to pick up all the plugin packages from pluginManager bean?

dtrunk90 avatar Jan 02 '19 23:01 dtrunk90