converting a simple maven project to a spring boot project from maven - maven

use eclipse,I new a maven project.
After,I replace pom to the spring boot pom and create counter java file.
But when I run this application,it went error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.yao.service.PersonInfoRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 31 more
I think this maybe coused by some config,but I don't know what config to.
Supplement: When I Generate the demo project from here, the same code is run normal.
This is my main class:
#ComponentScan(basePackages = { "com.yao" })
#SpringBootApplication
public class StartApplication {
public static void main(String[] args) {
SpringApplication.run(StartApplication.class, args);
}
}

Related

Spring #Service defined in Kotlin file results in 'UnsatisfiedDependencyException: Error creating bean' when referenced

I have an existing Springboot/Java application and I wanted to start migrating the application to Kotlin. I create a #Service in Kotlin, and my unit test fails at runtime because Spring can't find my service.
My unit test:
#ExtendWith(SpringExtension::class)
#SpringBootTest(classes = arrayOf(Application::class))
class Junit5SpringKotlinTests {
#Autowired // Springboot ConfigurationProperties (application.yaml) mapped to Java bean. This works.
lateinit var applicationConfigurationJavaBean: EnvironmentProperties
fun appProperties(): EnvironmentProperties.Environment? {
return applicationConfigurationJavaBean.environments[applicationConfigurationJavaBean.activeEnvironment]
}
#Autowired
lateinit var testServiceKotlinBean :TestService // My Kotlin #Service which can not be found at runtime.
#Test
fun `ApplicationConfiguration`() {
println(appProperties()?.baseClientId)
testServiceKotlinBean.hello()
}
}
My Kotlin service: TestService.kt
import org.springframework.stereotype.Service
#Service
class TestService {
fun hello() {
println("hello from service")
}
}
My error at runtime executing the unit test:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'Junit5SpringKotlinTests': Unsatisfied dependency expressed through field 'testServiceKotlinBean'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'api.model.TestService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'api.model.TestService' 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:1509)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
FWW, I am able to write JUnit5 SpringBootTests in Kotlin test code and exercise all my Java components, so this has something to do with Kotlin components being discovered at runtime by Spring. Java components work.
I suspected this might be a build problem and have seen similar issues. I have the following included in my pom.xml:
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin.version}</version>
</dependency>
so that wasn't the problem.
The problem was the package name I used for the Kotlin service. Kotlin is nice in that I don't have put my files in the same package path like java. But my Spring classpath scanning was relying on a package: A.B.C and below and my Kotlin path only had C. I changed the package name in my Kotlin file to be A.B.C.TestService and all is fine. Yay.

Spring JPA not implementing/autowiring repository despite #EnableJpaRepositories annotation

I'm getting an exception when I start my application, where Spring complain about UnsatisfiedDependencyException:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'applicationConfig': Unsatisfied dependency expressed through field 'controlRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean found for dependency [com.oak.api.finance.repository.ControlRepository]: 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.inject(AutowiredAnnotationBeanPostProcessor.java:569)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
My application is organized in this format:
I declared my repository interfaces, with the proper Spring JPA annotations:
#RepositoryRestResource(collectionResourceRel = "exchange", path = "exchanges")
public interface ControlRepository extends PagingAndSortingRepository<Control, Long> {
}
I annotated the EntryPoint class that contains the main method
#SpringBootApplication
#EntityScan(basePackages = {"com.oak.api.finance.model.dto"})
#EnableJpaRepositories(basePackages = {"com.oak.api.finance.repository"})
public class EntryPoint {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(EntryPoint.class);
logger.info("Starting application");
ApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class);
// SpringApplication.run(EntryPoint.class, args);
ctx.getBean(ApplicationServer.class).start();
}
I used #Autowired to inject my repository into my spring config (java based) ApplicationConfig class:
#Autowired
private ControlRepository controlRepository;
#Autowired
private CompanyRepository companyRepository;
#Autowired
private SectorRepository sectorRepository;
Essentially I want to control the dependency on Spring and limit it to a couple of packages, (the repositories, the java config, and the program entry point - EntryPoint)
I assumed that, by specifying #EnableJpaRepositories with the package where my repositories are located, spring would create a proxy for my repository and instantiate an instance of that, and that by the time I call :
ApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class)
The repositories instances would be present in the beans poole and would be possible to autowire them into my ApplicationConfig context, and then inject them into my controller.
This is clearly not happening, and Spring is complaining about the missing Bean to autowire, but I'm not sure what am I missing.
Below a snapshot of my packages:
any ideas?
My guess is your repositories are not being scanned, so as a result beans are not getting created. Can you try removing these 2 annotations
#EntityScan(basePackages = {"com.oak.api.finance.model.dto"})
#EnableJpaRepositories(basePackages = {"com.oak.api.finance.repository"})
And keep only #SpringBootApplication. If this is not working, you might need to check the package structure (if possible paste a screenshot here)
Edit 1
replace #SpringBootApplication with
#Configuration
#EnableAutoConfiguration
#ComponentScan("com.oak")
Edit2
Use
new SpringApplicationBuilder()
.sources(SpringBootApp.class)
.web(false)
.run(args);
Or use CommandLineRunner after changing ComponentScan path to "com.oak" as mh-dev suggested

