user1548451
user1548451

Reputation: 41

@Autowired can't find repository beans

I'am a bit confused about Spring Data JPA repositories used in an "Annotation only" context. When starting a tomcat server on which I am deploying the application, I get the following Error:

Grave: ContainerBase.addChild: start: 
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/dashboard]]

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'archivingService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.mycompany.dashboard.persistence.repository.RequestsRepository com.mycompany.dashboard.core.services.archiving.ArchivingServiceImplJPA.requestsRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.mycompany.dashboard.persistence.repository.RequestsRepository] 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)}

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.mycompany.dashboard.persistence.repository.RequestsRepository com.mycompany.dashboard.core.services.archiving.ArchivingServiceImplJPA.requestsRepository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.mycompany.dashboard.persistence.repository.RequestsRepository] 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)}

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.mycompany.dashboard.persistence.repository.RequestsRepository] 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)}

The error is clear but I can't figure out what exactly is wrong. My first suspicion is that the rootContext is created before the persistenceCOntext, and thus my repository beans are not known when Autowiring them in the Service class. My second suspicion is that I am missing something concerning the use of annotations.

My configuration classes:

package com.mycompany.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.mycompany.core.services.archiving.ArchivingService;
import com.mycompany.core.services.archiving.ArchivingServiceImplJPA;
import com.mycompany.core.services.restore.RestoreService;
import com.mycompany.core.services.restore.RestoreServiceImplAPI;
import com.mycompany.core.util.StatusConverter;

/**
 * Configuration class used to define core(service) beans
 * 
 *
 */
@Configuration
@ComponentScan(basePackages = { "com.mycompany.core.services", "com.mycompany.core.util"})
public class CoreConfig {

    @Bean
    public ArchivingService archivingService() {
        return new ArchivingServiceImplJPA();
    }
}

MVCConfig:

package com.mycompany.dashboard.config;

import java.util.ArrayList;
import java.util.List;

import org.dozer.DozerBeanMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.mycompany.dashboard.core.util.ApiObjectMapper;

/**
 * Configuration class used to define Web beans, these beans are used for the
 * REST service
 * 
 *
 */
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.mycompany.dashboard.rest.controller",
        "com.mycompany.dashboard.rest.filter" })
public class MVCConfig extends WebMvcConfigurerAdapter implements
        WebMvcConfigurer {

    private static final String MAPPING_FILE = "META-INF/dozer/global-dto.xml";

    /**
     * Configures dozer mapping and objectmapper
     * 
     * @return DozerBeanMapper
     */
    @Bean
    public DozerBeanMapper dozerMapper() {
        final DozerBeanMapper mapper = new DozerBeanMapper();
        final List<String> mappingFiles = new ArrayList<>();
        mappingFiles.add(MAPPING_FILE);

        mapper.setMappingFiles(mappingFiles);
        return mapper;
    }

    @Bean
    public ApiObjectMapper apiObjectMapper() {
        return new ApiObjectMapper();
    }

    /**
     * Configure Jackson Objects to JSON converter
     */
    @Override
    public void configureMessageConverters(
            List<HttpMessageConverter<?>> converters) {
        final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(apiObjectMapper());
        converters.add(converter);
    }

}

PersistenceJPAConfig:

package com.mycompany.dashboard.config;

import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
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 org.springframework.transaction.annotation.EnableTransactionManagement;


/**
 * Configuration class used to define persistence beans
 *
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("com.mycompany.dashboard.persistence.repository")
public class PersistenceJPAConfig {

    /**
     * Gets LocalContainerEntityManagerFactoryBean and configures it
     * 
     * @return LocalContainerEntityManagerFactoryBean
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[] { "com.mycompany.persistence.model" });

        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());

        return em;
    }

    /**
     * Configures connection to Database
     * 
     * @return Datasource
     */
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:oracle:thin:@dbdev:1521:DEV");
        dataSource.setUsername("CONTINTEGR");
        dataSource.setPassword("8944CE07176988D6F30CC021471EBC9A");
        return dataSource;
    }

    /**
     * Sets PlatformTransactionManager with an EntityManager
     * 
     * @param EntityManagerFactory
     * @return PlatformTransactionManager
     */
    @Bean
    public PlatformTransactionManager transactionManager(
            EntityManagerFactory emf) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);

        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    Properties additionalProperties() {
        Properties properties = new Properties();
        // properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
        // properties.setProperty("hibernate.dialect",
        // "org.hibernate.dialect.MySQL5Dialect");
        return properties;
    }
}

