pf4j-spring
pf4j-spring copied to clipboard
Not possible to create a CRUD repository as ExtensionPoint
I'm not able to autowire an Extension in an Extension: https://github.com/keering/keering/blob/master/plugins/widgets/chat/src/main/java/com/github/keering/plugins/widgets/chat/service/impl/ChatHistoryServiceImpl.java#L16
You can start the project by running: $ ./gradlew build && cd build && java -jar app-1.0-SNAPSHOT.jar
I don't understand why you say that ChatHistoryRepository is an extension point.
Put the log of PF4J on trace or debug (see demo) and see the details.
Oh well, you're right. I didn't marked ChatHistoryRepository as an extension point. Now I did locally and getting this stacktrace as it is an interface, not a class:
java.lang.InstantiationException: com.github.keering.plugins.widgets.chat.repository.ChatHistoryRepository
at java.base/java.lang.Class.newInstance(Class.java:547) ~[na:na]
at org.pf4j.spring.SpringExtensionFactory.createWithoutSpring(SpringExtensionFactory.java:70) [pf4j-spring-0.5.0.jar!/:0.5.0]
at org.pf4j.spring.SpringExtensionFactory.create(SpringExtensionFactory.java:51) [pf4j-spring-0.5.0.jar!/:0.5.0]
at org.pf4j.spring.ExtensionsInjector.registerExtension(ExtensionsInjector.java:80) [pf4j-spring-0.5.0.jar!/:0.5.0]
at org.pf4j.spring.ExtensionsInjector.injectExtensions(ExtensionsInjector.java:64) [pf4j-spring-0.5.0.jar!/:0.5.0]
at org.pf4j.spring.SpringPluginManager.init(SpringPluginManager.java:66) [pf4j-spring-0.5.0.jar!/:0.5.0]
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:564) ~[na:na]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:363) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:307) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:419) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1737) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:307) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) [spring-beans-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083) ~[spring-context-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:853) ~[spring-context-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) ~[spring-context-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.1.RELEASE.jar!/:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) ~[spring-boot-2.1.1.RELEASE.jar!/:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.1.1.RELEASE.jar!/:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[spring-boot-2.1.1.RELEASE.jar!/:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) ~[spring-boot-2.1.1.RELEASE.jar!/:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) ~[spring-boot-2.1.1.RELEASE.jar!/:2.1.1.RELEASE]
at com.github.keering.app.Application.main(Application.java:10) ~[classes!/: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:564) ~[na:na]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) ~[app-1.0-SNAPSHOT.jar:na]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) ~[app-1.0-SNAPSHOT.jar:na]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) ~[app-1.0-SNAPSHOT.jar:na]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) ~[app-1.0-SNAPSHOT.jar:na]
Caused by: java.lang.NoSuchMethodException: com.github.keering.plugins.widgets.chat.repository.ChatHistoryRepository.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3302) ~[na:na]
at java.base/java.lang.Class.newInstance(Class.java:532) ~[na:na]
... 40 common frames omitted
It's a so called CRUD repository which doesn't need a class: https://docs.spring.io/spring-data/jpa/docs/1.6.0.RELEASE/reference/html/jpa.repositories.html https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html
I guess SpringExtensionFactory#createWithoutSpring should check for org.springframework.data.repository.Repository.class.isAssignableFrom(extensionClass) and create a JpaRepositoryFactoryBean instead.
I'll do further research and open up a pull request if it fixes this restriction.
I was able to create a bean now with this method:
protected Object createWithoutSpring(Class<?> extensionClass) {
try {
if (isClassAvailable("org.springframework.data.repository.Repository") && Repository.class.isAssignableFrom(extensionClass)) {
PluginWrapper pluginWrapper = pluginManager.whichPlugin(extensionClass);
if (pluginWrapper != null) {
Plugin plugin = pluginWrapper.getPlugin();
if (plugin instanceof SpringPlugin) {
JpaRepositoryFactoryBean repositoryFactoryBean = new JpaRepositoryFactoryBean(extensionClass);
ApplicationContext pluginContext = ((SpringPlugin) plugin).getApplicationContext();
repositoryFactoryBean.setEntityManager(pluginContext.getBean(EntityManager.class));
repositoryFactoryBean.setEntityPathResolver(pluginContext.getBeanProvider(EntityPathResolver.class));
repositoryFactoryBean.afterPropertiesSet();
return repositoryFactoryBean;
}
}
} else {
return extensionClass.newInstance();
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}
private boolean isClassAvailable(String className) {
try {
Class.forName(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
But in the end I'm getting this exception:
java.lang.IllegalArgumentException: Not a managed type: class com.github.keering.plugins.widgets.chat.model.jpa.ChatHistory
at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:552) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final]
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:74) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:188) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:139) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:123) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:64) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:305) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:211) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.util.Lazy.get(Lazy.java:94) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:119) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.pf4j.spring.SpringExtensionFactory.createWithoutSpring(SpringExtensionFactory.java:84) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT]
at org.pf4j.spring.SpringExtensionFactory.create(SpringExtensionFactory.java:56) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT]
at org.pf4j.spring.ExtensionsInjector.registerExtension(ExtensionsInjector.java:80) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT]
at org.pf4j.spring.ExtensionsInjector.injectExtensions(ExtensionsInjector.java:64) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT]
at org.pf4j.spring.SpringPluginManager.init(SpringPluginManager.java:66) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT]
I also had to add some dependencies in provided scope and update spring version:
diff --git a/pf4j-spring/pom.xml b/pf4j-spring/pom.xml
index b4a6713..748eeb9 100644
--- a/pf4j-spring/pom.xml
+++ b/pf4j-spring/pom.xml
@@ -33,6 +33,27 @@
<version>${spring.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.springframework.data</groupId>
+ <artifactId>spring-data-commons</artifactId>
+ <version>${spring-data.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.data</groupId>
+ <artifactId>spring-data-jpa</artifactId>
+ <version>${spring-data.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>${persistence-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
<!-- Logs -->
<dependency>
<groupId>log4j</groupId>
diff --git a/pom.xml b/pom.xml
index 4ff28ac..3fcf403 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,7 +46,9 @@
<java.version>1.7</java.version>
<pf4j.version>2.5.0</pf4j.version>
- <spring.version>4.0.5.RELEASE</spring.version>
+ <persistence-api.version>1.0.2</persistence-api.version>
+ <spring.version>5.1.0.RELEASE</spring.version>
+ <spring-data.version>2.1.3.RELEASE</spring-data.version>
<slf4j.version>1.7.5</slf4j.version>
<junit.version>4.12</junit.version>
Maybe it's just not possible. I don't know what to try else.
development ?
look at https://pf4j.org/doc/development-mode.html
I was able to create a bean now with this method:
protected Object createWithoutSpring(Class<?> extensionClass) { try { if (isClassAvailable("org.springframework.data.repository.Repository") && Repository.class.isAssignableFrom(extensionClass)) { PluginWrapper pluginWrapper = pluginManager.whichPlugin(extensionClass); if (pluginWrapper != null) { Plugin plugin = pluginWrapper.getPlugin(); if (plugin instanceof SpringPlugin) { JpaRepositoryFactoryBean repositoryFactoryBean = new JpaRepositoryFactoryBean(extensionClass); ApplicationContext pluginContext = ((SpringPlugin) plugin).getApplicationContext(); repositoryFactoryBean.setEntityManager(pluginContext.getBean(EntityManager.class)); repositoryFactoryBean.setEntityPathResolver(pluginContext.getBeanProvider(EntityPathResolver.class)); repositoryFactoryBean.afterPropertiesSet(); return repositoryFactoryBean; } } } else { return extensionClass.newInstance(); } } catch (Exception e) { log.error(e.getMessage(), e); } return null; } private boolean isClassAvailable(String className) { try { Class.forName(className); return true; } catch (ClassNotFoundException e) { return false; } }But in the end I'm getting this exception:
java.lang.IllegalArgumentException: Not a managed type: class com.github.keering.plugins.widgets.chat.model.jpa.ChatHistory at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:552) ~[hibernate-core-5.3.7.Final.jar!/:5.3.7.Final] at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:74) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:188) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:139) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:123) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:64) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:305) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.util.Lazy.getNullable(Lazy.java:211) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.util.Lazy.get(Lazy.java:94) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300) ~[spring-data-commons-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:119) ~[spring-data-jpa-2.1.3.RELEASE.jar!/:2.1.3.RELEASE] at org.pf4j.spring.SpringExtensionFactory.createWithoutSpring(SpringExtensionFactory.java:84) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT] at org.pf4j.spring.SpringExtensionFactory.create(SpringExtensionFactory.java:56) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT] at org.pf4j.spring.ExtensionsInjector.registerExtension(ExtensionsInjector.java:80) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT] at org.pf4j.spring.ExtensionsInjector.injectExtensions(ExtensionsInjector.java:64) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT] at org.pf4j.spring.SpringPluginManager.init(SpringPluginManager.java:66) [pf4j-spring-0.6.0-SNAPSHOT.jar!/:0.6.0-SNAPSHOT]I also had to add some dependencies in provided scope and update spring version:
diff --git a/pf4j-spring/pom.xml b/pf4j-spring/pom.xml index b4a6713..748eeb9 100644 --- a/pf4j-spring/pom.xml +++ b/pf4j-spring/pom.xml @@ -33,6 +33,27 @@ <version>${spring.version}</version> </dependency> + <dependency> + <groupId>org.springframework.data</groupId> + <artifactId>spring-data-commons</artifactId> + <version>${spring-data.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.springframework.data</groupId> + <artifactId>spring-data-jpa</artifactId> + <version>${spring-data.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>javax.persistence</groupId> + <artifactId>persistence-api</artifactId> + <version>${persistence-api.version}</version> + <scope>provided</scope> + </dependency> + <!-- Logs --> <dependency> <groupId>log4j</groupId> diff --git a/pom.xml b/pom.xml index 4ff28ac..3fcf403 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,9 @@ <java.version>1.7</java.version> <pf4j.version>2.5.0</pf4j.version> - <spring.version>4.0.5.RELEASE</spring.version> + <persistence-api.version>1.0.2</persistence-api.version> + <spring.version>5.1.0.RELEASE</spring.version> + <spring-data.version>2.1.3.RELEASE</spring-data.version> <slf4j.version>1.7.5</slf4j.version> <junit.version>4.12</junit.version>Maybe it's just not possible. I don't know what to try else.
Were you able to get the CRUD Repository to work?