Injection of autowired dependencies failed - spring

I'm trying to realize the same as in Spring error when trying to manage several classes that share a common base class?
But I'm still getting this Exception:
Error creating bean with name 'com.example.model.CategoryTest': Injection of
autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not autowire
field: private com.example.model.CategoryService
com.example.model.CategoryTest.service; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean
of type [com.example.model.CategoryService] 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)}
Here are my classes in hope someone can help me understanding this autowiring stuff...
public abstract class BaseDAO<E>
{
public abstract void delete( int id );
public abstract void save( E entity );
public abstract List<E> list();
}
public abstract class BaseService<E, D extends BaseDAO<E>>
{
private final D dao;
protected BaseService( D dao )
{
this.dao = dao;
}
#Transactional
public void delete( int id )
{
dao.delete( id );
}
#Transactional
public void save( E entity )
{
dao.save( entity );
}
#Transactional
public List<E> list()
{
return dao.list();
}
}
#Repository
public class CategoryDAO extends BaseDAO<Category>
{
#Autowired
private SessionFactory sessionFactory;
#Override
public void delete( int id )
{
Category category = ( Category ) sessionFactory.getCurrentSession().load( Category.class, id );
if ( category != null )
{
sessionFactory.getCurrentSession().delete( category );
}
}
#Override
public void save( Category category )
{
sessionFactory.getCurrentSession().save( category );
}
#Override
public List<Category> list()
{
return sessionFactory.getCurrentSession().createQuery( "from Category" ).list();
}
}
#Service
public class CategoryService extends BaseService<Category, CategoryDAO>
{
#Autowired
public CategoryService( CategoryDAO dao )
{
super( dao );
}
}
UPDATE
Servlet context does contain this line: <context:component-scan base-package="com.example" />
Test context (I'm using maven) does contain this line: <context:annotation-config />
Replacing <context:annotation-config /> with <context:component-scan base-package="com.example" /> results in this Exception:
org.springframework.beans.factory.BeanCreationException: Could not autowire field:
private com.example.model.CategoryService
com.example.controller.ExampleController.categoryService;
nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating bean
with name 'categoryService' defined in file
[/home/danny/example/target/classes/com/example/model/CategoryService.class]:
Initialization of bean failed; nested exception is
org.springframework.aop.framework.AopConfigException: Could not generate CGLIB
subclass of class [class com.example.model.CategoryService]: Common causes of
this problem include using a final class or a non-visible class; nested exception
is java.lang.IllegalArgumentException: Superclass has no null constructors but no
arguments were given
UPDATE2
I'm still getting this exception, here's my new code (only changed classes):
public abstract class BaseService<E, D extends BaseDAO<E>>
{
private D dao;
/*protected BaseService( D dao )
{
this.dao = dao;
}*/
protected BaseService(){}
protected void setDAO( D dao )
{
this.dao = dao;
}
#Transactional
public void delete( int id )
{
dao.delete( id );
}
#Transactional
public void save( E entity )
{
dao.save( entity );
}
#Transactional
public List<E> list()
{
return dao.list();
}
}
#Service
public class CategoryService extends BaseService<Category, CategoryDAO>
{
#Autowired
public CategoryService( CategoryDAO dao )
{
setDAO( dao );
}
}
UPDATE3
The solution:
public abstract class BaseService<E, D extends BaseDAO<E>>
{
protected D dao;
public BaseService()
{
}
protected D getDao()
{
return dao;
}
#Autowired
protected void setDAO( D dao )
{
this.dao = dao;
}
// ...
}
#Service
public class CategoryService extends BaseService<Category, CategoryDAO>
{
public CategoryService()
{
setDAO( dao );
}
}

It doesn't look like an instance of CategoryService is available for Spring to inject in the dependency into the test. You may be missing the component-scan in your services package - <context:component-scan base-package="..">
Update:
Based on your update, and this post - Error creating bean with name 'org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0' defined in ServletContext resource , it looks like you will have to change your BaseService, to have a setter for dao rather than set using a constructor. CGLIB with Spring AOP may not work well with a non default constructor

You should annotate your classes with #Component at least, for them to be eligible for autowired injection.

Related

Spring: Register a component within a test class

I am registering an ErrorHandler for my Spring Scheduler and would like to test that is is correctly registered in a SpringTest
So far I have tried:
Handler
#Component
public class ScheduledErrorHandler implements ErrorHandler {
#Autowired
private ErrorService errorService;
#Override
public void handleError(final Throwable t) {
errorService.handle(t);
}
}
Registering the Handler
#EnableScheduling
#Configuration
public class SchedulingConfiguration implements SchedulingConfigurer {
#Autowired
private ScheduledErrorHandler handler;
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(1);
scheduler.setErrorHandler(handler);
scheduler.initialize();
taskRegistrar.setScheduler(scheduler);
}
//...
}
Testing it's registered
#ContextConfiguration(classes = {
SchedulerConfiguration.class,
SchedulerErrorHandler.class
})
#RunWith(SpringRunner.class)
public class SchedulerErrorHandlerTest {
#MockBean
private ErrorService service;
#Autowired
private ExampleScheduledJob job;
#Test
public void verifyHandlerGetsCalled() {
// Wait until the job runs
if(!job.latch.await(5, SECONDS)) {
fail("Job never ran");
}
verify(service).handle(any(RuntimeException.class));
}
#Component
public static class ExampleScheduledJob {
private final CountDownLatch latch = new CountDownLatch(1);
#Scheduled(fixedRate=1000)
public void run() {
latch.countDown();
throw new RuntimeException("error");
}
}
}
However when I do this I get a DependencyNotFound error saying Spring cannot create my test class as no Bean named ExampleScheduledJob can be found. How can I register it only for the sake of this test?
Error creating bean with name
'com.example.demo.SchedulerErrorHandlerTest': Unsatisfied dependency
expressed through field 'job'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'com.example.demo.SchedulerErrorHandlerTest$ExampleScheduledJob'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
This should work
#ContextConfiguration(classes = {
SchedulingConfiguration.class,
SchedulerErrorHandlerTest.ExampleScheduledJob.class,
ScheduledErrorHandler.class
})
#RunWith(SpringRunner.class)
You can register your test configuration class (ExampleScheduledJob) as indicated above. Since it is a static inner class, you need to use it like SchedulerErrorHandlerTest.ExampleScheduledJob

