0

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,

  1. I should been activate annotation.
  2. 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.

Juneyoung Oh
  • 7,318
  • 16
  • 73
  • 121
  • possible duplicate of [Understanding spring @Configuration class usage](http://stackoverflow.com/questions/24014919/understanding-spring-configuration-class-usage) – OO7 Jun 21 '15 at 05:53
  • @OO7 I think my question is little bit broaden range. It treats not only Java `@Cofigurations`, but also `@Repository`. I think main question here is how can CRUDRepository injected without implementation like MyBatis Mapper. – Juneyoung Oh Jun 22 '15 at 01:31

3 Answers3

0

In your above code don't see any PersonDAO implementation. Ideally there should be some implementation.

Once you have such implementation; then annotate it with @Controller("dao").

Ashish Patil
  • 4,428
  • 1
  • 15
  • 36
0

That means in your service class you have missed out something. Your classes are not autowired properly because of that you are getting that an exception.

Make your that, your PersonDAO should wired with service Implementation class.

Add @Service annotation in your PersionService Implementation Class.

Vignesh Shiv
  • 1,129
  • 7
  • 22
  • Thanks for your answer. but main problem here is not Service bean. it is all about dao bean. And the blog I was watching uses @Repository annotation to interface. the link is attached to main post. thanks. – Juneyoung Oh Jun 22 '15 at 00:53
0

The first @ComponentScan doesn't active @Autowired annotation, it only active @Component, @Service, @Controller and @ Repository annotation, add AnnotationConfig to active it. The second you don't have any implementation for PersonDao class, so that Spring can not find any qualify bean for it.

Tinh Cao
  • 67
  • 6