Arhn - архитектура программирования

NoSuchBeanDefinitionException: для зависимости не найден подходящий bean-компонент типа [Repository]: ожидается как минимум 1 bean-компонент, который квалифицируется как autowire

Я обнаружил, что подобные проблемы объясняются многими веб-порталами. Но я думаю, это уникальная ситуация. Я получаю сообщение об ошибке в приложении spring mvc.

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)

Код приведен ниже. Я думаю, что было скопировано достаточно кода. Пожалуйста, помогите мне понять, чего не хватает и как я могу исправить эту проблему. Любая помощь будет здорово...!! Код: Инициализатор:

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);
    }
}

Контроллер:

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();
    }
}

КатегорияРепозиторий:

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> {

}

=========================================================

РЕДАКТИРОВАТЬ: (Поскольку к этому добавлено много комментариев, мы также решили добавить эти детали)

Я имею в виду https://github.com/scottfrederick/spring-music. Который использует public class AppInitializer implements WebApplicationInitializer для appinitializer.

Здесь полный код, который я использовал в своем старом проекте. Это вручную регистрирует классы конфигурации, и это работает. Но это не требуется, когда мы расширяемся от 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);
    }
}

В случае AbstractAnnotationConfigDispatcherServletInitializer методы getRootConfigClasses и getServletConfigClasses выполняют неявную регистрацию. Теперь я ищу причину, по которой мой приведенный выше код не работает. У меня есть обходной путь, например, я могу заставить его работать, вернувшись к XML или WebApplicationInitializer. Я ищу решение и причину, если это возможно, с обновленным кодом, а не с документом API. Мне нужен учебник. Документ API не поможет мне решить проблему.


  • А откуда, по-твоему, весна знает о твоем ApplicationContextInitializer? Простое добавление класса, реализующего этот интерфейс, не сработает. Вы также должны зарегистрировать его. Также мне интересно, почему @EnableJpaRepositories зависит от используемого вами профиля... 28.05.2016
  • М. Дейнум, я использую AbstractAnnotation..., у вас есть ссылка на то, о чем вы говорите для меня? Я не могу найти ничего дополнительного, необходимого для ApplicationContextInitializer? У меня будет другой профиль. Могу сделать отдельно. Я сослался на это - github.com/scottfrederick/spring-music и получил приведенный выше дизайн, чтобы сделать красивый прямо и просто. 29.05.2016
  • Вам не нужен инициализатор, чтобы отличаться от профиля, просто установите spring.profiles.active в качестве среды системного свойства. Если у вас есть инициализатор, вам нужно зарегистрировать его в контексте, иначе он ничего не сделает. 29.05.2016
  • Итак, я думал, что AbstractAnnotationConfigDispatcherServletInitializer делает это автоматически. Мое старое приложение использовало WebApplicationInitializer, и у меня был метод onStartup для регистрации репозитория, конфигураций mvc. Я не уверен, что делать с AbstractAnnotationConfigDispatcherServletInitializer. Я ищу какой-нибудь справочный документ. Вы можете помочь? Я должен onStartup и здесь? 29.05.2016
  • Просто установите профиль для использования с помощью переменных среды. Использование инициализатора для этого не очень полезно (как правило). Я также не вижу здесь реальной выгоды, кроме того, что я все еще не верю, что @EnableJpaRepositories должен быть там. 29.05.2016
  • Исправлено возвращение к WebApplicationInitializer из AbstractAnnotationConfigDispatcherServletInitializer. Ничего не изменилось. Итак, вручную прописал три класса конфигурации вручную в 'onStartup`. Отсутствие документов заставило меня вернуться назад. 29.05.2016
  • Просто прочитайте документацию, там написано, как зарегистрировать ApplicationContextInitializer. Но все же эта вещь ничего не добавляет, поскольку вы должны использовать свойство. Кроме того, imho, вы все усложняете. 30.05.2016
  • Почему вы не даете какой-либо URL-адрес или не вставляете сюда содержимое? извините, я не могу понять, о чем вы говорите. Есть два способа, один использует WebApplicationInitializer , `AbstractAnnotationConfigDispatcherServletInitializer' для appinitializer. Во-первых, требуется ручная регистрация слушателя контекста, во-вторых, насколько я понимаю, не требуется. Возможно, вам придется уточнить, о чем вы говорите в деталях. Профилирование не проблема. Я могу переместить его. Моя проблема в том, что репозиторий не работает. Я не думаю, что это имеет какое-либо отношение к профилям. 30.05.2016
  • ApplicationContextInitializer не является WebApplicationInitializer. Как упоминалось 3 раза, прочитайте документацию. Информация содержится в Javadoc здесь< /а>. Также, если вы прочтете документацию по AbstractContextLoaderInitializer. Итак, в основном прочитайте javadoc классов, которые вы используете (или просто изучите API этих классов!). 30.05.2016
  • Я отредактировал свой вопрос. У меня есть все вещи, объясненные, как вы упомянули здесь. Пожалуйста, проверьте мой код выше и посмотрите, где и чего не хватает. Как вы упомянули, если мне нужен ApplicationContextInitializer, где он находится в проекте Spring-music? Как это работает? 30.05.2016
  • Давайте продолжим обсуждение в чате. 30.05.2016
  • В вашем собственном коде у вас есть configureAppContextInitializers, которого нет в коде, расширяющем базовые классы. Как я упоминал 3 раза, прежде чем вам все еще нужно зарегистрировать инициализаторы, как это сделать, объясняется в ссылках, которые я дал в других комментариях. Я также упомянул, что вам это не нужно, поскольку вы активируете профиль, вы также можете установить системное свойство с именем spring.profiles.active. 30.05.2016
  • getRootConfigClasses имеет класс SpringAppContInit. configureAppContextInitializers делает то же самое. Я пробовал по-другому, например, переопределял createServletApplicationContext, чтобы добавить активный профиль. До сих пор не работает. Я скопировал то же самое, что и -pastebin.com/hxRGerUr. неудачно 30.05.2016
  • Также, если у вас есть ответ, а не чтение документа API, поделитесь им. После всех этих комментариев у меня ничего не работает. Раньше я получал ошибку, например исключение Bean, после попытки, как вы упомянули, я получаю ошибку 404. Я не знаю почему. Тем не менее я считаю, что вы упускаете из виду настоящую первопричину. 30.05.2016
  • Нет, это не то же самое... getRootConfigClasses и ваш configureAppContextInitializers делают совершенно разные вещи. Но я сдаюсь вместо того, чтобы вы хотели учиться и читать, вы хотите скопировать и вставить ответ. 31.05.2016

Ответы:


1

Ваша собственная реализация WebApplicationInitializer и реализация, расширяющая AbstractAnnotationConfigDispatcherServletInitializer, отличаются. Они ведут себя по-разному, и это потому, что вы не регистрируете свой собственный ApplicationContextInitializer. Как зарегистрировать ApplicationContextInitializer, объясняется в javadoc (обратите внимание на 2 метода для установки набора ApplicationContextInitializers.).

public class AppInitialzer extends AbstractAnnotationConfigDispatcherServletInitializer {

    ...    

    protected ApplicationContextInitializer<?>[] getRootApplicationContextInitializers() {
        return new ApplicationContextInitializer[] { new SpringAppContInit() } ;
    }
}

Однако этот ApplicationContextInitializer на самом деле не добавляет ничего, что уже нельзя сделать, просто установив свойство среды или системы.

spring.profiles.active=SQLDev

Когда вы это сделаете, вам не нужен этот init.

Я также твердо верю, что ваш @EnableJpaRepositories относится к неправильному классу, тот факт, что вы хотите включить их, не должен зависеть от вашего профиля.

31.05.2016
  • Этот сработал. Мне нравится ваш подход, чтобы заставить других учиться чему-то. Но, к сожалению, это вне моей досягаемости. Сможете ли вы объяснить, как вы решили добавить этот метод? Я реорганизую код. Если я перенесу профиль из SpringAppContInit, в классе ничего не будет. Тем не менее, его нужно вызывать для инициализации контекста приложения, верно? 01.06.2016
  • Нет, это не так. ApplicationContextInitializer и WebApplicationInitializer это совершенно разные вещи. Чтобы создать контекст, вам не нужен ApplicationContextInitializer, который нужен только в том случае, если вам нужно выполнить некоторую работу до запуска контекста, например, выбрать профиль на основе некоторой переменной среды, загрузить что-то из базы данных. , сделать некоторые проверки и т. д. 01.06.2016
  • Спасибо М. Дейнум. Теперь понял. 01.06.2016
  • Есть ли у вас рекомендуемая веб-страница для чтения, чтобы иметь четкое представление о том, где какие конфигурации следует добавить для приложений Spring MVC? 01.06.2016

  • 2

    @ComponentScan(basePackages = "базовый пакет") @EntityScan(basePackages = "базовый пакет") @EnableJpaRepositories(basePackages = "базовый пакет")

    используйте эту аннотацию, и если вы используете spring-data-jpa, то расширяете CrudRepository или PagingAndSortingRepository вместо JpaRepository. И в TestController дайте autowired следующим образом:

    @Autowired(required = true) CategoryRepository catRepo; Также проверьте в категории, соответствует ли идентификатор типу BigDecimal.

    30.05.2016
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..