webentwicklung-frage-antwort-db.com.de

Spring Boot ConflictingBeanDefinitionException: Annotation-spezifizierter Bean-Name für die @Controller-Klasse

Ich erhalte in meiner Spring-Startanwendung ständig den Fehler ConflictingBeanDefinitionException. Ich bin nicht ganz sicher, wie ich damit umgehen soll. Ich habe mehrere Klassen mit Annotationen von @Configuration, die beim Einrichten von Thymeleaf, Spring Security und Web helfen. Warum versucht die Anwendung, den homeController zweimal einzurichten? (und wo versucht es das zu tun?)

Der Fehler ist:

org.springframework.beans.factory.BeanDefinitionStoreException: 
Failed to parse configuration class [org.kemri.wellcome.hie.Application]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'homeController' for bean class [org.kemri.wellcome.hie.HomeController] conflicts with existing, non-compatible bean definition of same name and class [org.kemri.wellcome.hie.controller.HomeController]

Mein Spring Boot-Hauptanwendungsinitialisierer:

@EnableScheduling
@EnableAspectJAutoProxy
@EnableCaching
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    protected final SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

}

Meine Datenbank-Konfigurationsdatei:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages="org.kemri.wellcome.hie.repositories")
@PropertySource("classpath:application.properties")
public class DatabaseConfig {

  @Autowired
  private Environment env;

  @Autowired
  private DataSource dataSource;

  @Autowired
  private LocalContainerEntityManagerFactoryBean entityManagerFactory;

   @Bean
  public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("spring.datasource.driverClassName"));
    dataSource.setUrl(env.getProperty("spring.datasource.url"));
    dataSource.setUsername(env.getProperty("spring.datasource.username"));
    dataSource.setPassword(env.getProperty("spring.datasource.password"));
    return dataSource;
  }
  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean entityManagerFactory =
        new LocalContainerEntityManagerFactoryBean();

    entityManagerFactory.setDataSource(dataSource);

    // Classpath scanning of @Component, @Service, etc annotated class
    entityManagerFactory.setPackagesToScan(
        env.getProperty("spring.jpa.hibernate.entitymanager.packagesToScan"));

    // Vendor adapter
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    entityManagerFactory.setJpaVendorAdapter(vendorAdapter);

    // Hibernate properties
    Properties additionalProperties = new Properties();
    additionalProperties.put(
        "hibernate.dialect", 
        env.getProperty("spring.jpa.hibernate.dialect"));
    additionalProperties.put(
        "hibernate.showsql", 
        env.getProperty("spring.jpa.hibernate.showsql"));
    additionalProperties.put(
        "hibernate.hbm2ddl.auto", 
        env.getProperty("spring.jpa.hibernate.hbm2ddl.auto"));
    entityManagerFactory.setJpaProperties(additionalProperties);

    return entityManagerFactory;
  }
  @Bean
  public JpaTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = 
        new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(
        entityManagerFactory.getObject());
    return transactionManager;
  }
  @Bean
  public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
  }

}

Meine Thymeleaf-Konfigurationsdatei:

@Configuration
public class ThymeleafConfig {

@Bean
public ServletContextTemplateResolver templateResolver(){
    ServletContextTemplateResolver thymeTemplateResolver = new ServletContextTemplateResolver();
    thymeTemplateResolver.setPrefix("/WEB-INF/views/");
    thymeTemplateResolver.setSuffix(".html");
    thymeTemplateResolver.setTemplateMode("HTML5");
    return thymeTemplateResolver;
}   

@Bean
public SpringSecurityDialect springSecurityDialect(){
    SpringSecurityDialect dialect = new SpringSecurityDialect();
    return dialect;
}

@Bean
public SpringTemplateEngine templateEngine() {
    SpringTemplateEngine engine = new SpringTemplateEngine();   
    engine.addTemplateResolver(templateResolver());
    Set<IDialect> dialects = new HashSet<IDialect>();
    dialects.add(springSecurityDialect());
    engine.setAdditionalDialects(dialects);     
    return engine;
}

@Bean
public ThymeleafViewResolver thymeleafViewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(templateEngine());
    resolver.setViewClass(ThymeleafTilesView.class);
    resolver.setCharacterEncoding("UTF-8");
    return resolver;
}

}

Meine Web-Konfigurationsklasse:

@Configuration
@PropertySource("classpath:application.properties")
public class WebConfig extends WebMvcAutoConfigurationAdapter  {

    @Autowired
    private Environment env;