Implemetation not found and get a NoSuchBeanDefinitionException

I use spring boot 2 application with spring data jpa and hibernate with postgres
package com.acmor.togy.repository.util.postgres
#Component
public class HStoreParameter implements FormatParameter{
...
}
package com.acmor.togy.repository.util;
public interface FormatParameter {
String format(Map<String, String> properties);
}
package com.acmor.togy.repository.util;
public class AbstractRepository<T, ID> extends SimpleJpaRepository<T, ID> {
private ThreadLocal<Map<String, Object>> parameters = new ThreadLocal<>();
#Autowired
private FormatParameter formatParameter;
public AbstractRepository(JpaEntityInformation entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
}
public AbstractRepository(Class domainClass, EntityManager em) {
super(domainClass, em);
}
}
package com.acmor.togy.repository;
#Repository
public class EnumsRepositoryImpl extends AbstractRepository implements EnumsRepositoryCustom {
}
public interface EnumsRepositoryCustom {
...
}
I created a basic test
#RunWith(SpringRunner.class)
public class EnumsRepositoryCustomTest {
#Autowired
private EnumsRepositoryCustom enumsRepository;
#Test
public void test_advanced_search_using_properties() {
EnumsSearch search = new EnumsSearch();
...
Page<Enums> page = enumsRepository.search(search, PageRequest.of(0, 10));
...
}
}
When I run test I get
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'com.acmor.togy.repository.util.FormatParameter' available: expected
at least 1 bean which qualifies as autowire candidate. Dependency
annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
I have a implementation of FormatParameter, it's HStoreParameter

Error : No qualifying bean found for dependency

I developp a web application with spring mvc 4. for DAO layer, i add a class GenericDAO : `public class GenericDAO {
#PersistenceContext
private EntityManager entityManager;
private Class<T> parametrizedType;
public GenericDAO(Class<T> parametrizedType) {
this.parametrizedType = parametrizedType;
}
public EntityManager getEntityManager() {
return entityManager;
}
public List<T> executeQuery(String query){
TypedQuery<T> typedQuery = entityManager.createQuery(query, parametrizedType);
List<T> result = typedQuery.getResultList();
return result;
}
public List<T> listAll(){
List<T> result = getEntityManager().createQuery("Select t From " + parametrizedType.getSimpleName() + " t", parametrizedType).getResultList();
return result;
}
public T getById(Object id){
return getEntityManager().find(parametrizedType, id);
}
#SuppressWarnings("unchecked")
public List<T> executeNativeQuery(String query){
List<T> result = entityManager.createNativeQuery(query, parametrizedType).getResultList();
return result;
}
public List<T> executeNamedQuery(String query){
List<T> result = entityManager.createNamedQuery(query, parametrizedType).getResultList();
return result;
}
#Transactional
public void save(T entity){
entityManager.persist(entity);
}
#Transactional
public void modify(T entity){
entityManager.merge(entity);
}
#Transactional
public T find(Object id){
if(id!=null){
return entityManager.find(this.parametrizedType, id);
}
return null;
}
#Transactional
public void delete(Object id){
T t = find(id);
if(t!=null){
entityManager.remove(t);
}
}
}`
declaring my DAO like below produce an error durring starting my application :
#Autowired
#Qualifier(value="partenaireDao")
private GenericDAO<VscPartenaire> partenaireDao;
error is :
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean found for dependency ....: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=partenaireDao)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1463)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1094)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
but it s OK with :
#Repository("partenaireDao")
public class PartenaireDao extends GenericDAO {
public PartenaireDao() {
super(VscPartenaire.class);
}
}
can you tell me what its wrong with my first declaration ?
i don't want create dao per entity.
Thanks
can you tell me what its wrong with my first declaration ?
you were not annotated genericDao class,so that class is not instantiated by spring.
i don't want create dao per entity.
then add #Repository("partenaireDao") to GenericDao class.

