I found similar issues explained many web portals. But I guess this is unique situation. I am getting an error in spring mvc app.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testController' defined in file [C:\Program Files (x86)\sts-bundle\pivotal-tc-server-developer-3.1.2.RELEASE\base-instance\wtpwebapps\ExpT1\WEB-INF\classes\com\expt\controller\TestController.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.expt.repositories.CategoryRepository]: No qualifying bean of type [com.expt.repositories.CategoryRepository] found for dependency: 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 [com.expt.repositories.CategoryRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
.....
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.expt.repositories.CategoryRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
The code is given below. I think enough code has been copied. Please help me to understand what is missing and how I can fix this issue. Any help would be great...!! Code: Appinitializer:
package com.expt.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class AppInitialzer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return new Class[]{SpringAppContInit.class, SQLDevDataSource.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
return new Class[]{WebMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
return new String[]{"/"};
}
}
SQLDEVConfig:
package com.expt.config;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration
@Profile("SQLDev")
@EnableJpaRepositories(basePackages={"com.expt.repositories"})
public class SQLDevDataSource extends AbstractJpaConfig {
@Override
public DataSource getDataSource() {
// TODO Auto-generated method stub
return createBasicDataSource("jdbc:jtds:sqlserver://LOCAL:1433/MYDB;", "net.sourceforge.jtds.jdbc.Driver", "UNMA", "PWD123");
}
public BasicDataSource createBasicDataSource(String jdbcUrl, String driverClass, String userName, String password) {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(jdbcUrl);
dataSource.setDriverClassName(driverClass);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
}
SpringAPpContInit:
package com.expt.config;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
public class SpringAppContInit implements ApplicationContextInitializer<AnnotationConfigWebApplicationContext> {
@Override
public void initialize(AnnotationConfigWebApplicationContext applicationContext) {
// TODO Auto-generated method stub
ConfigurableEnvironment configEnv = applicationContext.getEnvironment();
configEnv.addActiveProfile("SQLDev");
}
}
AbstrackJpaConfig:
package com.expt.config;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import javax.sql.DataSource;
import org.hibernate.dialect.SQLServer2008Dialect;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.orm.jpa.JpaDialect;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import com.expt.domain.Category;
public abstract class AbstractJpaConfig {
public abstract DataSource getDataSource();
@Bean(name="entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource){
Map<String, String> properties = new HashMap<String, String>();
properties.put(org.hibernate.cfg.Environment.HBM2DDL_AUTO, "validate");
properties.put(org.hibernate.cfg.Environment.DIALECT, SQLServer2008Dialect.class.getName());
properties.put(org.hibernate.cfg.Environment.SHOW_SQL, "true");
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
//em.setPackagesToScan(Expense.class.getPackage().getName());
em.setPackagesToScan(Category.class.getPackage().getName());
//em.setPersistenceProvider(new HibernatePersistenceProvider());
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
em.setJpaPropertyMap(properties);
return em;
}
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Controller:
package com.expt.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.expt.domain.Category;
import com.expt.repositories.CategoryRepository;
@RestController
@RequestMapping("/test")
public class TestController {
CategoryRepository catRepo;
@Autowired
public TestController(CategoryRepository catRepo) {
this.catRepo = catRepo;
}
/*private CategoryService catSvc;
@Autowired
public TestController(CategoryService catSvc) {
this.catSvc = catSvc;
}*/
@RequestMapping("/simple")
public String test(){
return "testing";
}
@RequestMapping("/json")
public Iterable<Category> testJ(){
return catRepo.findAll();
}
}
CategoryRepository:
package com.expt.repositories;
import java.math.BigDecimal;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.expt.domain.Category;
@Repository
public interface CategoryRepository extends JpaRepository<Category, BigDecimal> {
}
=========================================================
EDIT:(As there are lot of comments added to this, thought to add these details as well)
I am referring the https://github.com/scottfrederick/spring-music. Which uses the public class AppInitializer implements WebApplicationInitializer
for appinitializer.
Full Code is here, what I was using in my old project. This does manually registering the configuration classes and it was working. But it does not require when we extend from AbstractAnnotationConfigDispatcherServletInitializer
.
public class AppInitializer implements WebApplicationInitializer{
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// TODO Auto-generated method stub
configureAppContextInitializers(servletContext, SpringAppContInit.class.getName());
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RepositoryConfig.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
webContext.register(WebMvcConfig.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
private void configureAppContextInitializers(ServletContext container, String... initClassNames) {
String initializerClasses = container.getInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM);
String delimitedClassNames = StringUtils.arrayToDelimitedString(initClassNames, " ");
if (StringUtils.hasText(initializerClasses)) {
initializerClasses += " " + delimitedClassNames;
}
else {
initializerClasses = delimitedClassNames;
}
container.setInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM, initializerClasses);
}
}
In case of AbstractAnnotationConfigDispatcherServletInitializer
, the methods getRootConfigClasses
and getServletConfigClasses
do the registering implicitly.Now I am looking for the reason why my above code is not working. I have workaround like I can make it working by reverting back to XMLs or WebApplicationInitializer
. I am looking for a solution and reason if possible with updated code rather than API document. I need a tutorial. API document wont help me to resolve the issue.
use this annotation and if you are using spring-data-jpa then extends CrudRepository or PagingAndSortingRepository instead of JpaRepository.And in TestController give autowired like this :
Your own implementation of the
WebApplicationInitializer
and the implementation extendingAbstractAnnotationConfigDispatcherServletInitializer
are different. They behave different and that is because you aren't registering your customApplicationContextInitializer
. How to register theApplicationContextInitializer
is explained in the javadoc (notice the 2 methods to set a collection ofApplicationContextInitializer
s.).However that
ApplicationContextInitializer
doesn't really add anything that cannot already be done by simply setting an environment or system property.When you do that you don't need that init.
I also strongly believe that your
@EnableJpaRepositories
is on the wrong class, the fact that you want to enable those shouldn't depend on your profile.