    @Bean
    public JavaMailSenderImpl javaMailSenderImpl() {
        JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl();
        mailSenderImpl.setHost(env.getProperty("smtp.Host"));
        mailSenderImpl.setPort(env.getProperty("smtp.port", Integer.class));
        mailSenderImpl.setProtocol(env.getProperty("smtp.protocol"));
        mailSenderImpl.setUsername(env.getProperty("smtp.username"));
        mailSenderImpl.setPassword(env.getProperty("smtp.password"));
        Properties javaMailProps = new Properties();
        javaMailProps.put("mail.smtp.auth", true);
        javaMailProps.put("mail.smtp.starttls.enable", true);
        mailSenderImpl.setJavaMailProperties(javaMailProps);
        return mailSenderImpl;
    }

    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager();
    }
}

Mein Controller (bei der Installation des Controllers ist ein Fehler aufgetreten)

@Controller
public class HomeController {

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);

        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

        String formattedDate = dateFormat.format(date);

        model.addAttribute("serverTime", formattedDate );

        return "index.html";
    }
}

Was könnte den ConflictingBeanDefinitionException-Fehler für meine Controller-Klasse verursachen?

12
Timothy Tuti

Wie ich herausgefunden habe, besteht die Lösung darin, die doppelte Initialisierung zu deaktivieren, indem ein Filter in den Komponentenscan aufgenommen wird. In meinem Fall:

@EnableScheduling
@EnableAspectJAutoProxy
@EnableCaching
@Configuration
@ComponentScan(basePackages = { "org.kemri.wellcome.hie" }, 
    excludeFilters = {@Filter(value = Controller.class, type = FilterType.ANNOTATION)})
@EnableAutoConfiguration
@PropertySource("classpath:application.properties")
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
5
Timothy Tuti

Ich hatte das gleiche Problem, aber aus einem anderen Grund.

Dies kann auch vorkommen, wenn Sie Ihre Klassen in Ihrem Projekt verschieben und keine 'Säuberung' durchführen.

Ich benutze gradle mit Spring-Boot-Plugin. Jetzt laufe ich normalerweise:

$> ./gradlew clean bootRun
22
mchlstckl

Ich hatte das gleiche Problem bei einem Spring-Integrationstest , als ich ihn mit InteliJ ausführte.

Nach einem Refactor war einer meiner Controller-Klasse tatsächlich im Verzeichnis / out/production/classes vorhanden, das seit Version 2017.2 ..__ das Standardausgabeverzeichnis für Intelij ist. Es ist build/classes), das Gradle Clean-Ziel hatte keine Auswirkungen.

Für mich bestand die Lösung darin, / out/production/classes manuell zu entfernen und meinen Integrationstest erneut auszuführen.

Für eine mögliche dauerhafte Lösung ohne 2 Ausgabeverzeichnisse siehe hier

4
user3793803

Ich hatte das gleiche Problem mit einer generierten .war-Datei von Spring-Boot. Die genehmigte Lösung (Timothy Tutis eigene Lösung) hat für mich nicht ganz so funktioniert, wie sie ist, aber ich habe sie ein wenig optimiert, und sie hat funktioniert. Ich habe gerade die folgende Zeile zu meiner Application.Java hinzugefügt:

@ComponentScan(basePackages = { "com.mypackage" })

Als Referenz geht hier meine vollständige Application.Java

package com.inmoment.devchallenge;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.config.Neo4jConfiguration;

@SpringBootApplication
@Configuration
@ComponentScan(basePackages = { "com.inmoment.devchallenge.controller" })
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {

    @Configuration
    @EnableNeo4jRepositories(basePackages = "com.inmoment.devchallenge.repository")
    static class ApplicationConfig extends Neo4jConfiguration {

        public ApplicationConfig() {
            setBasePackage("com.inmoment.devchallenge.repository");
        }

        @Bean
        GraphDatabaseService graphDatabaseService() {
            return new GraphDatabaseFactory().newEmbeddedDatabase("accessingdataneo4j.db");
        }
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

}
0
lotif

Ich habe dies bei mvn festgestellt, nachdem ich mehrere Ordnernamen und verwandte Paketnamen geändert hatte. Dann habe ich maven clean aufgetragen und wieder Springboot gefahren, alles gelöst:

mvn clean
mvn spring-boot:run
0
tolga

Es scheint, dass Sie zwei entityManagerFactory haben, eine, die Sie automatisch einrichten werden, und eine, die Sie als Bean programmatisch auflösen:

@Autowired
private LocalContainerEntityManagerFactoryBean entityManagerFactory;

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
...
}

Ich denke, Sie brauchen nur Ihre konfigurierte Factory in entityManagerFactory () -Methode.

0
sven.kwiotek