Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading plugin as spring boot executable jar #48

Open
fabioformosa opened this issue Jun 5, 2020 · 7 comments
Open

Loading plugin as spring boot executable jar #48

fabioformosa opened this issue Jun 5, 2020 · 7 comments

Comments

@fabioformosa
Copy link

fabioformosa commented Jun 5, 2020

I've tested loading a plugin developed with spring boot.

Normally, a spring boot project (it could be the plugin) is built with spring-boot-maven-plugin that create a spring boot executable jar, that is a fat jar that contains classes + libs.

The structure of a spring boot executable jar is different than a standard jar, look at this doc page: https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-executable-jar-format.html#executable-jar-jar-file-structure

So plugin classes (and extension.idx) are placed, into the jar, at this folder: BOOT-INF/classes.
Is there a way for pf4j to search classes not in the root of jar but in a subfolder of it?

@decebals
Copy link
Member

decebals commented Jun 6, 2020

Is there a way for pf4j to search classes not in the root of jar but in a subfolder of it?

Sure.
Take a look at PluginClasspath and its implementations like DevelopmentPluginClasspath.

@fabioformosa
Copy link
Author

fabioformosa commented Jun 10, 2020

Thank you for your answer.
Why doesn't JarPluginLoader use PluginClasspath? It seems the way to load class from a jar that hasn't the standard structure, for example like the spring-executable-jar.

@decebals
Copy link
Member

decebals commented Jun 11, 2020

Why doesn't JarPluginLoader use PluginClasspath?

JarPluginLoader loads plugins in JAR format. The layout of a JAR file is standard. Sure, in the end I think that we can force the use of PluginClasspath also in JarPluginLoader but my feeling is that you use spring-executable-jar in a non natural way (maybe I am wrong).
I am not familiar with Spring Boot but my question is why do you need to use a spring-executable-jar instead of classic jar file for your plugins. In my opinion a spring-executable-jar has a clear semantic and a well defined scenario. Even the name says that it's executable (it contains a main class inside) which doesn't make sense when it comes to plugins
In the end, this spring-executable-jar is very similar with a standard ZIP file (almost the same layout) used by default by PF4J to represent a plugin. In the current version of PF4J, each plugin in ZIP format is extracted in a directory before it's loaded, but I think that it will be nice to have an option to not unpack the zip and use it as such. In this mode we can model a spring-executable-jar as a standard zip plugin file but with a custom file extension name.
When I see a file with extension .jar my expectation is that I have to deal with a standard layout.

@fabioformosa
Copy link
Author

In spring boot application, the natural way to build a jar is just the spring-executable-jar.
As you properly point out, it's a nonsense to have an executable file to load as a plugin. It's true, but spring boot is not only a way to run app standalone, by now it's also the standard way to develop using spring framework, because it semplifies the setup and reduces the boilerplate.
In my context, plugins won't developed by me, but by 3rd parties and a java plugin mechanics, nowadays, must necessarily support spring boot.
Ok, I could say to plugin developers: "you can develop through spring framework, but you should build a traditional jar". Ok, it's easy, because spring boot produces, at the end of the build phase, both jars: the spring-executable-jar and the classic jar, as well.
So, why do I insist on spring-executable-jar? Because spring-executable-jar is a fat jar that contains natively all libs. Whereas, pf4j requires a standard jar but enriched and assembled with all libs. I should ask to all 3rd parties to customize their build process in order to produce a pf4j compliant jar. Is it right?
I think pf4j should be compliant to the standard way to develop app in spring not viceversa, and in my view it means:

  1. to have a plugin loader for spring-executable-jar
  2. to instanciate all controllers, services and beans defined by plugin.

The JarPluginLoader could work as now (applying to all *.jar files), and using a special PluginClasspath if it recognizes the spring boot structure.

@decebals
Copy link
Member

decebals commented Jun 12, 2020

Of course, I don't want to convince you to not use spring-executable-jar.
By default (current implementation), PF4J doesn't come with support for a such type of jar but PF4J is very flexible and it allows you to configure every aspect.
So, the fast solution for you is to create a SpringBootPluginLoader that probably will extends JarPluginLoader, and to override the load method. After this you can inject this loader in PF4J.

Other variant is what I said in my previous comment:

In the end, this spring-executable-jar is very similar with a standard ZIP file (almost the same layout) used by default by PF4J to represent a plugin. In the current version of PF4J, each plugin in ZIP format is extracted in a directory before it's loaded, but I think that it will be nice to have an option to not unpack the zip and use it as such. In this mode we can model a spring-executable-jar as a standard zip plugin file but with a custom file extension name.

Any contribution (PR) is welcome.
If you have other concrete ideas, I'm ready to listen.

@shirishpandharikar
Copy link

I have personally used pf4j in some of my projects with Spring Boot. I think what @decebals is saying about plugins not being executable makes complete sense. A plugin at the end of the day is a contract implementation. So they you can actually lay down some guidelines for the plugin developers on how it should be packaged. That is exactly what we did in our projects. I understand that using a .jar file is more native to Java and no extraction is required, but like we already know the Spring Boot executable is a complex beast in itself.

@fabioformosa
Copy link
Author

fabioformosa commented Aug 28, 2020

I'm trying to understand what happens under the hood of the spring boot classloader. I agree with you, it's complex enough, but "we should try, not because it's easy but because it's hard" :)
I'll let you know when I have some news.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants