Giter Club home page Giter Club logo

sbp's People

Contributors

batugane avatar dobrolubovajane avatar dtrouillet avatar hank-cp avatar j-barata avatar kenpb avatar l-dietrich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sbp's Issues

插件如何携带统一路径前缀

例如 我插件plugins-a 我想他的所有接口都是以/plugins-a开头 但是我并不想在每个controller里面都写/plugins-a/xxx/xxx

How to specify multiple plugin folders?

Eg

pf4j

The plugins are stored in a folder. You can specify the plugins folder in the constructor of DefaultPluginManager. If the plugins folder is not specified then the location is returned by System.getProperty("pf4j.pluginsDir", "plugins").

NOTE: The “pf4j.pluginsDir” property comes with comma-separated directory list support (support for multiple plugin root directories).

The structure of plugins folder is:

plugin1.zip (or plugin1 folder)
plugin2.zip (or plugin2 folder)

But the SpringBootPluginManager constructor only supports single Path

    public SpringBootPluginManager(Path pluginsRoot) {
        super(pluginsRoot);
    }

(Machine translation may be inaccurate, hope to understand)

ClassNotFoundException for plugin class, loading a spring boot executable jar

I'm testing the deployment runtime-mode.
Main App finds plugin jar that I put in plugins folder, but it fails when it tries to switch plugin state from RESOLVED to STARTED because:

java.lang.ClassNotFoundException: com.example.MyPlugin

I put the spring boot fat jar, built by spring-boot-maven-plugin that creates the following structure into the jar:

  • BOOT-INF
    -> classes -> com.example.MyPlugin and all others
    -> libs -> all jar dependencies
  • META-INF
  • org/springframework/boot/loader/...

Managing plugins with the shape of spring boot application, is SBP library aware to search classes under BOOT-INF folder?

Plugins lifecycle issue

Hello,

I've identified an issue with the management of the plugins lifecycle.

I have three plugins A, B and C. The plugins B and C depends on the plugin A.
Initially, the three plugins A, B and C are started. Then I do the following actions (actions order is important).

  1. A is stopped -> B and C are also stopped (OK)
  2. B is started -> A is also started and C is still stopped (OK)
  3. C is started -> A, B and C are started (OK)
  4. A is stopped -> B and C are still started (NOK : dependent plugins should never be started if one of its dependencies is stopped, unless it's an optional dependency)

I'm not sure if it's a SBP issue or a PF4J issue (?).
This issue can be reprocuded easily, but an existing example already exists here.

Can't run plugin in test project

Hello,

I try to create a test project to run plugin in spring application with sbp. (repo with the code here => https://github.com/dtrouillet/sbp-test )
My problem is that my plugin won't run.

I have this stacktrace :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-11-08 22:48:01.929 ERROR 91165 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :


APPLICATION FAILED TO START


Description:

Field pluginManager in fr.trouillet.devportal.PluginController required a bean of type 'org.pf4j.PluginManager' that could not be found.

The injection point has the following annotations:

  • @org.springframework.beans.factory.annotation.Autowired(required=true)

The following candidates were found but could not be injected:

  • Bean method 'pluginManager' in 'SbpAutoConfiguration' not loaded because auto-configuration 'SbpAutoConfiguration' was excluded
  • Bean method 'pluginManager' in 'SbpAutoConfiguration' not loaded because auto-configuration 'SbpAutoConfiguration' was excluded

Action:

Consider revisiting the entries above or defining a bean of type 'org.pf4j.PluginManager' in your configuration.

2020-11-08 22:48:01.941 ERROR 91165 --- [ main] org.laxture.sbp.SpringBootPluginManager : Error creating bean with name 'pluginController': Unsatisfied dependency expressed through field 'pluginManager'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.pf4j.PluginManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Thanks a lot

Class not found exception

Hello Hank-cp . Pls I tried implement the sbp library in my project but I keep getting ClassnotFoundException. Pls what am I not doing right?
Uploading sbp.PNG…

ClassCastException: class org.laxture.sbp.spring.boot.SbpAutoConfiguration$1

Caused by: java.lang.ClassCastException: class org.laxture.sbp.spring.boot.SbpAutoConfiguration$1 cannot be cast to class org.laxture.sbp.SpringBootPluginManager (org.laxture.sbp.spring.boot.SbpAutoConfiguration$1 is in unnamed module of loader 'app'; org.laxture.sbp.SpringBootPluginManager is in unnamed module of loader org.pf4j.PluginClassLoader @69d3cf7e)
at org.laxture.sbp.SpringBootPlugin.getPluginManager(SpringBootPlugin.java:183) ~[sbp-core-0.1.13.jar:na]
at org.laxture.sbp.SpringBootPlugin.getMainApplicationContext(SpringBootPlugin.java:187) ~[sbp-core-0.1.13.jar:na]
at org.laxture.sbp.spring.boot.SpringBootstrap.(SpringBootstrap.java:238) ~[sbp-core-0.1.13.jar:na]
at com.plugin.dynamic.DynamicPlugin.createSpringBootstrap(DynamicPlugin.java:15) ~[na:na]
at org.laxture.sbp.SpringBootPlugin.(SpringBootPlugin.java:73) ~[sbp-core-0.1.13.jar:na]
at com.plugin.dynamic.DynamicPlugin.(DynamicPlugin.java:10) ~[na:na]
... 25 common frames omitted

It happens when I am trying to load a plugin from the *.zip.

application.yml:
`spring.sbp:
enabled: true
runtimeMode: deployment
customPluginLoader: org.pf4j.DefaultPluginLoader
classes-directories:

  • out/production/classes
  • out/production/resources`

Add third-party lib to plugin

  1. How can we add third-party lib to plugin?

Now we can only add dependency to main application pom.

  1. How can we get values from plugin properties file application.yaml from jar?

Help

Thank you for your response, I have been able to start the plugin and have access to the endpoint inside the plugin. but pls can you explain how I can stop and update the plugin. And connect each plugin to the data base of the core. It was not that written in the Read Me file. Thank you.

Persistent Bean Initialization Issues in sbp with Spring Boot 3.x

I'm encountering multiple bean initialization issues in a Spring Boot 3.x project using sbp version 3.1.22. The primary challenge involves an UnsatisfiedDependencyException, starting with the SpringBootPluginManager bean and persisting with others.

Steps to Reproduce:

  1. Set up a Spring Boot project with a multi-subproject structure for plugin-oriented programming.
  2. Incorporate sbp-spring-boot-starter in the dependencies.
  3. Configure application.properties as per sbp guidelines.
  4. Create a plugin project within the plugins directory.
  5. Attempt to run the application.

I've basically followed the guide on readme.

Errors Encountered:
The application fails to start, initially due to an UnsatisfiedDependencyException for SpringBootPluginManager. The error message indicates a missing bean:

2024-04-02T09:34:56.200+03:00 ERROR 40304 --- [pluginDemo] [           main] o.laxture.sbp.SpringBootPluginManager    : Error creating bean with name 'pluginManagerController': Unsatisfied dependency expressed through field 'pluginManager': No qualifying bean of type 'org.laxture.sbp.SpringBootPluginManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'pluginManagerController': Unsatisfied dependency expressed through field 'pluginManager': No qualifying bean of type 'org.laxture.sbp.SpringBootPluginManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
...

Resolving this leads to similar issues with other beans.

Attempted Solutions:

  • Utilizing a custom class loader.
  • Adjusting spring.factories.
  • Creating a custom PluginManager bean.
  • Applying scanBasePackages.
  • Downgrading Spring Boot and sbp

None of these attempts have successfully resolved the bean initialization issues.

Additional Context:
The problem seems to extend beyond a specific bean, suggesting a more systemic issue with the sbp setup or compatibility.
I have set up a GitHub repository for detailed inspection of the project.

Request for Assistance:
Guidance or suggestions to resolve these bean initialization challenges would be greatly appreciated.


Unit tetss for core, etc

Not seeing unit tests for core, plugin, etc classes. Looks like there is recent work for sb 3.0. Looks good. Thanks

Integrating library that uses RequestMappingHandlerMapping

Hello,

I'm currently interested in integrating htmx-spring-boot; it's a set of helpers to work with htmx and avoid some boilerplate, the library provides a custom class that extends RequestMappingHandlerMapping for intercepting htmx specific endpoints.

If I add the dependencies and just run my example repo I would get a ClassCastException, I've tried adding the property plugin.pluginFirstClasses=HtmxRequestMappingHandlerMapping and plugin.pluginFirstClasses=io.github.wimdeblauwe.htmx.spring.boot.mvc.HtmxRequestMappingHandlerMapping to the config without any luck, maybe I didn't understand the right way to use this?

So my question is, if I were to integrate this library permanently without relaying in the config for it, how should proceed? Should I create a custom WebMvcRegistrations bean to override the one in SbpWebMvcPatchAutoConfiguration and provide an extended PluginRequestMappingHandlerMapping class that also to included the htmx handling? Or what would be a right way of handling this?

Salutations and thanks.

spring.sbp.custom-plugin-loaders and pluginRepository

I've tried the prop in application-context spring.sbp.custom-plugin-loaders.
It appends custom loaders to the list of pre-existing loaders. So custom loaders can't apply for files with extension .zip or .jar, because the loading is prevented by pre-existing loaders.
So the custom loader should apply for files with different extension, but it's not possible, because the file discovering is accomplished by fileFilter in PluginRepository and there is no way to add custom pluginRepository.

Could you allow to set plugin repositories as you done with plugin loaders?

Let me say my opinion: maybe It's too limited to customize the SpringBootPluginManager only through properties in application.yml. The force of pf4j is the high grade of customization by class inheritance. Why is it not possible to extend your SpringBootPluginManager and declare it as bean preventing the creation in the sbp library? after all there is a @ConditionalOnMissingBean in SbpAutoConfiguration.

ClassNotFoundException in DefaultPluginFactory.create

Hi,

I tried to setup a (very) simple/dummy test project in order to test your library but I'm still not able to load my application.
The source code is available here: https://github.com/j-barata/marketbasket-sbp-sample.

Actually when I try to run the application (through IntelliJ IDEA), I get the following stack and although I've read the documentation many times, I can't see what I'm doing wrong. do you have an idea ?

2020-07-26 21:34:21.133 INFO 45051 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2700 ms
2020-07-26 21:34:21.412 INFO 45051 --- [ main] org.pf4j.DefaultPluginStatusProvider : Enabled plugins: []
2020-07-26 21:34:21.414 INFO 45051 --- [ main] org.pf4j.DefaultPluginStatusProvider : Disabled plugins: []
2020-07-26 21:34:21.421 INFO 45051 --- [ main] org.pf4j.DefaultPluginManager : PF4J version 3.1.0 in 'development' mode
2020-07-26 21:34:21.436 INFO 45051 --- [ main] org.pf4j.AbstractPluginManager : Plugin 'com.github.market.basket.sbp.sample.plugins.tomatoes@1.0.0-SNAPSHOT' resolved
2020-07-26 21:34:21.436 INFO 45051 --- [ main] org.pf4j.AbstractPluginManager : Plugin 'com.github.market.basket.sbp.sample.plugins.potatoes@1.0.0-SNAPSHOT' resolved
2020-07-26 21:34:21.437 INFO 45051 --- [ main] org.pf4j.AbstractPluginManager : Start plugin 'com.github.market.basket.sbp.sample.plugins.tomatoes@1.0.0-SNAPSHOT'
2020-07-26 21:35:44.484 ERROR 45051 --- [ main] org.pf4j.DefaultPluginFactory : com.github.market.basket.sbp.sample.plugins.tomatoes.TomatoesPlugin

java.lang.ClassNotFoundException: com.github.market.basket.sbp.sample.plugins.tomatoes.TomatoesPlugin
at org.laxture.sbp.internal.SpringBootPluginClassLoader.loadClassFromDependencies(SpringBootPluginClassLoader.java:156) ~[sbp-core-0.1.5.jar:na]
at org.laxture.sbp.internal.SpringBootPluginClassLoader.loadClass(SpringBootPluginClassLoader.java:101) ~[sbp-core-0.1.5.jar:na]
at org.pf4j.DefaultPluginFactory.create(DefaultPluginFactory.java:46) ~[pf4j-3.1.0.jar:3.1.0]
at org.pf4j.PluginWrapper.getPlugin(PluginWrapper.java:79) ~[pf4j-3.1.0.jar:3.1.0]
at org.pf4j.AbstractPluginManager.startPlugins(AbstractPluginManager.java:331) ~[pf4j-3.1.0.jar:3.1.0]
at org.laxture.sbp.SpringBootPluginManager.init(SpringBootPluginManager.java:122) ~[sbp-core-0.1.5.jar:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1304) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1224) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:893) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE]
at com.github.market.basket.sbp.sample.application.MarketBasketApplication.main(MarketBasketApplication.java:35) ~[classes/:na]

Bean with that name has already been defined

Hello,

I get the follow error message:

The bean 'resourceHandlerRegistrationCustomizer', defined in class path resource [org/laxture/sbp/spring/boot/SbpMvcPatchAutoConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$ResourceChainCustomizerConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

The Action is not a Solution. Than I get another error message.

I use Spring Boot Version 2.6.8 and sbp-spring-boot-starter Version 0.1.13

Can you help me?

@Autowired support

Hello,

In my plugins I've defined some service classes that implement an interface (and also provided a bean allowing to instantiate the service classes).
In the application I try to autowire these interfaces but I only get :

Field <> in <> Component required a bean of type '<>' that could not be found.
The injection point has the following annotations:

  • @org.springframework.beans.factory.annotation.Autowired(required=true)

It seems that the beans providing these components have not been recognized... or maybe I've missed something.
I already successfully tested the plugin manager "getExtensions" way, but now I would like to use the autowired annotation.

Is it supported ?

Thanks

java.lang.IllegalArgumentException: Profile array must not be null

Hello there, quite new to pf4j and sbp. So I'm probably just missing something.

I'm trying to move an existing pf4j application to sbp. However, when starting the plugin-container, I receive an IllegalArgumentException from spring. According to the stack-trace, the responsible spring boot method is directly called by sbp.

I've tried to specify spring-profiles int the container, as well as in the loaded test-plugin, however, that seems not to be the profiles, spb is using.
Is there any way to specify the used profiles / make that array not null?

spring-boot-starter-parent: 2.2.6.RELEASE
sbp-core: 0.1.3
java: 11

Logs:
sbp.log

Resource handlers support

Hello,

I'm trying to setup a resource provider within a plugin (the resources shall be provided by the plugin itself), and tried the following code :

@configuration
@EnableWebMvc
public class ImageProvider implements WebMvcConfigurer {
@OverRide
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/icons/*").addResourceLocations("classpath:/icons/");
}
}

But I only get a 404 Error.

Is this kind of feature currently supported ?
Thanks

Application can't load the plugin's resourse

Frist ,I have a plugin use springboot and thymeleaf,it can run .

but when the application load it , it's error like

Error resolving template [search_index], template might not exist or might not be accessible by any of the configured Template Resolvers

关于spring+p4j实现的讨论

具体不爽的点:

  1. 如果想使用spring实现一套插件,明明只需要使用spring context即可,为什么要费这么大劲要用springboot来实现,new annotation application context应该更简单
  2. SpringBootstrap类里列举了这么多auto configuration需要排除,真的 看到这个类我心都凉了半截。有没有一种可能,就是,咱只要用简单的spring context就不需要操心这些
  3. 明明p4j提供了明确的classloader加载顺序规范(ClassLoadingStrategy),我实现的时候也没有用这套。但是SpringBootPluginClassLoader这个类实现的真丑,明明内部loadClass可以按约定先平台、后插件jar,居然还提供pluginFirstClasses让调用者关心细节。SpringBootstrap也没有指定父容器的classLoader

新项目已经被我重新实现了,仍然是spring+p4j,如果想看我也可以放出源码

How plugins can read application.properties outside plugin jar

Hi there,

Trying to read plugin-name.properties in plugin jar file using PropertySource.

@PropertySource(value = "file:${admin-ui.home}/config/plugin-name.properties")

But it shows the below message when the plugin is started.

java -jar hans-admin-ui-api-standalone.jar --admin-ui.home=D:\Projects\java\hans-admin-ui-api

Logs

2021-02-25 18:02:58.338  INFO 11584 --- [           main] o.s.c.a.ConfigurationClassParser         : Properties location [file:${admin-ui.home}/config/plugin-name.properties] not resolvable: Could not resolve placeholder 'admin-ui.home' in value "file:${admin-ui.home}/config/plugin-name.properties"

We have also used admin-ui.home placeholder in the parent project. It is working there.

How to load external jar as plugins?

Is that possible to load a plugin from a external jar at runtime?
For example, to haveg an app with a REST API as below:

@RequestMapping(value = "/installplugin", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public void install(@RequestBody(required = true) MultipartFile file) {
        URLClassLoader child = new URLClassLoader(
                new URL[] {myJar.toURI().toURL()},
                this.getClass().getClassLoader()
        );
        Class<?> clazz = Class.forName("mypackage.MyClass", true, loader);

       // pesudo code
       pluginManager.load(clazz);
       pluginManager.start("plugin-id");
}

then mypackage.MyClass (as a plugin) is a RestController:

@RestController
@RequestMapping("/message")
public class MyClass {

	@RequestMapping(value = "/return", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
	public Message testMethod() {
		return new Message("HIHIHIHI");
	}
}

User should be able to call new endpoint with /message/return after plugin being installed.

Support multiple Jvm/Spring Boot version

Dfficalties:

  • PluginResourceHandlerRegistrationCustomizer changes a lot between Spring boot versions.
  • DemoApp 3th patry libs version changes.
    • Flyway
  • Gradle version requirement changes.

SOLUTION 1:

  • Make Spring Boot dependecies level lower from implementation to runtime
  • App specify Spring Boot version as their own needs.

SOLUTION 2:

  • Release different version branch, which mapping to coresponding Spring Boot versions

Can't start with java 8

Hello!

Could you help me?

Error appeared, when I create bean for pluginManager

Error:(88, 23) java: cannot access org.laxture.sbp.SpringBootPluginManager
bad class file: /C:/m2/org/laxture/sbp-core/0.1.7/sbp-core-0.1.7.jar!/org/laxture/sbp/SpringBootPluginManager.class
class file has wrong version 55.0, should be 52.0
Please remove or make sure it appears in the correct subdirectory of the classpath.

How to get DataSource

How to get DataSource in main App from plugin ??
Or Plugin datasource withaut set on plugin(application.yaml)

Error when Main Application uses Eureka

How to solve the following problem ??

My main application use eureka client
If the plugin does not use eureka configuration, it will error.
But not to the contrary, I have to force the plugin to use eureka config.

SS:
I have to force the plugin to use eureka config. its OK
image

But if set to false is Fails
image
Result :
image

java.lang.IllegalArgumentException: class org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer is not assignable to interface org.springframework.context.ApplicationContextInitializer

Hello!

I tried to use SpringBootPlugin, but I have an error, when init SpringBootstrap at
super(new DefaultResourceLoader(plugin.getWrapper().getPluginClassLoader()), primarySources);

ConfigurationWarningsApplicationContextInitializer and ApplicationContextInitializer are under different Class Loader (PluginClassLoader and AppClassLoader) and SpringApplication.createSpringFactoriesInstances#Assert.isAssignable(type, instanceClass); fails

What should I do? Thank you!

Add third-party lib to plugin

  1. How can we add third-party lib to plugin? For example
org.apache.xmlbeans xmlbeans 3.1.0 runtime

Now we can only add dependency to main application pom.

  1. How can we get values from plugin properties file application.yaml from jar?

org.hibernate.MappingException: An association refers to an unmapped class

So, I'm trying to understand how to use the "Single shared DataSource", as described in the persistence documentation.

I have two plugins, one responsible for storing libraries and a second one for storing videos.

I'm using the SharedDataSourceSpringBootstrap within the SpringBootPlugin class in both plugins like so:

public class LibraryPlugin extends SpringBootPlugin {
  public LibraryPlugin(final PluginWrapper wrapper) {
    super(wrapper);
  }

  @Override
  protected SpringBootstrap createSpringBootstrap() {
    return new SharedDataSourceSpringBootstrap(this, LibraryStarter.class);
  }
}

And create the Entities as usual, however, separated into the two different plugins.

The Video entity contains a reference to the Library entity as follows:

@Entity
public class Video {
  @Id
  private long id;
  @OneToOne
  @MapsId
  @JoinColumn(name = "library")
  private Library library;
}

When starting the system, the video-plugins exits with the following cause:
Caused by: org.hibernate.MappingException: An association from the table video refers to an unmapped class: com.example.plugins.library.Library

Now, as hibernate thinks that the plugin is unmapped and both plugins are running their own hibernate instance, where they can't see the other classes.

Is this even supposed to work?
In the end, the persistence documentation never states that the data source is also shared between plugins (i just assumed since both plugins are using the data source from the main-application)

Do I have to include SharedDataSourceSpringBootstrap somewhere within the main-application?
I have not seen anything that hints to something like that, but as the data-source is probably still separated.

Edit:
Forgot to mention, but i've added the plugin dependency to both, maven and plugin.properties

How to customize the plugin manager?

I've tried to define a custom plugin manager

@Configuration
public class AppConfig {

    @Bean
    public SpringBootPluginManager pluginManager() {
        return new CustomPluginManager();
    }
   ...
}

public class CustomPluginManager extends SpringBootPluginManager {
 ...
}

and I got this error:

Caused by: java.lang.ClassCastException: class org.mypackage.CustomPluginManager cannot be cast
 to class org.laxture.sbp.SpringBootPluginManager (org.mypackage.CustomPluginManager is in 
unnamed module of loader 'app'; org.laxture.sbp.SpringBootPluginManager is in unnamed module 
of loader org.pf4j.PluginClassLoader @69228e85)

How can I define a CustomPluginManager that extends SpringBootPluginManager?

Plugin 使用 @SpringBootApplication 出現 PluginResourceHandlerRegistrationCustomizer 無法初始化問題

我的環境是 Java8
測試的倉庫在這
Springboot 版本為 2.7.17
Sbp 版本為 2.7.17

不管在 development mode 還是在 deployment mode
只要 Plugin 的啟動器使用 @SpringBootApplication 標籤 ( 例如這樣 )
運行時就會出現

2023-11-14 17:52:21.153 DEBUG 24704 --- [           main] o.l.s.i.PluginListableBeanFactory        : Creating shared instance of singleton bean 'resourceHandlerRegistrationCustomizer'
2023-11-14 17:52:21.170  WARN 24704 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'resourceHandlerRegistrationCustomizer': Unsatisfied dependency expressed through field 'webProperties'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.autoconfigure.web.WebProperties' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2023-11-14 17:52:21.176  INFO 24704 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-11-14 17:52:21.216 ERROR 24704 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field webProperties in org.springframework.boot.autoconfigure.web.servlet.PluginResourceHandlerRegistrationCustomizer required a bean of type 'org.springframework.boot.autoconfigure.web.WebProperties' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.springframework.boot.autoconfigure.web.WebProperties' in your configuration.

2023-11-14 16:36:53.849 ERROR 28064 --- [           main] org.laxture.sbp.SpringBootPluginManager  : Error creating bean with name 'resourceHandlerRegistrationCustomizer': Unsatisfied dependency expressed through field 'webProperties'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.autoconfigure.web.WebProperties' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'resourceHandlerRegistrationCustomizer': Unsatisfied dependency expressed through field 'webProperties'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.autoconfigure.web.WebProperties' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:713) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:693) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:408) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:921) [spring-context-5.3.30.jar:5.3.30]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) [spring-context-5.3.30.jar:5.3.30]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-2.7.17.jar:2.7.17]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) ~[spring-boot-2.7.17.jar:2.7.17]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.17.jar:2.7.17]
	at org.laxture.sbp.SpringBootPlugin.start(SpringBootPlugin.java:99) ~[sbp-core-2.7.17.jar:na]
	at org.laxture.sbp.SpringBootPluginManager.doStartPlugins(SpringBootPluginManager.java:149) [sbp-core-2.7.17.jar:na]
	at org.laxture.sbp.SpringBootPluginManager.startPlugins(SpringBootPluginManager.java:232) [sbp-core-2.7.17.jar:na]
	at org.laxture.sbp.internal.MainAppStartedListener.onApplicationEvent(MainAppStartedListener.java:43) [sbp-core-2.7.17.jar:na]
	at org.laxture.sbp.internal.MainAppStartedListener.onApplicationEvent(MainAppStartedListener.java:31) [sbp-core-2.7.17.jar:na]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178) [spring-context-5.3.30.jar:5.3.30]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171) [spring-context-5.3.30.jar:5.3.30]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:145) [spring-context-5.3.30.jar:5.3.30]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421) [spring-context-5.3.30.jar:5.3.30]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378) [spring-context-5.3.30.jar:5.3.30]
	at org.springframework.boot.context.event.EventPublishingRunListener.started(EventPublishingRunListener.java:108) [spring-boot-2.7.17.jar:2.7.17]
	at org.springframework.boot.SpringApplicationRunListeners.lambda$started$5(SpringApplicationRunListeners.java:78) [spring-boot-2.7.17.jar:2.7.17]
	at java.util.ArrayList.forEach(ArrayList.java:1259) ~[na:1.8.0_265]
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120) [spring-boot-2.7.17.jar:2.7.17]
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114) [spring-boot-2.7.17.jar:2.7.17]
	at org.springframework.boot.SpringApplicationRunListeners.started(SpringApplicationRunListeners.java:78) [spring-boot-2.7.17.jar:2.7.17]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) ~[spring-boot-2.7.17.jar:2.7.17]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.7.17.jar:2.7.17]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) ~[spring-boot-2.7.17.jar:2.7.17]
	at com.xeriou.robotapp.RobotAppApplication.main(RobotAppApplication.java:15) ~[classes/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.autoconfigure.web.WebProperties' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1801) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1357) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.30.jar:5.3.30]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:710) ~[spring-beans-5.3.30.jar:5.3.30]
	... 36 common frames omitted

但是,只要將啟動改成@ComponentScan (例如這樣) 就不會出錯,且運行不會有問題。

但這樣會導致 DataSource 的 Bean 沒有辦法共用 (在 pluginx 裡)
且開發上,無法獨立運行,挺不方便的
我看大家都沒出甚麼問題,可能是我設定方式不對...

Plugin not loading when using Swagger in Application with below error

Configuration :
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableSwagger2 in Configuration class

Error
Ambiguous mapping. Cannot map 'springfox.documentation.oas.web.OpenApiControllerWebMvc@64c5516e' method \nspringfox.documentation.oas.web.OpenApiControllerWebMvc#getDocumentation(String, HttpServletRequest)\nto {GET [/v3/api-docs], produces [application/json || application/hal+json]}: There is already 'openApiControllerWebMvc' bean method\nspringfox.documentation.oas.web.OpenApiControllerWebMvc#getDocumentation(String, HttpServletRequest) mapped.

Different classLoader is used with spring-dev-tools

When I use spring-dev-tools my api interface is in a different class loader : RestartClassLoader managed by Spring Dev Tools.
With this library, my Plugin can't upcasted in my API Interface (ClassCastException) because the API Interface is in other class loader (RestartClassLoader).

For now I remove spring-dev-tools in my prject.

Support WebFlux

Now sbp supports WebMVC only. Need to investigate how to support WebFlux.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.