I am building a shell application using Spring shell. At this point, everything is running fine on intelliJ, meaning I can run my commands without any problems.
I am using JPA with hibernate being the implementation provider, I was able to connect to my database and able to query.
The problems starts when I make an artifact of the application and running it without intellij.
Here is my demo command:
@ShellComponent
public class MyCommands {
private final EntityManager entityManager;
@Autowired
public MyCommands(EntityManager manager) {
this.entityManager = manager;
}
@ShellMethod(value = "Add two integers together", key = "find")
public String find(int id) {
Customer customer = entityManager.find(Customer.class, id);
String res = "";
if(customer != null) {
// logic
} else {
// logic
}
return res;
}
}
Project structure:
My artifact setup:
Config:
@Configuration
public class Config {
@Bean
public EntityManagerFactory entityManagerFactory() {
return Persistence.createEntityManagerFactory("pu");
}
@Bean
public EntityManager entityManager(EntityManagerFactory emf) {
return emf.createEntityManager();
}
}
Application:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
The log:
16:47:46.312 [main] ERROR org.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'standardParameterResolver' defined in class path resource [org/springframework/shell/standard/StandardAPIAutoConfiguration.class]: Unsatisfied dependency expressed through method 'standardParameterResolver' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.core.convert.ConversionService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value="spring-shell")}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:769)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1313)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
at com.example.demo.DemoApplication.main(DemoApplication.java:14)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.core.convert.ConversionService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value="spring-shell")}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1790)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
... 19 common frames omitted
Thank you!
You need to use something to package your dependencies into the jar with your code or you need to manually add the dependencies to the classpath at execution. This usually involves something like maven's shade plugin or gradle's shadow plugin.
See How can I create an executable JAR with dependencies using Maven?
This can also be done within intellij but its usually a bad idea to make an ide your build tool.
https://blog.karthicr.com/posts/2016/07/10/creating-an-executable-jar-in-intellij-idea/