getting "No qualifying bean of type is defined."

I am getting exception -
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.muztaba.service.VerdictServiceImpl] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:372)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1066)
at com.muztaba.service.App.task(App.java:35)
at com.muztaba.service.App.main(App.java:28)
This is the class from where I am getting there exception.
#Component
public class App {
QueueService<Submission> queue;
Compiler compiler;
VerdictService verdictService;
public static void main( String[] args ) {
new App().task();
}
private void task() {
AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
queue = context.getBean(QueueImpl.class);
compiler = context.getBean(CompilerImpl.class);
verdictService = context.getBean(VerdictServiceImpl.class); //here the exception thrown.
while (true) {
if (!queue.isEmpty()) {
Submission submission = queue.get();
compiler.submit(submission);
}
}
}
}
First two variable injected properly but the verdictService is not.
this is my VerdictService and VerdictServiceImpl interface and class.
public interface VerdictService {
void post(Verdict verdict);
}
==
#Service
#Transactional
public class VerdictServiceImpl implements VerdictService {
#Autowired
SessionFactory sessionFactory;
#Override
public void post(Verdict verdict) {
sessionFactory.getCurrentSession()
.save(verdict);
}
}
and this is my configuration class
#Configuration
#EnableScheduling
#ComponentScan(basePackages = "com.muztaba")
public class AppConfig {
}
I have also give my project directory structure.
What I am missing here ? thank you.
You need to autowire VerdictService
#Autowired
VerdictService verdictService;
and you need to omit the line
verdictService = context.getBean(VerdictServiceImpl.class);
Ideally your code should use the services via autowiring.
it seems since you have annotated it with #transactional, Spring is creating a JDK interface based proxy. So spring manages a bean 'VerdictService' not 'VerdictServiceImpl'.
it should be
verdictService = context.getBean(verdictService.class);
instead of
verdictService = context.getBean(VerdictServiceImpl.class);

MongoDB and Spring JPA integration is throwing error

I am trying to integrate Spring JPA with MongoDB. My intention is to just retrieve data from mongo DB. I am getting the below error while injecting my repository.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.org.coop.society.data.mongo.repositories.MaterialMasterRepository com.org.coop.security.service.MongoService.materialMasterRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'materialMasterRepository': Invocation of init method failed; nested exception is java.lang.AbstractMethodError
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
My configuration snippet is given below.
TestMongoDBConfig.java
#Configuration
#EnableMongoRepositories(basePackages = {"com.abc.data.mongo.repositories"})
#ComponentScan(basePackages = "com.abc")
#PropertySource("classpath:applicationTest.properties")
public class TestMongoDBConfig extends AbstractMongoConfiguration {
#Autowired
private Environment env;
#Override
protected String getDatabaseName() {
return "retail";
}
#Override
#Bean
public MongoClient mongo() throws Exception {
MongoClient client = new MongoClient("localhost", 27017);
return client;
}
#Override
protected String getMappingBasePackage() {
return "com.abc.data.mongo.entities";
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), getDatabaseName());
}
}
MaterialMaster.java in com.abc.data.mongo.entities package
#Document(collection = "materialMaster")
public class MaterialMaster {
#Id
private Long materialId;
#Field
private String name;
MaterialMasterRepository.java in com.abc.data.mongo.repositories package
public interface MaterialMasterRepository extends MongoRepository<MaterialMaster, Long> {
}
MongoService.java in com.abc.service package
#Service
public class MongoService {
#Autowired
private MaterialMasterRepository materialMasterRepository;
public void getMaterials() {
List<MaterialMaster> materials = materialMasterRepository.findAll();
System.out.println(materials);
}
}
Junit class looks like below
#RunWith(SpringJUnit4ClassRunner.class)
#ComponentScan(basePackages = "com.abc")
#ContextHierarchy({
#ContextConfiguration(classes={TestMongoDBConfig.class})
})
public class ModuleWSTest {
#Autowired
private MongoService mongoService;
#Test
public void testModule() {
mongoService.getMaterials();
}
}
I have tried all possible changes (as per my knowledge) but no luck. Any help is really appreciated.
The error message is little confusing. I was using latest spring-data-mongodb (1.8.4.RELEASE). Once I downgraded the dependency to 1.6.0.RELEASE then the above configuration started working.

Resources