WebAppInitializer:

    package com.mycompany.dashboard.config;

    import java.util.Set;

    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRegistration;

    import org.springframework.web.WebApplicationInitializer;
    import org.springframework.web.context.ContextLoaderListener;
    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    import org.springframework.web.servlet.DispatcherServlet;

    import com.mycompany.dashboard.rest.filter.CORSFilter;

    /**
     * Configuration class which centralizes the core, web and persistence
     * configurations
     *
     */
    public class WebAppInitializer implements WebApplicationInitializer {

        // API servlet name
        private static final String API_SERVLET_NAME = "api";
        // API servlet mapping
        private static final String API_SERVLET_MAPPING = "/api/*";

        public void onStartup(ServletContext servletContext)
                throws ServletException {
            WebApplicationContext rootContext = createRootContext(servletContext);

            configurePersistence(rootContext);

            configureSpringMvc(servletContext, rootContext);
        }

        private WebApplicationContext createRootContext(
                ServletContext servletContext) {
            AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
            rootContext.register(CoreConfig.class);
            rootContext.refresh();

            servletContext.addListener(new ContextLoaderListener(rootContext));
            servletContext.addFilter("CORSFilter", new CORSFilter())
                    .addMappingForUrlPatterns(null, false, "/*");
            ;
            servletContext.setInitParameter("defaultHtmlEscape", "true");

            return rootContext;
        }

        private void configureSpringMvc(ServletContext servletContext,
                WebApplicationContext rootContext) {
            AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();
            mvcContext.register(MVCConfig.class);
            mvcContext.setParent(rootContext);
            ServletRegistration.Dynamic appServlet = servletContext.addServlet(
                    API_SERVLET_NAME, new DispatcherServlet(mvcContext));
            appServlet.setLoadOnStartup(1);
            Set<String> mappingConflicts = appServlet
                    .addMapping(API_SERVLET_MAPPING);

        }

        private void configurePersistence(WebApplicationContext rootContext) {

            AnnotationConfigWebApplicationContext persistenceContext = new AnnotationConfigWebApplicationContext();
            persistenceContext.register(PersistenceJPAConfig.class);
            persistenceContext.setParent(rootContext);
        }

    }

My Service class:

package com.mycompany.dashboard.core.services.archiving;

import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.mycompany.dashboard.arcsysdashboard.core.util.StatusConverter;
import com.mycompany.dashboard.persistence.model.Request;
import com.mycompany.dashboard.persistence.repository.ArchivingsRepository;
import com.mycompany.dashboard.persistence.repository.RequestsRepository;
import com.mycompany.dashboard.rest.domain.RestRequest;

/**
 * Implementing class of the archiving service interface using Spring Data JPA
 * repositories
 *
 */
public class ArchivingServiceImplJPA implements ArchivingService {

    @Autowired
    private RequestsRepository requestsRepository;
    @Autowired
    private ArchivingsRepository archivingsRepository;
    @Autowired
    private StatusConverter statusConverter;

    @Override
    public List<RestRequest> findLastArchivingRequests() {

        List<RestRequest> recordRequests = new LinkedList<RestRequest>();

        List<RestRequest> restRequests = new LinkedList<RestRequest>();
        List<Request> requests = requestsRepository.findFiveLastRequests("A");
        for (Request request : requests) {

            RestRequest restRequest = new RestRequest(new Timestamp(request
                    .getDate().getTime()), this.statusConverter.getStatus(
                    request.getLastStatus()).toString(), archivingsRepository
                    .findOne(request.getLotIdent()).getCode());
            restRequests.add(restRequest);
        }

        return recordRequests;

    }

}

My repository classes:

package com.mycompany.dashboard.persistence.repository;

import java.rmi.server.UID;

import org.springframework.data.jpa.repository.JpaRepository;

import com.mycompany.dashboard.persistence.model.Record;

/**
 * Spring Data Repository interface used to manage Records
 *
 */
public interface ArchivingsRepository extends JpaRepository<Record, UID> {

    Record findOne(Long id);
}

package com.mycompany.dashboard.persistence.repository;

import java.rmi.server.UID;
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.mycompany.dashboard.persistence.model.Request;

/**
 * Spring Data Repository interface used to manage Requests
 */

public interface RequestsRepository extends JpaRepository<Request, UID> {

    @Query("SELECT TOP 5 req FROM Request req WHERE req.owner = :name and req.type = paramType")
    List<Request> findFiveLastRequestsByOwnerAndType(
            @Param("owner") String author, @Param("type") String paramType);

    @Query("SELECT TOP 5 req FROM Request req WHERE req.type = A")
    List<Request> findFiveLastRequests(@Param("type") String paramType);
}

Upvotes: 1

Views: 3451

Answers (1)

Andrei Stefan
Andrei Stefan

Reputation: 52368

Place an @Import(PersistenceJPAConfig.class) to your CoreConfig class as it seems this configuration class isn't being picked up properly or at all.

Upvotes: 1

Related Questions