Injecting properties in Spring using CDI fails due BeanCreationException - java

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/

Related

Spring: Map could not Autowire issue

#Component
public class BankServicesImpl implements BankServices {
#Autowired
private DataRepoImpl db;
}
----------------------------------------------------------------------------
#Component
public class DataRepoImpl implements DataRepo{
private Map<Integer, Account> repo = new HashMap<Integer,Account>();
}
----------------------------------------------------------------------------
#Component
public class Account {
private Integer accountID;
private int balance;
}
The codes do the job, the repo HashMap object is created ( {} ). Yet i am trying to get the repo Map object to be generated by Spring. so i changed the DataRepoImpl into:
#Component
public class DataRepoImpl implements DataRepo{
#Autowired
private Map<Integer, Account> repo;
}
Error:
Nov 08, 2021 11:37:06 PM org.springframework.context.support.AbstractApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataRepoImpl': Unsatisfied dependency expressed through field 'repo'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.Map<java.lang.Integer, com.doubleliu.model.Account>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataRepoImpl': Unsatisfied dependency expressed through field 'repo'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.Map<java.lang.Integer, com.doubleliu.model.Account>' 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 'java.util.Map<java.lang.Integer, com.doubleliu.model.Account>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
However, when i refactor accountID and Map key into String type,
i able to produce the HashMap containing a 'dummy' variable which is weird:
{account=com.doubleliu.model.Account#397fbdb}
Back to Integer, I couldnt fix the error, I then tried to move the Autowired to the empty constructor of the DataRepoImpl class:
#Autowired
public DataRepoImpl() {
}
However i get null value from repo, since (my assumption) the object hasnt been created or assigned to the repo Map variable.
Again, i then move the Autowired onto the constructor with map as the parameter:
#Autowired
public DataRepoImpl(Map<Integer, Account> repo) {
this.repo = repo;
}
This time the repo object is created ( {} ) and not null, i assume that the object is created through the parameter, is this the right way to create it utilizing spring? also my IDE flag me with an error of
Could not autowire. No beans of 'Map<Integer, Account>' type found. but i can still compile it. i wonder how to fix it.. fyi, I am using IntelliJ IDEA
I just started learning spring for a bit, trying to completely understand before i go to the next level. so any response, solutions, comments, advice to the code, fix, and issue is very pleased especially with the autowired.
Thank you.
EDIT: i am using xml annotation based configuration
Related to here
I just found out that i need to define the properties of the defined bean in the xml. everytime i define something like HashMap, add following to the xml and it enables me to inject the just defined Map bean by defining #Resource on the Map variable inside the class.
<util:map id="repo" scope="prototype" map-class="java.util.HashMap"
key-type="java.lang.String" value-type="com.doubleliu.model.Account"/>
Thank you for the help and comments, any more comments and advices are welcomed.

Spring - No default constructor found

I have a class which looks like this:
#Service("myService")
public class MyServiceImpl {
#Autowired
private SimpMessagingTemplate simpMessagingTemplate;
and I also have a test class which looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {
MyServiceImpl.class})
...
I get this exception:
Injection of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not autowire
field: private org.springframework.messaging.simp.SimpMessagingTemplate
myPackage.MyServiceImpl.simpMessagingTemplate; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.messaging.simp.SimpMessagingTemplate] 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)}
Does anyone know what I can do in order to get it work, SimpMessagingTemplate does not have a default constructor.
SimpMessagingTemplate seems to have either no default constructor or is not annotated with #Component (or #Service or another sub-class of #Component); or both.
Please check that a default constructor is available and the class is configured to be a Spring bean.
Its not related to missing constructor, but Spring fails to find proper bean to inject into your test class,
Two options to solve it as I see
#ContextConfiguration(classes = {
MyServiceImpl.class, SimpMessagingTemplate.class})
Add #mock SimpMessagingTemplate simpMessagingTemplate; to your test class

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.

Strange NoSuchBeanDefinitionException in Spring

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.

#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