Strange NoSuchBeanDefinitionException in Spring - java

I get a classic org.springframework.beans.factory.BeanCreationException:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Server': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private MyClass Server.myClass; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [MyClass] 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:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at root.package.Application.main(Application.java:14)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private MyClass Server.myClass; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [MyClass] 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:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 12 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [MyClass] 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:1373)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
... 14 more
"MyClass" in the stack trace above is of course the FQN of my class, which I replaced in this case (I can't show my package). It's a simple Netty Handler:
#Service
public class MyClass extends SimpleChannelInboundHandler<Protocol> implements Visitor {
#Autowired
private RestTemplate restTemplate;
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Protocol protocol) throws Exception {
channelHandlerContext.writeAndFlush(protocol.accept(this, channelHandlerContext));
}
public Object visit(Protocol protocol, ChannelHandlerContext channelHandlerContext) {
return restTemplate.exchange(...);
}
}
The class that depends on MyClass:
#Component
public class Server {
#Autowired
private MyClass myClass;
private ChannelFuture serverChannelFuture;
#PostConstruct
public void start() throws Exception {
serverChannelFuture = bootstrap().bind(tcpPort()).sync();
}
#PreDestroy
public void stop() throws Exception {
serverChannelFuture.channel().close();
serverChannelFuture.channel().closeFuture().sync();
}
private ServerBootstrap bootstrap() {
// Bootstrap setup
}
}
And my configuration:
#Configuration
#ComponentScan("root.package")
public class SpringConfig {
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
#Bean
public Logger logger() {
return Logger.getLogger(InternalLoggerFactory.class.toString());
}
}
All my classes are in either root.package or a subpackage of it. MyClass is in a subpackage as well.
I have no idea why this would cause the above Exception. I have other Services in my root.package package that are being autowired just fine! Does any one have an idea?
EDIT: after some further testing, it appears the "visit" method is the problem. If I rename it, the application boots fine. Could this be a bug in Spring?
EDIT 2: I celebrated too early. I renamed the method in my Visitor interface and now I'm back to the same problem. Even if I comment out my interface, I cannot have any method with the same name as that interface. MyClass is the only class that implements Visitor that is a Spring bean.

Your class MyClass has no package name?
"No qualifying bean of type [MyClass]"
in your Configuration you set the componentscan to a specififc package
#ComponentScan("root.package")
so Spring could not found your beans.
to fix: remove ("root.package") or add the package "root.package" to your classes

The thing about Spring annotations is that classes must reside in the same package tree as the runner or context.
For example, if your Spring application class is in com.dippity.dot.myapp all other classes annotated as #Service, #Component, etc must also be down the com.dippity.dot.myapp package tree.
A #Service annotated package could live com.dippity.dot.myapp.service and work.

This answer set me on my way: Spring instantiates bean but can't use it
The problem was that I use Spring aspects as well, which are configured with
#EnableAspectJAutoProxy
However, by default, this enables JDK proxies, which work differently (see the answer of that question for more info).
#EnableAspectJAutoProxy(proxyTargetClass=true)
Enables CGLIB proxies, which was the solution to my problem.

Related

Injection of autowired dependencies failed inside a jar file

