I am studying hibernate and spring which uses servlet3.0. So I made follow classes which are replacement of *-context.xml. (There are lots of samples in internet, but I do not want to use xml.)
First, follows are my configuration classes.
RootConfig - Has informations about database connection and JPA settings.
@Configuration
public class RootConfig {
@Value(value = "${jdbc.driverClassName}")
private String driverClassName;
@Value(value = "${jdbc.url}")
private String url;
@Value(value = "${jdbc.username}")
private String username;
@Value(value = "${jdbc.password}")
private String password;
@Value(value ="${jdbc.postgres.url}")
private String DB_URL;
private static final String RESOURCE_LOCATION = "resources";
@Bean
public static PropertyPlaceholderConfigurer propertyPlaceholder() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[]{
new ClassPathResource(RESOURCE_LOCATION + File.separator + "properties"
+ File.separator + "jdbc" + File.separator + "jdbc.properties")
};
ppc.setLocations(resources);
return ppc;
}
@Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean localContainerEntityFactoryManagerBean(){
LocalContainerEntityManagerFactoryBean lcemfb = new LocalContainerEntityManagerFactoryBean();
lcemfb.setDataSource(dataSource());
lcemfb.setPackagesToScan("org.owls.posthibernate.person");
lcemfb.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.dialect", PostgreSQL82Dialect.class.getName());
jpaProperties.put("hibernate.show_sql", false);
jpaProperties.put("hibernate.format_sql", false);
//jpaProperties.put("hibernate.hbm2ddl.auto", "create");
lcemfb.setJpaProperties(jpaProperties);
return lcemfb;
}
};
ServletConfig - Has ViewResolver and ResourceHandler + context:component-scan
@Configuration
@EnableWebMvc
@EnableAsync
@ComponentScan(basePackages={
"org.owls.posthibernate.person.dao"
, "org.owls.posthibernate.person.service"
, "org.owls.posthibernate.person.controller"
, "org.owls.posthibernate.init.controller"
}, excludeFilters=@ComponentScan.Filter(Configuration.class))
public class ServletConfig extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver irv = new InternalResourceViewResolver();
irv.setPrefix("/WEB-INF/views/");
irv.setSuffix(".jsp");
return irv;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/")
.setCachePeriod(31556926);;
}
};
till here, it works nice. When I running this code, has no error.
I can attach @Service
and @controller
, and no problem with reading DB informations.
And now, I attach @Repository
layer. and it spits an error. Below is my @Repository
interface.
@Repository
public interface PersonDAO extends CrudRepository<Person, Long> {
public List<Person> list();
public List<Person> findByFamilyName (String familyName);
};
Since I declare content:component-scan in ServletConfig.java. I think it should work. but not :(
When I use this class, I just @Autowired
. like..
@Autowired
PersonDAO dao;
I do not know why it can not find any bean for that DAO class. Thanks for answer and below is error message what I got in console.
SEVERE: StandardWrapper.Throwable
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.owls.posthibernate.person.dao.PersonDAO org.owls.posthibernate.person.service.PersonService.dao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.owls.posthibernate.person.dao.PersonDAO] 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), @org.springframework.beans.factory.annotation.Qualifier(value=dao)}
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)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:663)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:535)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:489)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1280)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1091)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5176)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5460)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.owls.posthibernate.person.dao.PersonDAO org.owls.posthibernate.person.service.PersonService.dao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.owls.posthibernate.person.dao.PersonDAO] 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), @org.springframework.beans.factory.annotation.Qualifier(value=dao)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 26 more
===================== Edit 0622 ========================
First, thanks for your help.
I should read that article about @Configuration, but I decided to answer another answers.
I got 2 main point there,
- I should been activate annotation.
- I should implement PersonDAO.
This is my answer for question 1. I did not describe annotation driven since my WebApplicationInitializer looks like below.
public class Initializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext arg0) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(RootConfig.class);
ctx.register(ServletConfig.class);
ctx.setServletContext(arg0);
Dynamic servlet = arg0.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
};
I think AnnotationConfigWebApplicationContext
can do same with annotation driven
. (I am not sure of it. I will look for it after writing this)
The answer for the second, the reason why I did not implement personDAO
is I do not want to use implemented class. I have worked with MyBatis Mapper interface, so I believe Hibernate can do such interface thing. Is there no way to inject DAO without implementation in Hibernate?
The link I was looking is http://devcrumb.com/hibernate/spring-data-jpa-hibernate-maven (I am not sure it is OK to post link on here)
and it uses @Repository without implemented class.