No qualifying bean of type 'javax.persistence.EntityManager' available: expected single matching bean but found 2

16,255

Solution 1

Found a solution by marking the class I was injecting with the EntityManager with @Component and then auto-wiring that class into the class that uses the GraphQLExecutor:

New class marked @Component

package p4;

import org.crygier.graphql.GraphQLExecutor;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Component
public class CompanyGraphQLComponent {

  @PersistenceContext(unitName = "company")
  private EntityManager entityManager;

  public GraphQLExecutor graphQLExecutor() {
    return new GraphQLExecutor(entityManager);
  }
}

Class auto-wiring CompanyGraphQLComponent

package p4.rest.controllers;

import core_services.persistence.CompanyContextHolder;
import core_services.records.system.Company;
import graphql.ExecutionResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import p4.CompanyGraphQLComponent;
import p4.records.GraphQLQuery;

@RestController
public class GraphQLController {
  @Autowired
  private CompanyGraphQLComponent companyGraphQLComponent;

  @RequestMapping(value = "/graphql", consumes = MediaType.APPLICATION_JSON_VALUE)
  public ExecutionResult postJson(@RequestBody GraphQLQuery graphQLQuery) {
    return companyGraphQLComponent.graphQLExecutor().execute(graphQLQuery.getQuery(), graphQLQuery.getVariables());
  }
}

Solution 2

You have defined two entitymanager. Now you have to tell spring which one should injected. For this you can use the @Qualifier Annotation:

@PersistenceContext(unitName = "company")
@Qualifier(<Name of the entitimanager you want to use>)
private EntityManager entityManager;

Solution 3

Can you try giving the annotation @Primary over entityManagerFactory and transactionManager in one of the configuration files once?

Share:
16,255
MJPearsall
Author by

MJPearsall

Updated on July 01, 2022

Comments

  • MJPearsall
    MJPearsall almost 2 years

    I have two entity manager configurations for two separate databases but when I try to auto-wire an entity manager in to configure my GraphQLExecutor bean I get an exception stating that there are two beans that match the criteria even though I've specified a unit name in the PersistenceContext.

    Exception

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'graphQLExecutor': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManager' available: expected single matching bean but found 2: org.springframework.orm.jpa.SharedEntityManagerCreator#0,org.springframework.orm.jpa.SharedEntityManagerCreator#1 at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:321) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE] at com.ogl.JpaDemoApplication.main(JpaDemoApplication.java:15) [classes/:na] Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManager' available: expected single matching bean but found 2: org.springframework.orm.jpa.SharedEntityManagerCreator#0,org.springframework.orm.jpa.SharedEntityManagerCreator#1 at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:173) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:518) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:627) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.9.RELEASE.jar:4.3.9.RELEASE] at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:318) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE] ... 17 common frames omitted

    Entity Manager 1

    package com.ogl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.Environment;
    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.LocalContainerEntityManagerFactoryBean;
    import org.springframework.orm.jpa.vendor.Database;
    import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
    import org.springframework.transaction.PlatformTransactionManager;
    
    import javax.sql.DataSource;
    
    @Configuration
    @EnableJpaRepositories(basePackages = "com.ogl.system", entityManagerFactoryRef = "companyEntityManagerFactory", transactionManagerRef = "companyTransactionManager")
    public class SystemJpaConfig {
    
      private final Environment environment;
    
      @Autowired
      public SystemJpaConfig(Environment environment) {
        this.environment = environment;
      }
    
      @Bean("systemEntityManagerFactory")
      public LocalContainerEntityManagerFactoryBean systemEntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setPackagesToScan("com.ogl.system");
        entityManagerFactoryBean.setPersistenceUnitName("system");
        entityManagerFactoryBean.setDataSource(systemDataSource());
    
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setDatabase(Database.POSTGRESQL);
        adapter.setShowSql(true);
        adapter.setGenerateDdl(false);
    
        entityManagerFactoryBean.setJpaVendorAdapter(adapter);
    
        return entityManagerFactoryBean;
      }
    
      @Bean
      DataSource systemDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getProperty("p4.datasource.driver"));
        dataSource.setUrl(environment.getProperty("p4.system.url"));
        dataSource.setUsername(environment.getProperty("p4.system.user"));
        dataSource.setPassword(environment.getProperty("p4.system.password"));
    
        return dataSource;
      }
    
      @Bean
      public PlatformTransactionManager systemTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory((systemEntityManagerFactory().getObject()));
    
        return transactionManager;
      }
    }
    

    Entity Manager 2

    package com.ogl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.Environment;
    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.LocalContainerEntityManagerFactoryBean;
    import org.springframework.orm.jpa.vendor.Database;
    import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
    import org.springframework.transaction.PlatformTransactionManager;
    
    import javax.sql.DataSource;
    
    @Configuration
    @EnableJpaRepositories(basePackages = "com.ogl.company", entityManagerFactoryRef = "companyEntityManagerFactory", transactionManagerRef = "companyTransactionManager")
    public class CompanyJpaConfig {
    
      private final Environment environment;
    
      @Autowired
      public CompanyJpaConfig(Environment environment) {
        this.environment = environment;
      }
    
      @Primary
      @Bean("companyEntityManagerFactory")
      public LocalContainerEntityManagerFactoryBean companyEntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setPackagesToScan("com.ogl.company");
        entityManagerFactoryBean.setPersistenceUnitName("company");
        entityManagerFactoryBean.setDataSource(companyDataSource());
    
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setDatabase(Database.POSTGRESQL);
        adapter.setShowSql(true);
        adapter.setGenerateDdl(false);
    
        entityManagerFactoryBean.setJpaVendorAdapter(adapter);
    
        return entityManagerFactoryBean;
      }
    
      @Bean
      DataSource companyDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getProperty("p4.datasource.driver"));
        dataSource.setUrl(environment.getProperty("p4.company.url"));
        dataSource.setUsername(environment.getProperty("p4.company.user"));
        dataSource.setPassword(environment.getProperty("p4.company.password"));
    
        return dataSource;
      }
    
      @Primary
      @Bean
      public PlatformTransactionManager companyTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory((companyEntityManagerFactory().getObject()));
    
        return transactionManager;
      }
    }
    

    Injection

    package com.ogl;
    
    import org.crygier.graphql.GraphQLExecutor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    @Configuration
    @ComponentScan
    public class GraphQLJpaConfig {
    
      @PersistenceContext(unitName = "company")
      private EntityManager entityManager;
    
      @Bean
      public GraphQLExecutor graphQLExecutor() {
        return new GraphQLExecutor(entityManager);
      }
    }
    

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.ogl</groupId>
        <artifactId>jpa-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>jpa-demo</name>
        <description>Demo project for JPA</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.postgresql</groupId>
                <artifactId>postgresql</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.graphql-java</groupId>
                <artifactId>graphql-java</artifactId>
                <version>2.3.0</version>
            </dependency>
            <dependency>
                <groupId>com.crygier</groupId>
                <artifactId>graphql-jpa</artifactId>
                <version>0.3</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>