I have put a jar file under lib folder of my war file. Inside the jar I have some classes with #Autowired fileds. Inside the jar , in the applicationContext xml I have given
<context:component-scan base-package="com.main.java.mypath" />
Code:
package com.main.java.mypath.client;
#Component
public class ServiceProvider {
#Autowired
private StoreField storeField;
package com.main.java.mypath.data;
public interface StoreField {
}
Error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serviceProvider': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.main.java.mypath.data.StoreField com.main.java.mypath.client.ServiceProvider.storeField; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.main.java.mypath.data.StoreField] 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)}
It is not possible to inject the dependency as long as you don't have the implementation for your StoreField interface. Make sure that it is implemented as a class and properly initialized in spring context via xml or annotation.

Injecting properties in Spring using CDI fails due BeanCreationException

I am trying to inject properties file into my spring component using CdI and keeps throwing the exception below.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'validationService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.Properties ValidationService.ProjectProperties; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.util.Properties] 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), #PropertiesFromFile(value=config.properties)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
Here is my code:
#Component
public class ValidationService {
#Autowired
#PropertiesFromFile("config.properties")
private Properties configProperties;
#Autowired
#PropertiesFromFile("custom.properties")
private Properties customProperties;
}
Another piece of code that I tried was:
#Component
public class ValidationService {
#Inject
#PropertiesFromFile("config.properties")
private Properties configProperties;
#Inject
#PropertiesFromFile("custom.properties")
private Properties customProperties;
}
Although Spring now supports Inject under AutoWired I still tried both.
I am new to Spring, I would really appreciate if someone could point me to the right direction
P.S. The code for the Generic annotation can be found here:
http://slackspace.de/articles/injecting-properties-in-java-ee-applications/

Autowiring Embedded Elastic with Spring

I'm trying to build a rest api with Spring and Embedded Elastic. I'm getting an NoSuchBeanDefinitionException when trying to start my application.
Currently, I have this for wiring the elastic db:
#Configuration
public class EsConfig {
Node node;
#Bean
public Client es() {
node = nodeBuilder().local(true).node();
return node.client();
}
(Destructor)
}
and in the controller:
#RestController
public class Controller {
#Autowired
public Client elasticSearchClient;
...
}
But when I start it up, I get this exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'controller': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public org.elasticsearch.client.Client package.Controller.elasticSearchClient;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.elasticsearch.client.Client] 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)}
I've tried a few different annotations but I'm obviously way off.
No qualifying bean of type [some.Thing] means that spring knowns no class that is applicable for this interface.
Reasons for that can be
The class that has the #Bean method is not a #Configuration class
The #Configuration class is not picked up by the classpath component scanner.
Spring boot by default will only scan the child package hierarchy of the #SpringBootApplication. If you want to include code outside of that you can change the scanning behavior via the #ComponentScan annotation.
#SpringBootApplication
#ComponentScan(basePackageClasses = {MyApp.class, SomeOtherClassInARootPackage.class})
public class MyApp {
...
Would add the package (and sub packages) of some other class, while keeping the packages of the application scanned as well.

Spring autowiring dillema when using injection by both interface and implementation

Consider we have interface CountryService, which has one implementation: CountryServiceImpl which is annotated with #Service
We also have ITTest for CountryImpl.
The problem:
Frequently when running tests we want to explicitly show what we are testing so we are autowiring by implementation, so we create ITTest:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = Application.class, loader = SpringApplicationContextLoader.class)
#ActiveProfiles(ProfileConstants.SPRING_PROFILE_DEVELOPMENT)
public class CountryServiceITTest {
#Autowired
CountryServiceImpl countryServiceImpl;
#Test
public void test() {
countryServiceImpl.getAllCountriesTranslationsInLanguage("en");
}
So far so good. We run our test and it is green. Now lets make life little more fun.
We add a CountryResource with CountryResourceImpl #RestController which #Autowire (s) CountryService.
We run our test again and suddenly we receive error message causing maddness:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'countryResourceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com....service.CountryService com....rest.CountryResourceImpl.countryService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com....service.CountryService] 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)}
This behavior reveals an interesting thing:
Once we autowire by interface, we can't autowire by direct implementation somewhere else. This works vice versa(if we autowire by impl the interface injection will fail).
Please explain why is this happening?

#ComponentScan and #Autowired fail to inject from a specific package

I am aware of the many similar questions about this issue on SO, however, non of them solved my problem. I have a Spring REST project and I am using Spring Tool Suite (STS) 3.5.1 RELEASE.
The application class:
package com.example.rest;
#ComponentScan({"com.example.repositories", "com.example.config", "com.example.services", "com.example.rest", "com.example.jms"})
#EnableAutoConfiguration
public class Application
{
... //declaring some beans for JMS
}
The repository class:
package com.example.repositories;
#Repository
public interface ActorRepository extends MongoRepository<Actor, String>
{
public Actor findByFNameAndLName(String fName, String lName);
public Actor findByFName (String fName);
public Actor findByLName(String lName);
}
The Service class (Autowire fails here to inject actorRepository):
package com.example.services;
#Service
public class ActorService
{
#Autowired
private ActorRepository actorRepository;
....
}
The REST service (Autowired fails to inject actorService -I assume it is because ActorService failed to inject ActorRepository):
package com.example.rest;
#RestController
#RequestMapping("/actors")
public class ActorRESTService
{
private static final Logger logger = Logger.getLogger(ActorRESTService.class);
#Autowired
private ActorService actorService;
....
}
The reason I believe it is happening because #ComponentScan is not scanning the repositories package is that in STS, Spring classes have a little S on the right top corner of thier Java icon. And this appears on all classes that should be scanned (the componenets except for anything in the repositories package). Moving the repository classes to the rest package makes them scanned (No Idea why!).
This is part of the excpetion I get when I try to run the project using Spring Boot App.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'actorService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.repositories.ActorRepository com.example.services.ActorService.actorRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.repositories.ActorRepository] 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:1185)
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:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
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:120)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:683)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:944)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:933)
at com.example.rest.Application.main(Application.java:94)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.repositories.ActorRepository com.example.services.ActorService.actorRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.repositories.ActorRepository] 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)
... 16 common frames omitted
.....
The Repositories have to be in the same packaege or a sub-package of the main(Application) class. This is the default behavior in spring boot. To keep things clean you can also put the repos in a sub package, like com.example.rest.repo in your case. Or as M. Deinum sugested you can put the main class in the base package so that spring can handle that automaticaly.

Categories

Resources