spring-projects / spring-shell

Spring based shell
http://projects.spring.io/spring-shell/
Apache License 2.0
724 stars 393 forks source link

Spring Initializr not configured correctly for Spring Shell #976

Closed JohnDuncanScott closed 3 months ago

JohnDuncanScott commented 8 months ago

Hiya, I followed https://docs.spring.io/spring-shell/reference/getting-started.html and used Spring Initializr to create a demo app. I have attached the zip provided by the website: demo.zip

I deleted the test, ran the package step, and then ran java -jar on the package as documented. However, there seems to be an issue with the dependencies and the app fails to start with quite a cryptic message. I assume there's some issue with the jline terminal under the hood, probably mismatched dependency.

Here is the stack trace:

:: Spring Boot :: (v3.2.1)

2024-01-16T22:26:32.708Z INFO 22448 --- [ main] com.example.demo.DemoApplication : Starting DemoApplication using Java 21.0.1 with PID 22448 (C:\Users\dunca\Downloads\demo\demo\target\demo-0.0.1-SNAPSHOT.jar started by dunca in C:\Users\dunca\Downloads\demo\demo\target) 2024-01-16T22:26:32.710Z INFO 22448 --- [ main] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default" 2024-01-16T22:26:33.512Z WARN 22448 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultShellApplicationRunner' defined in class path resource [org/springframework/shell/boot/ApplicationRunnerAutoConfiguration.class]: Unsatisfied dependency expressed through method 'defaultShellApplicationRunner' parameter 0: Error creating bean with name 'interactiveApplicationRunner' defined in class path resource [org/springframework/shell/boot/ShellRunnerAutoConfiguration$NonePrimaryCommandConfiguration.class]: Unsatisfied dependency expressed through method 'interactiveApplicationRunner' parameter 0: Error creating bean with name 'org.springframework.shell.boot.LineReaderAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'terminal' defined in class path resource [org/springframework/shell/boot/JLineShellAutoConfiguration.class]: Failed to instantiate [org.jline.terminal.Terminal]: Factory method 'terminal' threw exception with message: Cannot invoke "java.lang.Boolean.booleanValue()" because "this.jna" is null 2024-01-16T22:26:33.518Z INFO 22448 --- [ main] .s.b.a.l.ConditionEvaluationReportLogger :

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2024-01-16T22:26:33.530Z ERROR 22448 --- [ main] o.s.boot.SpringApplication : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultShellApplicationRunner' defined in class path resource [org/springframework/shell/boot/ApplicationRunnerAutoConfiguration.class]: Unsatisfied dependency expressed through method 'defaultShellApplicationRunner' parameter 0: Error creating bean with name 'interactiveApplicationRunner' defined in class path resource [org/springframework/shell/boot/ShellRunnerAutoConfiguration$NonePrimaryCommandConfiguration.class]: Unsatisfied dependency expressed through method 'interactiveApplicationRunner' parameter 0: Error creating bean with name 'org.springframework.shell.boot.LineReaderAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'terminal' defined in class path resource [org/springframework/shell/boot/JLineShellAutoConfiguration.class]: Failed to instantiate [org.jline.terminal.Terminal]: Factory method 'terminal' threw exception with message: Cannot invoke "java.lang.Boolean.booleanValue()" because "this.jna" is null at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:802) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1164) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:960) ~[spring-context-6.1.2.jar!/:6.1.2] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.2.jar!/:6.1.2] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762) ~[spring-boot-3.2.1.jar!/:3.2.1] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:464) ~[spring-boot-3.2.1.jar!/:3.2.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.1.jar!/:3.2.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1358) ~[spring-boot-3.2.1.jar!/:3.2.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1347) ~[spring-boot-3.2.1.jar!/:3.2.1] at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[!/:na] at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na

    at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
    at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91) ~[demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53) ~[demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:58) ~[demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'interactiveApplicationRunner' defined in class path resource [org/springframework/shell/boot/ShellRunnerAutoConfiguration$NonePrimaryCommandConfiguration.class]: Unsatisfied dependency expressed through method 'interactiveApplicationRunner' parameter 0: Error creating bean with name 'org.springframework.shell.boot.LineReaderAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'terminal' defined in class path resource [org/springframework/shell/boot/JLineShellAutoConfiguration.class]: Failed to instantiate [org.jline.terminal.Terminal]: Factory method 'terminal' threw exception with message: Cannot invoke "java.lang.Boolean.booleanValue()" because "this.jna" is null at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:802) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1164) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1689) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1653) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeanCollection(DefaultListableBeanFactory.java:1543) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1511) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1392) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:911) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789) ~[spring-beans-6.1.2.jar!/:6.1.2] ... 23 common frames omitted Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.shell.boot.LineReaderAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'terminal' defined in class path resource [org/springframework/shell/boot/JLineShellAutoConfiguration.class]: Failed to instantiate [org.jline.terminal.Terminal]: Factory method 'terminal' threw exception with message: Cannot invoke "java.lang.Boolean.booleanValue()" because "this.jna" is null at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:802) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:241) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1191) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:413) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1164) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:911) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789) ~[spring-beans-6.1.2.jar!/:6.1.2] ... 41 common frames omitted Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'terminal' defined in class path resource [org/springframework/shell/boot/JLineShellAutoConfiguration.class]: Failed to instantiate [org.jline.terminal.Terminal]: Factory method 'terminal' threw exception with message: Cannot invoke "java.lang.Boolean.booleanValue()" because "this.jna" is null at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:643) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1164) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:911) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789) ~[spring-beans-6.1.2.jar!/:6.1.2] ... 64 common frames omitted Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.jline.terminal.Terminal]: Factory method 'terminal' threw exception with message: Cannot invoke "java.lang.Boolean.booleanValue()" because "this.jna" is null at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:177) ~[spring-beans-6.1.2.jar!/:6.1.2] at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) ~[spring-beans-6.1.2.jar!/:6.1.2] ... 78 common frames omitted Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Boolean.booleanValue()" because "this.jna" is null at org.jline.terminal.TerminalBuilder.doBuild(TerminalBuilder.java:443) ~[jline-3.24.1.jar!/:na] at org.jline.terminal.TerminalBuilder.build(TerminalBuilder.java:362) ~[jline-3.24.1.jar!/:na] at org.springframework.shell.boot.JLineShellAutoConfiguration.terminal(JLineShellAutoConfiguration.java:51) ~[spring-shell-autoconfigure-3.2.0.jar!/:3.2.0] at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na

    at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~[spring-beans-6.1.2.jar!/:6.1.2]
    ... 79 common frames omitted
jvalkeal commented 8 months ago

Could you add jna as that's basically required on windows:

<dependency>
    <groupId>org.springframework.shell</groupId>
    <artifactId>spring-shell-starter-jna</artifactId>
</dependency>

That NPE is coming from JLine itself looks to be a bug there. Check on windows before throwing error for missing jna or jansi. I'll report that to them.

https://github.com/jline/jline3/blob/c0462003a4dbef935f622492bf9f3707aff1b786/terminal/src/main/java/org/jline/terminal/TerminalBuilder.java#L443-L446

JohnDuncanScott commented 8 months ago

Thanks very much, that fixed it perfectly :).

It would be good to update the getting started documentation - https://docs.spring.io/spring-shell/reference/getting-started.html. spring-shell-starter-jna being required is not mentioned and it isn't added as part of Spring Initialzr either.

euledge commented 4 months ago

According to the issue on https://github.com/jline/jline3/issues/930, it was resolved in 3.25.1

jvalkeal commented 3 months ago

Right yes, forget to close this as we're on newer jline already.