spring retry unit test

I am using spring retry (http://docs.spring.io/spring-retry/docs/1.1.2.RELEASE/apidocs/) in a maven project and I have the following unit test
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class RetriableFileManagerTest {
#Autowired
#Qualifier("asset")
private AssetResource assetResource;
#Test
public void testRetry() throws URISyntaxException {
byte[] image = this.assetResource.fetchResource("name", "path");
verify(assetResource, times(3)).fetchResource("name", "path");
Assert.assertEquals("should be equal", "image", new String(image));
}
#Configuration
#EnableRetry
public static class SpringConfig {
#Bean(name = "asset")
public AssetResource assetResource() throws Exception {
AssetResource remoteService = mock(AssetResource.class);
when(remoteService.fetchResource(anyString(), anyString()))
.thenThrow(new RuntimeException("Remote Exception 1"))
.thenThrow(new RuntimeException("Remote Exception 2"))
.thenReturn("Completed".getBytes());
return remoteService;
}
}
}
However when I try to run the test it fails with
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ctp.cms.actions.handlers.repository.resources.AssetResource ctp.cms.actions.handlers.filemanager.RetriableFileManagerTest.assetResource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [ctp.cms.actions.handlers.repository.resources.AssetResource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=asset)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 25 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [ctp.cms.actions.handlers.repository.resources.AssetResource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=asset)}
Finally figured out the issue, I had to move the #Retryable annotation to the interface that AssetResource implements and autowire this interface type to the unit test.
Error message says
No qualifying bean of type
[ctp.cms.actions.handlers.repository.resources.AssetResource] found
for dependency
How is ctp.cms.actions.handlers.repository.resources.AssetResource declared?
Do you have #Component (#Service or similar annotation on it?) Is this package enabled for #ComponentScan ?

spring boot repository metrics

