Error to inject some dependency with kotlin + quarkus - quarkus

I want to include a dependency in my Kotlin Resource file. But I cant.
I made this tutorial: https://quarkus.io/guides/rest-client-guide
But, to start the project, I've included extension "kotlin" in my project.
My codes below:
Country.kt
package org.acme.restclient
class Country {
var name:String? = null
var alpha2Code:String? = null
var capital:String? = null
var currencies:List<Currency>? = null
class Currency {
var code:String? = null
var name:String?= null
var symbol:String? = null
}
}
CountriesService.kt
package org.acme.restclient
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.PathParam
import javax.ws.rs.Produces
#Path("/v2")
#RegisterRestClient
interface CountriesService {
#GET
#Path("/name/{name}")
#Produces("application/json")
fun getByName(#PathParam("name") name: String): Set<Country>
}
CountriesResource.kt
package org.acme.restclient
import org.eclipse.microprofile.rest.client.inject.RestClient
import javax.inject.Inject
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.PathParam
import javax.ws.rs.Produces
import javax.ws.rs.core.MediaType
#Path("/country")
class CountriesResource {
#Inject
#RestClient
lateinit internal var countriesService: CountriesService
#GET
#Path("/name/{name}")
#Produces(MediaType.APPLICATION_JSON)
fun name(#PathParam("name") name: String): Set<Country> {
return countriesService.getByName(name)
}
}
application.properties
org.acme.restclient.CountriesService/mp-rest/url=https://restcountries.eu/rest
The error:
12:23:55,340 ERROR [io.qua.dev.DevModeMain] Failed to start quarkus: java.lang.RuntimeException: org.jboss.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.arc.deployment.ArcAnnotationProcessor#build threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.restclient.CountriesService and qualifiers [#Default]
- java member: org.acme.restclient.CountriesResource#countriesService
- declared on CLASS bean [types=[org.acme.restclient.CountriesResource, java.lang.Object], qualifiers=[#Default, #Any], target=org.acme.restclient.CountriesResource]
at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:134)
at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:105)
at io.quarkus.dev.DevModeMain.main(DevModeMain.java:66)
Caused by: org.jboss.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.arc.deployment.ArcAnnotationProcessor#build threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.restclient.CountriesService and qualifiers [#Default]
- java member: org.acme.restclient.CountriesResource#countriesService
- declared on CLASS bean [types=[org.acme.restclient.CountriesResource, java.lang.Object], qualifiers=[#Default, #Any], target=org.acme.restclient.CountriesResource]
at org.jboss.builder.Execution.run(Execution.java:123)
at org.jboss.builder.BuildExecutionBuilder.execute(BuildExecutionBuilder.java:136)
at io.quarkus.deployment.QuarkusAugmentor.run(QuarkusAugmentor.java:110)
at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:99)
... 2 more
Caused by: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.restclient.CountriesService and qualifiers [#Default]
- java member: org.acme.restclient.CountriesResource#countriesService
- declared on CLASS bean [types=[org.acme.restclient.CountriesResource, java.lang.Object], qualifiers=[#Default, #Any], target=org.acme.restclient.CountriesResource]
at io.quarkus.arc.processor.BeanDeployment.processErrors(BeanDeployment.java:740)
at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:276)
at io.quarkus.arc.processor.BeanProcessor.process(BeanProcessor.java:153)
at io.quarkus.arc.deployment.ArcAnnotationProcessor.build(ArcAnnotationProcessor.java:237)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.quarkus.deployment.ExtensionLoader$1.execute(ExtensionLoader.java:506)
at org.jboss.builder.BuildContext.run(BuildContext.java:413)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1998)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1525)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1416)
at java.base/java.lang.Thread.run(Thread.java:834)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.acme.restclient.CountriesService and qualifiers [#Default]
- java member: org.acme.restclient.CountriesResource#countriesService
- declared on CLASS bean [types=[org.acme.restclient.CountriesResource, java.lang.Object], qualifiers=[#Default, #Any], target=org.acme.restclient.CountriesResource]
at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:326)
at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:365)
at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:268)
... 14 more
Someone can help me?
Thanks!

This problem results as a combination of how Kotlin handles annotations and the lack of the a #Target on the #RestClient annotation definition.
To fix your problem, simply use:
#Inject
#field: RestClient
lateinit internal var countriesService: CountriesService

Related

JUnit #DataJpaTest org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name

I'm trying to do a test on the repository using #DataJPATest but #Autowired is not working
I already tried looking for examples of junit5 with #DataJpaTest, but I didn't find it
I tried adding other dependencies, I used #SpringTest and it worked, but I wanted to use #DataJpaTest
package com.projetoSpring.catalog.repositories;
import com.projetoSpring.catalog.model.Product;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import java.util.Optional;
#DataJpaTest
public class ProductRepositoryTests {
#Autowired
private ProductRepository repositorys;
#Test
public void deleteShouldDeleteObjectWhenIdExists() {
long exintingId = 1L;
repositorys.deleteById(exintingId);
Optional<Product> result = repositorys.findById(1L);
Assertions.assertFalse(result.isPresent());
}
}
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.projetoSpring.catalog.repositories.ProductRepositoryTests': Unsatisfied dependency expressed through field 'repositorys'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.projetoSpring.catalog.repositories.ProductRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I managed to solve it, I updated spring to version 2.7.5 and I verified that the test dependency was not downloading correctly, I redid the pom.xml and it worked.

Component Scan with both including package and excluding a class is not working SpringBoot

I am trying to scan a package com.training and want to exclude a specific class(SDIAuthorizerConfig.java) from scanning in componenet scan but it doesnt seems like working
package com.training.execution.tom.action;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import com.training.foundation.core.application.SDIServiceApplication;
import com.training.foundation.core.authorizer.config.SDIAuthorizerConfig;
import org.springframework.context.annotation.FilterType;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
#SpringBootApplication
#ComponentScan(basePackages = "com.training",excludeFilters = #Filter(type= FilterType.ASSIGNABLE_TYPE, value=SDIAuthorizerConfig.class))
#EnableGlobalMethodSecurity(securedEnabled = true)
#EnableEurekaClient
#EnableAutoConfiguration
public class TOMActionServiceApplication extends SDIServiceApplication{
public static void main(String[] args) {
SpringApplication.run(TOMActionServiceApplication.class, args);
}
}
And getting this below error while starting the application in tomcat
Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'SDIAuthorizerFilter': Unsatisfied dependency expressed through field 'authorizer'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'SDILDAPAuthorizer': Unsatisfied dependency expressed through field 'populator';
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'SDIAuthorizerConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'sdi.ldap.url' in value "${sdi.ldap.url}"
the above property is being referenced inside SDIAuthorizerConfig class which I don't want my component scan to include so I have used the below but it still being scanned.
#ComponentScan(basePackages = "com.training",excludeFilters = #Filter(type= FilterType.ASSIGNABLE_TYPE, value=SDIAuthorizerConfig.class))

Startup error in Spring Cloud Stream after upgrading to Spring Boot 2.6.1 and Spring Cloud 2021.0.0

I just upgraded a Spring Boot application that uses Spring Cloud Stream Kafka producers and consumers to
plugins {
id("org.springframework.boot") version "2.6.1"
...
}
extra["springCloudVersion"] = "2021.0.0"
extra["springCloudStreamVersion"] = "3.2.1"
The applications doesn't start anymore with the following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'functionInitializer' defined in class path resource [org/springframework/cloud/stream/function/FunctionConfiguration.class]: Invocation of init method failed; nested exception is java.lang.ClassCastException: class reactor.core.publisher.MonoPeekTerminal cannot be cast to class reactor.core.publisher.Flux (reactor.core.publisher.MonoPeekTerminal and reactor.core.publisher.Flux are in unnamed module of loader 'app')
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804)
...
Caused by: java.lang.ClassCastException: class reactor.core.publisher.MonoPeekTerminal cannot be cast to class reactor.core.publisher.Flux (reactor.core.publisher.MonoPeekTerminal and reactor.core.publisher.Flux are in unnamed module of loader 'app')
at org.springframework.cloud.sleuth.instrument.messaging.TraceFunctionAroundWrapper.reactorFluxStream(TraceFunctionAroundWrapper.java:187)
at org.springframework.cloud.sleuth.instrument.messaging.TraceFunctionAroundWrapper.reactorStream(TraceFunctionAroundWrapper.java:120)
at org.springframework.cloud.sleuth.instrument.messaging.TraceFunctionAroundWrapper.doApply(TraceFunctionAroundWrapper.java:97)
at org.springframework.cloud.function.context.catalog.FunctionAroundWrapper.apply(FunctionAroundWrapper.java:47)
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$1.doApply(SimpleFunctionRegistry.java:256)
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.apply(SimpleFunctionRegistry.java:550)
at org.springframework.cloud.stream.function.FunctionConfiguration$FunctionToDestinationBinder.bindFunctionToDestinations(FunctionConfiguration.java:512)
at org.springframework.cloud.stream.function.FunctionConfiguration$FunctionToDestinationBinder.afterPropertiesSet(FunctionConfiguration.java:418)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800)
... 16 common frames omitted
Did I miss any upgrade guide or is it a bug?
Producer
#Component
class EventProducer(#Qualifier("eventSink") private val eventProcessor: Sinks.Many<Message<EventReceived>>) {
private val logger = LoggerFactory.getLogger(javaClass)
fun send(event: EventReceived): Mono<EventReceived> {
return Mono.defer {
val message = MessageBuilder.withPayload(event)
.setHeader(MESSAGE_KEY, event.id)
.setHeader(TIMESTAMP, OffsetDateTime.now().toInstant().toEpochMilli())
.build()
logger.info("Sending event {}", event)
while (eventProcessor.tryEmitNext(message).isFailure) {
LockSupport.parkNanos(10)
}
event.toMono()
}.subscribeOn(Schedulers.boundedElastic())
}
Consumer
#Configuration
class MetricConsumer(...) {
private val logger = LoggerFactory.getLogger(javaClass)
#Bean
fun consumeMetricUpdated(): Function<Flux<Message<MetricUpdated>>, Mono<Void>> {
...
}
This looks like a bug in s-c-sleuth. I'll follow up with Marcin about this.
Can you please post the signature of your function as well, need to confirm something?
Meanwhile, you can temporarily disconnect sleuth's TraceFunctionAroundWrapper by setting spring.sleuth.function.enabled to false.

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.

NoSuchBeanDefinitionException when the package is changed from hello to foo.

I can get the spring boot example program working successfully when I follow the instructions available at https://spring.io/guides/gs/spring-boot/.
If I add HelloService and HelloServiceImpl, code shown below, to hello package and change HelloController.java to call sayHello method, it works as expected and from http://localhost:8080, I see the message shown below, as expected.
Greetings from Spring Boot! helloService = Hello from HelloServiceImpl
Now, if I move HelloService and HelloServiceImpl to foo package, then after compilation when I run it, I get the error shown below.
Why the spring boot/framework is not able to pick up the needed beans from 'foo' package? I am able to verify it can pick up the bean successfully from hello package, though.
Thanks,
cat HelloService.java
package hello;
public interface HelloService {
public String sayHello();
}
cat HelloServiceImpl.java
package hello;
import org.springframework.stereotype.Service;
#Service("helloService")
public class HelloServiceImpl implements HelloService {
/* (non-Javadoc)
* #see com.apress.prospring3.springblog.service.HelloService#sayHello()
*/
#Override
public String sayHello() {
return "Hello from HelloServiceImpl ";
}
}
In HelloController.java, change return statement in the index method as shown below, so that the hello service is invoked.
cat HelloController.java
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class HelloController {
#Autowired
private HelloService helloService;
#RequestMapping("/")
public String index() {
return "Greetings from Spring Boot! helloService = " + helloService.sayHello();
}
}
When I run the command shown below, there are no errors.
$ java -jar target/gs-spring-boot-0.1.0.jar
$ java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)
$ which java
/usr/bin/java
$ ls -lt /usr/bin/java
lrwxr-xr-x 1 root wheel 74 Mar 9 22:00 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
If I move HelloService.java and HelloServiceImpl.java to foo package from hello package and no other change, I get the error below when I try to run it. Why it is not able to pick up from 'foo' package when it can do it successfully from hello package? How to fix this issue? Does it mean these two classes must reside in hello package only for it to work?
Thx,
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private foo.HelloService hello.HelloController.helloService; nested exception is org.springframework.beans.factory.**NoSuchBeanDefinitionException**: No qualifying bean of type [foo.HelloService] 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)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1180)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:296)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:660)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:552)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:293)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:749)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:738)
at hello.Application.main(Application.java:17)
... 6 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private foo.HelloService hello.HelloController.helloService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [foo.HelloService] 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)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
... 22 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [foo.HelloService] 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)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1060)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:920)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:815)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 24 more
Initially when HelloService is in hello package, #ComponentScan on the Configuration class tells Spring to look for other components, configurations, and services in the the hello package, allowing it to find this class.
Now since you have moved HelloService to foo package, #ComponentScan cannot find it any more; you need to specify the new package name as well like:
#ComponentScan({"hello","foo"})

Resources