0

By configuring application to use two datasource instances, it cause an issue in one of my integration tests with the following message - "Unsatisfied dependency expressed through method 'entityManagerFactoryBean' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}"

Here is the bean that stores the information for both database instances:

@Component
public class DataSourceRouting extends AbstractRoutingDataSource {
    private final DataSourcePrimeConfig dataSourcePrimeConfig;
    private final DataSourceSecondConfig dataSourceSecondConfig;
    private final DataSourceContextHolder dataSourceContextHolder;

    public DataSourceRouting(DataSourceContextHolder dataSourceContextHolder, DataSourcePrimeConfig dataSourcePrimeConfig,
                             DataSourceSecondConfig dataSourceSecondConfig) {
        this.dataSourcePrimeConfig = dataSourcePrimeConfig;
        this.dataSourceSecondConfig = dataSourceSecondConfig;
        this.dataSourceContextHolder = dataSourceContextHolder;

        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put(DataSourceEnum.DATASOURCE_PRIME, dataSourceOneDataSource());
        dataSourceMap.put(DataSourceEnum.DATASOURCE_SECOND, dataSourceTwoDataSource());
        this.setTargetDataSources(dataSourceMap);
        this.setDefaultTargetDataSource(dataSourceOneDataSource());
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return this.dataSourceContextHolder.getBranchContext();
    }

    public DataSource dataSourceOneDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(dataSourcePrimeConfig.getUrl());
        dataSource.setUsername(dataSourcePrimeConfig.getUsername());
        dataSource.setPassword(dataSourcePrimeConfig.getPassword());
        return dataSource;
    }

    public DataSource dataSourceTwoDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(dataSourceSecondConfig.getUrl());
        dataSource.setUsername(dataSourceSecondConfig.getUsername());
        dataSource.setPassword(dataSourceSecondConfig.getPassword());
        return dataSource;
    }
}

Here is the configuration class:

@Configuration
@EnableJpaRepositories(basePackages = "test.project.repository", transactionManagerRef = "transcationManager", entityManagerFactoryRef = "entityManager")
@EnableTransactionManagement
@RequiredArgsConstructor
@DependsOn("dataSourceRouting")
public class DataSourceConfig {
    private final DataSourceRouting dataSourceRouting;

    @Bean
    @Primary
    public DataSource dataSource() {
        return dataSourceRouting;
    }

    @Bean(name = "entityManager")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(dataSource()).packages("test.project").build();
    }

    @Bean(name = "transcationManager")
    public JpaTransactionManager transactionManager(
            @Autowired @Qualifier("entityManager") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
        return new JpaTransactionManager(entityManagerFactoryBean.getObject());
    }
}

And here is the failing test:

@SpringBootTest
@Import(value = DataSourceConfig.class)
@RunWith(SpringRunner.class)
@ActiveProfiles("test")
public class MailBodyProviderServiceTest {
    @Autowired
    private MailService mailService;

    @Autowired
    private ReportService reportService;

    @MockBean
    private JPATransactionDataRepository jpaTransactionDataRepository;

    @Autowired
    private MailBodyBuilder builder;

    @Autowired
    private DataSourceRouting dataSourceRouting;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private LocalContainerEntityManagerFactoryBean entityManagerFactoryBean;

    @Autowired
    private JpaTransactionManager jpaTransactionManager;

    @Autowired
    private EntityManagerFactoryBuilder entityManagerFactoryBuilder;

    @Rule
    public SmtpServerRule smtpServerRule = new SmtpServerRule(2525);

    @Test
    public void shouldSendSingleMail() throws MessagingException {

        when(this.jpaTransactionDataRepository.mapTransactionData()).thenReturn(generateReportData());
        mailService.sendEmail(new ReportEvent(this, "report event", EventType.CREDIT_CARD));

        MimeMessage[] receivedMessages = smtpServerRule.getMessages();
        assertEquals(3, receivedMessages.length);

        MimeMessage current = receivedMessages[0];
        String contentType = current.getContentType();
        assertTrue(contentType.contains("multipart"));
    }

    private static Map<Date, List<TransactionDto>> generateReportData(){

        Date today = new Date();

        List<Object[]> objects = new ArrayList<>();
        Object[] object1 = new Object[] { today, AuthStatus.AUTH_CONFIRMED.name(), ProcessingType.DIRECT.name(), BigDecimal.valueOf(10l)};
        Object[] object2 = new Object[] { today, AuthStatus.AUTH_REJECTED.name(), ProcessingType.DIRECT.name(), BigDecimal.valueOf(10l)};
        Object[] object3 = new Object[] { new Date(today.getTime() + (1000 * 60 * 60 * 24)), AuthStatus.AUTH_CANCELED.name(), ProcessingType.TAN.name(), BigDecimal.valueOf(10l)};
        Object[] object4 = new Object[] { new Date(today.getTime() + (1000 * 60 * 60 * 24)), AuthStatus.AUTH_FAILED.name(), ProcessingType.TAN.name(), BigDecimal.valueOf(10l)};
        objects.add(object1);
        objects.add(object2);
        objects.add(object3);
        objects.add(object4);

        return TransactionMapper.mapFromDatabaseQuery(objects);
    }
}

I try with @TestConfiguration, also to exclude DataSourceConfig, but nothing helps. Hope someone to have idea what I do wrong or miss :)

  • Can you please show the exception stacktrace you get? – Simon Martinelli Jul 16 '21 at 09:36
  • Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManager' defined in class path resource [DataSourceConfig.class]: Unsatisfied dependency expressed through method 'entityManagerFactoryBean' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} – akyurkchiev Jul 16 '21 at 09:47
  • Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} – akyurkchiev Jul 16 '21 at 09:47

0 Answers0