I am trying to make an object repositoryMetrics in SpringBoot and later I obtained information with this repository. But I create a repository and this always is null.
How I generate a repository and this save the metrics?
I have this code:
public static void stateSist() throws Exception {
InMemoryMetricRepository metricRepository = null;
metricRepository.findAll();
System.out.println(metricRepository.count());
}
EDIT 1:
I do this change in my version and I obtained this error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'actuatorMetricsPrinter' defined in file [ActuatorMetricsPrinter.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.util.Collection]: : No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1115)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
at hello.Application.main(Application.java:14)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.actuate.endpoint.PublicMetrics] found for dependency [collection of org.springframework.boot.actuate.endpoint.PublicMetrics]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1118)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:919)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739)
... 18 common frames omitted
Thank you!
In order to access all Public Metrics printed by the Spring Boot actuator framework you need to inject a 'Collection' into your component and then access it to read all the metrics. Here is an example:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.PublicMetrics;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.stereotype.Component;
import java.util.Collection;
#Component
public class ActuatorMetricsPrinter {
private static final String TEMPLATE = "Metric: %s [%s]";
private final Collection<PublicMetrics> publicMetrics;
#Autowired
public ActuatorMetricsPrinter(Collection<PublicMetrics> publicMetrics) {
this.publicMetrics = publicMetrics;
}
public String printAllMetrics() {
StringBuilder sb = new StringBuilder();
for (PublicMetrics pm : publicMetrics) {
sb.append("Public Metric: " + pm.getClass().getName());
sb.append("\n\n");
for (Metric<?> m : pm.metrics()) {
sb.append(String.format(TEMPLATE, m.getName(), m.getValue().toString()));
sb.append("\n");
}
}
return sb.toString();
}
}
If you want to reproduce this simple scenario, then:
Go to http://start.spring.io/ and create new project with Actuator and Web checked,
Create a demo project with Build tool of your choice (Gradle, Maven),
Download it and open in your IDE,
Create a new component just like one in my example,
Create a new RestController, like this:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class DummyController {
private final ActuatorMetricsPrinter metricsPrinter;
#Autowired
public DummyController(ActuatorMetricsPrinter metricsPrinter) {
this.metricsPrinter = metricsPrinter;
}
#RequestMapping(value = "/customMetrics", method = RequestMethod.GET)
public String printMetrics() {
return metricsPrinter.printAllMetrics();
}
}
Then start the application and type in your browser: http://localhost:8080/customMetrics
You should see all the metrics printed by your class in the most messy way possible
If you are using Maven or Gradle for dependency management, then you must make sure these are present in either (from Spring Clouds's Home Page):
Maven:
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>Angel.SR4</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
</dependencies>
Gradle:
buildscript {
dependencies {
classpath "io.spring.gradle:dependency-management-plugin:0.4.0.RELEASE"
}
}
apply plugin: "io.spring.dependency-management"
dependencyManagement {
imports {
mavenBom 'org.springframework.cloud:spring-cloud-starter-parent:Angel.SR4'
}
}
dependencies {
compile 'org.springframework.cloud:spring-cloud-starter-config'
compile 'org.springframework.cloud:spring-cloud-starter-eureka'
}
If you omit the parent in Maven or the dependencyManagement in gradle, and try to just import the latest version of each of the dependencies, you will get the runtime error that you are describing.
A similar problem addresses this here on GitHub.

Spring-boot with Liquibase Overloading Property

I am using Spring boot and Liquibase.
Using this url as guidelines
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/
In pom.xml, the below entry is present so that spring boot knows about liquibase.
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
and put the changelog file in resources folder.
db.changelog-master.xml
Now Spring boot first tring to find db.changelog-master.yaml in classpath and throwing the exception like this.
Cannot find changelog location: class path resource [db/changelog/db.changelog-master.yaml
To Fix the Issue, I have added the bean like below in my class and tried to set changeLog proprty.
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class SampleDataJpaApplication {
#Autowired
LiquibaseProperties properties;
#Autowired
private DataSource dataSource;
#Bean
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
properties.setChangeLog("classpath:/db/changelog/db.changelog-master.xml");
liquibase.setChangeLog(this.properties.getChangeLog());
liquibase.setContexts(this.properties.getContexts());
liquibase.setDataSource(this.dataSource);
liquibase.setDefaultSchema(this.properties.getDefaultSchema());
liquibase.setDropFirst(this.properties.isDropFirst());
liquibase.setShouldRun(this.properties.isEnabled());
return liquibase;
}
public static void main(String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger("SampleDataJpaApplication");
SpringApplication springApplication = new SpringApplication();
springApplication.run(SampleDataJpaApplication.class, args);
}
}
but it is failing with the message.
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'sampleDataJpaApplication': Injection of
autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field:
org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties
sample.data.jpa.SampleDataJpaApplication.properties; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties]
found for dependency: expected at least 1 bean which qualifies as
autowire candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Caused by: org.springframework.beans.factory.BeanCreationException:
Could not autowire field:
org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties
sample.data.jpa.SampleDataJpaApplication.properties; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties]
found for dependency: expected at least 1 bean which qualifies as
autowire candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Please provide the inputs here, why i am getting this exception or Is there any any other available way to override the same class so that i can change the changeLog property of liquibase properties.
I'm not entirely sure what the exact runtime path to your change log is, but why don't you just use the "liquibase.*" properties in application.properties? You should be able to leave out the Liquibase #Bean and let Boot do it for you.
If you prefer to add you own Liquibase #Bean then take the hint and make sure you define a LiquibaseProperties bean as well (e.g. by declaring #EnableConfigurationProperties(LiquibaseProperties.class)).

Resources