wiverson / maven-jpackage-template

Sample project illustrating building nice, small cross-platform JavaFX or Swing desktop apps with native installers while still using the standard Maven dependency system.
Apache License 2.0
346 stars 53 forks source link

Spring Boot + JPA integration #75

Closed 0-don closed 2 years ago

0-don commented 2 years ago

I am having problems impleting spring boot + jpa into your maven-jpackage template.

I saw there was a branch which is missing https://github.com/wiverson/maven-jpackage-template/tree/spring-boot-test is there a way to still check it out

I managed to implemenet spring boot without jpa as seen here but when trying to implement jpa with sql lite I am getting problems in production build for example.

Log :: Spring Boot :: (v2.7.4) 2022-09-24 10:07:54.292 INFO ??? --- [JavaFX-Launcher] o.s.boot.SpringApplication : Starting application using Java 17.0.4 on windows with PID ??? (started by don in C:\WINDOWS\system32) 2022-09-24 10:07:54.295 INFO ??? --- [JavaFX-Launcher] o.s.boot.SpringApplication : No active profile set, falling back to 1 default profile: "default" 2022-09-24 10:07:54.590 ERROR ??? --- [JavaFX-Launcher] o.s.boot.SpringApplication : Application run failed java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration.propertySourcesPlaceholderConfigurer at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60) ~[spring-boot-autoconfigure-2.7.4.jar:2.7.4] at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:193) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:153) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:129) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:343) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.4.jar:2.7.4] at com.javafxspring.BaseApplication.init(BaseApplication.java:47) ~[javafx-spring-1.0-SNAPSHOT.jar:na] at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source) ~[javafx.graphics:na] at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(Unknown Source) ~[javafx.graphics:na] at java.base/java.lang.Thread.run(Unknown Source) ~[na:na] Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.javafxspring.config.DbConfig] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@e3269ba] at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:485) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:361) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:418) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.lambda$getTypeForFactoryMethod$2(AbstractAutowireCapableBeanFactory.java:765) ~[spring-beans-5.3.23.jar:5.3.23] at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(Unknown Source) ~[na:na] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:764) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:703) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:674) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1670) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:570) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:250) ~[spring-boot-autoconfigure-2.7.4.jar:2.7.4] at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:243) ~[spring-boot-autoconfigure-2.7.4.jar:2.7.4] at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:233) ~[spring-boot-autoconfigure-2.7.4.jar:2.7.4] at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:181) ~[spring-boot-autoconfigure-2.7.4.jar:2.7.4] at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:156) ~[spring-boot-autoconfigure-2.7.4.jar:2.7.4] at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-2.7.4.jar:2.7.4] ... 19 common frames omitted Caused by: java.lang.NoClassDefFoundError: javax/sql/DataSource at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na] at java.base/java.lang.Class.privateGetDeclaredMethods(Unknown Source) ~[na:na] at java.base/java.lang.Class.getDeclaredMethods(Unknown Source) ~[na:na] at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:467) ~[spring-core-5.3.23.jar:5.3.23] ... 35 common frames omitted Caused by: java.lang.ClassNotFoundException: javax.sql.DataSource at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source) ~[na:na] at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(Unknown Source) ~[na:na] ... 39 common frames omitted 2022-09-24 10:07:54.598 WARN ??? --- [JavaFX-Launcher] o.s.boot.SpringApplication : Unable to close ApplicationContext java.lang.IllegalStateException: Failed to introspect Class [com.javafxspring.config.DbConfig] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@e3269ba] at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:485) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:361) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:418) ~[spring-core-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.lambda$getTypeForFactoryMethod$2(AbstractAutowireCapableBeanFactory.java:765) ~[spring-beans-5.3.23.jar:5.3.23] at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(Unknown Source) ~[na:na] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:764) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:703) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:674) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1670) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:570) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:542) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:669) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:661) ~[spring-beans-5.3.23.jar:5.3.23] at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1300) ~[spring-context-5.3.23.jar:5.3.23] at org.springframework.boot.SpringApplication.getExitCodeFromMappedException(SpringApplication.java:867) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.getExitCodeFromException(SpringApplication.java:855) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.handleExitCode(SpringApplication.java:842) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:782) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:318) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.4.jar:2.7.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.4.jar:2.7.4] at com.javafxspring.BaseApplication.init(BaseApplication.java:47) ~[javafx-spring-1.0-SNAPSHOT.jar:na] at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source) ~[javafx.graphics:na] at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(Unknown Source) ~[javafx.graphics:na] at java.base/java.lang.Thread.run(Unknown Source) ~[na:na] Caused by: java.lang.NoClassDefFoundError: javax/sql/DataSource at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na] at java.base/java.lang.Class.privateGetDeclaredMethods(Unknown Source) ~[na:na] at java.base/java.lang.Class.getDeclaredMethods(Unknown Source) ~[na:na] at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:467) ~[spring-core-5.3.23.jar:5.3.23] ... 24 common frames omitted Caused by: java.lang.ClassNotFoundException: javax.sql.DataSource at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source) ~[na:na] at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(Unknown Source) ~[na:na] ... 28 common frames omitted Exception in Application init method java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source) at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at java.base/sun.launcher.LauncherHelper$FXHelper.main(Unknown Source) Caused by: java.lang.RuntimeException: Exception in Application init method at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source) at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) Caused by: java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration.propertySourcesPlaceholderConfigurer at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60) at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:193) at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:153) at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:129) at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:343) at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) at com.javafxspring.BaseApplication.init(BaseApplication.java:47) ... 3 more Caused by: java.lang.IllegalStateException: Failed to introspect Class [com.javafxspring.config.DbConfig] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@e3269ba] at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:485) at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:361) at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:418) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.lambda$getTypeForFactoryMethod$2(AbstractAutowireCapableBeanFactory.java:765) at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(Unknown Source) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:764) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:703) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:674) at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1670) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:570) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:542) at org.springframework.boot.autoconfigure.condition.OnBeanCondition.collectBeanNamesForType(OnBeanCondition.java:250) at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:243) at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getBeanNamesForType(OnBeanCondition.java:233) at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(OnBeanCondition.java:181) at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:156) at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ... 19 more Caused by: java.lang.NoClassDefFoundError: javax/sql/DataSource at java.base/java.lang.Class.getDeclaredMethods0(Native Method) at java.base/java.lang.Class.privateGetDeclaredMethods(Unknown Source) at java.base/java.lang.Class.getDeclaredMethods(Unknown Source) at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:467) ... 35 more Caused by: java.lang.ClassNotFoundException: javax.sql.DataSource at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source) at java.base/java.lang.ClassLoader.loadClass(Unknown Source) ... 39 more Exception running application com.javafxspring.BaseApplication ```
wiverson commented 2 years ago

Hmm. I get this request/attempt pretty often - folks trying to integrate Spring Boot into a desktop app. This scenario (Spring Boot + SQLite) seems pretty popular.

Question - are you trying to build a UI with Spring Boot as well? e.g. Thymeleaf? Just stepping back a bit - what are you trying to do here?

I've been pondering building an "official" version of the template specifically for this scenario. I think the main two scenarios are a) a background app that lives in the system tray and b) basically something like Tauri+Rust but instead it's more like Electron for Java.

In the b) scenario which I'm going to call "BootFX" going forward, the template would likely bundle the JavaFX embedded web browser and point it at a preconfigured Spring Boot app. Developers would mainly just build a Spring Boot app w/Thymeleaf like normal, but if they wanted to do more "desktop" stuff they can fall back on regular desktop Java/JavaFX stuff.

Whaddya think? What are you trying to build?

0-don commented 2 years ago

I am just building simple concept apps like color detector and clipboard manager and wanted to have a better developer expierence with jpa and dependency injections.

is the branch that was mentioned in previous issue fully removed or is there an example still available?

I dont think I would use the web based components of spring like Thymleaf or run it as a web server personally but I think jpa + sqlite would be an awesome addition.

wiverson commented 2 years ago

Not sure what's up with that branch or where it went.

Conceptually, it's pretty easy. Just grab that main method from your Spring Boot app and instead have it be part of the Swing or JavaFX launch. You almost certainly will want to route System.out/System.err to a log file at the very beginning of your launch (before you start up Spring Boot and Swing/JavaFX) so you will be able to figure out launch related errors. Eventually you will to get fancier with integration (e.g. adding listeners to the Spring/Spring Boot application life cycle to add nicer UI) but that is (as they say) just work.

orx0815 commented 2 years ago

I have a PoC toy-project that uses springboot for no reason. It's only using the IoC container to glue stuff together. No JPA or any other modules from spring-boot are used. Have a loom at the Application-class to see how to start the context within javaFx

It has a collection of different deployments and the aot-compiled on is using spring-native, but that's a different story.

Never found the time to add this maven-jpackage-template to the deploy section though :(