I have a persistance interface that implements MongoRepository interface that looks as follows:
package org.prithvidiamond1.DB.Repositories;
import org.prithvidiamond1.DB.Models.SomeModel;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface ServerRepository extends MongoRepository<SomeModel, String> {
}
Despite this, I keep getting the following error:
Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'botApplication':
Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.prithvidiamond1.DB.Repositories.ServerRepository' available: expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {}
PPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in org.prithvidiamond1.BotApplication required a bean of type 'org.prithvidiamond1.DB.Repositories.ServerRepository' that could not be found.
Action:
Consider defining a bean of type 'org.prithvidiamond1.DB.Repositories.ServerRepository' in your configuration.
I have tried many solutions (custom #ComponentScan, using #Service instead of #Component, etc.) I found on the internet but none could help me solve the problem, can someone explain to me what is wrong and how I should fix this?
Note: The directory structure is as follows (this is not the full directory structure, but I think this should be enough to get an idea):
org.prithvidiamond1
|
+--BotApplication.java
|
+--DB
|
+--Repository
|
+--ServerRepository.java
BotApplication.java looks as follows:
package org.prithvidiamond1;
import org.jc.api.Api;
import org.jc.api.ApiBuilder;
import org.jc.api.entity.server.Server;
import org.prithvidiamond1.DB.Models.Server;
import org.prithvidiamond1.DB.Repositories.ServerRepository;
import org.slf4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.Collection;
#Component
public class BotApplication {
private final Api api;
private final ServerRepository serverRepository;
public BotApplication(ServerRepository serverRepository, Logger logger){
String botToken = System.getenv().get("BOT_TOKEN");
this.api = new ApiBuilder();
this.serverRepository = serverRepository;
appRuntime(logger);
}
public void appRuntime(Logger logger){
logger.info("Bot has started!");
// Handling server entries in the database
if (this.serverRepository.findAll().isEmpty()) {
logger.trace("server data repository empty, initializing data repository...");
Collection<Server> servers = api.getServers();
for (Server server : servers) {
this.serverRepository.save(new Server(String.valueOf(server.getId())));
}
logger.trace("server data repository initialized");
}
}
#Bean
public Api getApi() {
return this.api;
}
}
Edit: Here is a link to a repository with all the code: https://github.com/prithvidiamond1/DiamondBot/tree/springboot-restructure
The problem is that you are using the primary source class(BotApplication.class) for executing custom code during start-up.
public static void main(String[] args) {
ApplicationContext AppContext = SpringApplication.run(BotApplication.class, args);
}
public BotApplication(DiscordServerRepository serverRepository, Logger logger){
...
appRuntime(logger);
}
It is not a good place for using repositories or any startup code.
In the SpringApplication.run method you need to pass only classes which provide beans definitions. These are #Configuration classes.
See the best practices Running code after Spring Boot starts
I describe one of the best solutions: ApplicationRunner
BotApplication class must implement ApplicationRunner interface. The interface is used to indicate that a bean should run when it is contained within a SpringApplication.
Execute all startup code at the run method.
#Component
public class BotApplication implements ApplicationRunner {
private final DiscordApi api;
private final DiscordServerRepository serverRepository;
private final Logger logger;
public BotApplication(DiscordServerRepository serverRepository, Logger logger){
String botToken = System.getenv().get("BOT_TOKEN");
this.logger = logger;
this.serverRepository = serverRepository;
this.api = new DiscordApiBuilder()
.setToken(botToken)
.setAllIntents()
.setWaitForServersOnStartup(true)
.setWaitForUsersOnStartup(true)
.login().exceptionally(exception -> { // Error message for any failed actions from the above
logger.error("Error setting up DiscordApi instance!");
logger.error(exception.getMessage());
return null;
})
.join();
}
public void appRuntime(Logger logger){
logger.info("Bot has started!");
// Handling server entries in the database
if (this.serverRepository.findAll().isEmpty()) {
logger.trace("Bot server data repository empty, initializing data repository...");
Collection<Server> servers = api.getServers();
for (Server server : servers) {
this.serverRepository.save(new DiscordServer(String.valueOf(server.getId()), Main.defaultGuildPrefix));
}
logger.trace("Bot server data repository initialized");
}
}
#Bean
public DiscordApi getApi() {
return this.api;
}
#Override
public void run(ApplicationArguments args) throws Exception {
appRuntime(logger);
}
}
Pass Main.class to the SpringApplication.run
#SpringBootApplication
#EnableMongoRepositories
public class Main {
public static void main(String[] args) {
ApplicationContext AppContext = SpringApplication.run(Main.class, args);
}
}
use annotation #Autowired with the constructor of BotApplication class as shown below -
#Autowired
public BotApplication(ServerRepository serverRepository, Logger logger){
String botToken = System.getenv().get("BOT_TOKEN");
this.api = new ApiBuilder();
this.serverRepository = serverRepository;
appRuntime(logger);
}
You need to use #EnableMongoRepositories on top of your main application class to enable scanning of mongo repository beans.
You have Created Repository bean (ServerRepository)within your application.
But in your BotApplication component (which itself is a bean), you are not telling spring to inject dependency of Repository bean (i.e. Dependancy Injection).
Such a dependancy injection can be achieved by constructor , field-based or setter based methodologies.
You can either remove ServerRepository serverRepository from public BotApplication(ServerRepository serverRepository, Logger logger) constructor & just use :
#Autowired
private final ServerRepository serverRepository;
Or as other answer suggested, use #Autowired in Constructor itself and remove field ServerRepository serverRepository :
`
#Autowired
public BotApplication(ServerRepository serverRepository, Logger logger)
`
Please note, here, this.serverRepository = serverRepository; is also not required in constructor as dependency injection will take care of this.
Related
I see a lot of posts surrounding this error message, but none with a solution that's worked for me.
I'm writing a Spring application that has required me to configure multiple data sources. I got all of those working, but now I need to import a module my teammates built that uses an additional data source and several repositories. They've been using this module in their code and it seems to be working for them, but when I try to run my code I get the following error (some details obscured for work reasons):
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.company.teammodule.repositories.StatsRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
//I can't paste code, so there may be typos...
Spring Application Class:
package com.company.mymodule;
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan(basePackages={
"com.company.mymodule",
"com.company.mymodule.utils",
"com.company.mymodule.configuration",
"com.company.teammodule.repositories",
//I've been fiddling with packages here; I've added every package from the teammatemodule app and still get the error described})
#public class MyModuleApplication
{
public static void main(String[] args) { SpringApplication.run(MyModuleApplication.class, args); }
}
My class that uses the teammatemodule:
package com.company.mymodule.utils;
#Component
public class TeammateModuleUtil {
#Autowired
private TeammateModuleConfiguration config; //This class contains an object of another class which references the problem repository
#Value("${applicationName})
private final String applicationName;
public TeammateModuleUtil()
{
try {
config.setApplicationName(applicationName);
config.loadConfiguration();
}
catch (Exception e) {
//Error handling
}
}
}
The TeammateModuleConfiguration class:
package com.company.teammatemodule
#Component
public class TeammateModuleConfiguration extends ConfigurationBase {
#Autowired
TeammateModuleServiceData data; //This class contains a reference to the problem repository
#Autowired
Utilities util;
#Autowired
ConfigurationRepository configurationRepository;
public void loadConfiguration() throws Exception {
try {
this.alConfigure = this.configurationRepository.findByConfigureIdApplicationName(this.applicationName);
} catch (Exception e) {
//Error handling
}
}
}
Here's the class that has the problem reference:
package com.company.teammatemodule;
#Component
public class TeammateModuleServiceData {
#Autowired
StatsRepository statsRepository //This is the repo the code can't find a bean for
#Autowired
MessageAuthorizationRepository messageAuthorizationRepository;
#Autowired
LogMessagesRepository logMessagesRepository;
#Autowired
Utilities util;
//Class methods
}
And here's the repository class for good measure:
package com.company.teammatemodule.repositories;
#Repository
public interface StatsRepository extends JpaRepository<Stats, StatsId> {
#Procedure(
procedureName = "schema.log_service_stats",
outputParameterName = "o_stats_id"
)
String logServiceStats(#Param("i_request_payload") String var1, #Param("i_response_payload") String var2, #Param("i_operation_name") String var3, #Param("i_stats_id") String var4);
#Procedure(procedureName = "schema.update_service_stats)
void updateServiceStats(#Param("i_request_payload") String var1, #Param("i_response_payload") String var2, #Param("i_operation_name") String var3, #Param("i_stats_id) String var4);
}
The above repository is the one that can't be found when I try to launch the application. What I've checked and tried:
The main application has the #SpringApplication annotation, and all other involved classes have either #Component, #RestController, or #Repository, so I don't think it's an issue of some component not being labeled a bean...
None of the other repositories in teammatemodule are giving me a problem, but I'm guessing StatsRepository is just the first repository to be referenced
The only properties in my properties file are applicationName and data sources unrelated to the teammatemodule. I'm not listing any packages or exclusions there.
I've specified all packages in #ComponentScan ( basepackages = {//packages} ) as well as #SpringApplication( scanBasePackages = {//packages} )
I've tried excluding spring's autoconfigure by using the following annotations in my SpringAplication class:
#SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })
#EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
So I don't think it's a missing #Component or other bean annotation, and to the best of my ability I've specified the package in which the repository bean is located and overridden Spring's built-in autoconfiguration tools... But the app still can't find the bean.
Thanks for your help!
It looks like this might just be a simple misspelling:
com.company.teammodule.repositories <- Component Scan
com.company.teammatemodule.repositories <- Package specified in Repository class
I have a notification library (written in Spring Boot, gradle, Java) which has a Service class (an interface) and an Implementation class (which extends the Service class and overrides the methods).
Service interface:
public interface NotificationService {
void sendNotification(String title, String message, List<String> ids);
Implementation class:
#Component
public class NotificationServiceImpl implements NotificationService {
private String notificationServiceURL;
public NotificationServiceImpl(#Value("${notificationService.url}") String notificationServiceURL) {
this.notificationServiceURL = notificationServiceURL;
}
public void sendNotification(String title, String message, List<String> employeeIds) {
// Some functionality
}
}
Application.yaml
notificationService:
url: "someURL"
I have packaged this library as a JAR and imported in some project which is also Spring boot project.
Now, in the main class, I added Component Scan for the path where the imported library classes are:
#ComponentScan({"com.abchealth.xyz.red", "com.abchealth.xyz.red.service", "com.abchealth.xyz.red.service.serviceImpl"})
public class SecondProject {
public static void main(String[] args) {
SpringApplication.run(SecondProject.class, args);
}
}
Then in one of the inner classes, I created an object of NotificationService
#Slf4j
#Component
#StepScope
public class SomeInnerClass implements Tasklet {
#Autowired
NotificationService notificationService;
// some code
When I run the application, it gives me this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'notificationServiceImpl' defined in URL [jar:file:/Users/usera/.gradle/caches/modules-2/files-2.1/com.abchealth.xyz.red/notification-lib/1.0.0-12/f973790603b7c261b2f6a693e83ca3e8f3f021de/notification-lib-1.0.0-12-scan.jar!/com/abchealth/xyz/red/service/serviceImpl/NotificationServiceImpl.class]: Unexpected exception during bean creation; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'notificationService.url' in value "${notificationService.url}"
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:529) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
Note: If I test this directly in Notification library by creating an object of NotificationService, it works just fine! The issue is when it is being imported in other project.
You need add notificationService.url property to your SecondProject's application.yml
Edited to add proc structure:
main/java
hello(package)
Application(main app)
TestRestController
models(package)
Test
services(package)
TestRepo(interface)
I'm currently looking at component scan as just released the 'repo.Test' in the exception is a clue.
I've been through numerous tutorials and questions and still cannot find the answer to my particular issue, which is most likely to be down to my lack of understanding.
I have a spring boot application that I'm adding a db to. I've been following this tutorial : https://www.callicoder.com/spring-boot-rest-api-tutorial-with-mysql-jpa-hibernate/
However when I try and run my application (following identical steps) I get an exception:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testRestController': Unsatisfied dependency expressed through field 'testRepo'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'repo.TestRepo' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I do have another bean autowired in, the main difference is that this bean(the one that works) has a service that implements the interface and a bean configuration class. None of the examples for JPA follow that model and it seems daft to create a service to re-implement the methods from the JPARepo.
This is the controller I'm using:
#RestController
public class TestRestController {
#Autowired
GreetingService greetingService;
#Autowired
TestRepo testRepo;
#RequestMapping("/hello")
public String home() {
return greetingService.greet();
}
#RequestMapping("/testrepo")
public String testrepo() {
Test test = new Test("steve");
testRepo.save(test);
Long idOftest = test.getId();
test = null;
test = testRepo.findById(idOftest).get();
return "DID THIS WORK::::: + "+ test.toString();
}
with the interface being
#Repository
public interface TestRepo extends JpaRepository<Test, Long> {
}
and the model:
#Entity
#Data
public class Test {
private final String name;
public Test(String name){
this.name = name;
}
#Id
#GeneratedValue
private Long id;
public Long getId(){
return this.id;
}
}
The application main is:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
// #Bean
// public CommandLineRunner commandLineRunner(ApplicationContext ctx ) {
// return args -> {
//
// System.out.println("Let's inspect the beans provided by Spring Boot:");
//
// String[] beanNames = ctx.getBeanDefinitionNames();
// Arrays.sort(beanNames);
// for (String beanName : beanNames) {
// System.out.println(beanName);
// }
//
//
// };
// }
}
I recently commented out the bean annotation to see if that was causing an issue.
Thank you for any help in advance!
You are getting this exception because your class TestRepo is part of repo package, which is not the sub-package hierarchy of Application class package. #SpringBootApplication defines an automatic component scan on the packages which are subpackages of your main class i.e Application. If you want to resolve this issue without changing your package hierarchy add below line with #SpringBootApplication:
#ComponentScan({"repo","your.application.class.package"}) //// add the names of the packages where the controllers, services, repositories beans are stored
I've been using Spring with MyBatis and it's been working really well for a single database. I ran into difficulties when trying to add another database (see reproducible example on Github).
I'm using Spring Java configuration (i.e. not XML). Most of the examples I've seen show how to achieve this using XML.
I have two data configuration classes (A & B) like this:
#Configuration
#MapperScan("io.woolford.database.mapper")
public class DataConfigDatabaseA {
#Bean(name="dataSourceA")
public DataSource dataSourceA() throws SQLException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriver(new com.mysql.jdbc.Driver());
dataSource.setUrl("jdbc:mysql://" + dbHostA + "/" + dbDatabaseA);
dataSource.setUsername(dbUserA);
dataSource.setPassword(dbPasswordA);
return dataSource;
}
#Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSourceA());
return sessionFactory.getObject();
}
}
Two mappers, and a service that autowires the mappers:
#Service
public class DbService {
#Autowired
private DbMapperA dbMapperA;
#Autowired
private DbMapperB dbMapperB;
public List<Record> getDabaseARecords(){
return dbMapperA.getDatabaseARecords();
}
public List<Record> getDabaseBRecords(){
return dbMapperB.getDatabaseBRecords();
}
}
The application won't start:
Error creating bean with name 'dataSourceInitializer':
Invocation of init method failed; nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [javax.sql.DataSource] is defined:
expected single matching bean but found 2: dataSourceB,dataSourceA
I've read that it's possible to use the #Qualifier annotation to disambiguate the autowiring, though I wasn't sure where to add it.
Can you see where I'm going wrong?
If you want to use two data sources at same time and they are not primary and secondary, you should disable DataSourceAutoConfiguration by #EnableAutoConfiguration(excludes = {DataSourceAutoConfiguration.class}) on your application annotated by #SpringBootApplication. Afterwards, you can create your own SqlSessionFactory and bundle your own DataSource. If you also want to use DataSourceTransactionManager, you should do that too.
In this case, you haven't disabled DataSourceAutoConfiguration, so spring framework will try to #Autowired only one DataSource but got two, error occurs.
As what I've said before, you should disable DataSourceAutoConfiguration and configure it manually.
You can disable data source auto configuration as following:
#SpringBootApplication
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class YourApplication implements CommandLineRunner {
public static void main (String... args) {
SpringApplication.run(YourApplication.class, args);
}
}
And if you are really want to use multiple databases at same time, I suggest you to registering proper bean manually, such as:
package xyz.cloorc.boot.mybatis;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;
#Configuration
public class SimpleTest {
private DataSource dsA;
private DataSource dsB;
#Bean(name = "dataSourceA")
public DataSource getDataSourceA() {
return dsA != null ? dsA : (dsA = new BasicDataSource());
}
#Bean(name = "dataSourceB")
public DataSource getDataSourceB() {
return dsB != null ? dsB : (dsB = new BasicDataSource());
}
#Bean(name = "sqlSessionFactoryA")
public SqlSessionFactory getSqlSessionFactoryA() throws Exception {
// set DataSource to dsA
return new SqlSessionFactoryBean().getObject();
}
#Bean(name = "sqlSessionFactoryB")
public SqlSessionFactory getSqlSessionFactoryB() throws Exception {
// set DataSource to dsB
return new SqlSessionFactoryBean().getObject();
}
}
#Repository
public class SimpleDao extends SqlSessionDaoSupport {
#Resource(name = "sqlSessionFactoryA")
SqlSessionFactory factory;
#PostConstruct
public void init() {
setSqlSessionFactory(factory);
}
#Override
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
public <T> T get (Object id) {
return super.getSqlSession().selectOne("sql statement", "sql parameters");
}
}
In the end, we put each mapper in its own folder:
src/main/java/io/woolford/database/mapper/a/DbMapperA.java
src/main/java/io/woolford/database/mapper/c/DbMapperB.java
We then created two DataConfig classes, one for each database. The #MapperScan annotation resolved the expected single matching bean but found 2 issue.
#Configuration
#MapperScan(value = {"io.woolford.database.mapper.a"}, sqlSessionFactoryRef="sqlSessionFactoryA")
public class DataConfigDatabaseA {
It was necessary to add the #Primary annotation to the beans in one of the DataConfig classes:
#Bean(name="dataSourceA")
#Primary
public DataSource dataSourceA() throws SQLException {
...
}
#Bean(name="sqlSessionFactoryA")
#Primary
public SqlSessionFactory sqlSessionFactoryA() throws Exception {
...
}
Thanks to everyone who helped. No doubt, there's more than one way to do this. I did try #Qualifier and #EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) as recommended by #eduardlofitskyi and #GeminiKeith, but that generated some further errors.
In case it's useful, the solution that worked for us is posted here: https://github.com/alexwoolford/mybatis-spring-multiple-mysql-reproducible-example
You can use #Qualifier annotation
The problem is that you have two the same type beans in Spring container. And when you try autowire beans, Spring cannot resolve which bean inject to field
The #Qualifier annotation is the main way to work with qualifiers. It can be applied alongside #Autowired or #Inject at the point of injection to specify which bean you want to be injected.
So, your DbService should look like this:
#Service
public class DbService {
#Autowired
#Qualifier("dataSourceA")
private DbMapperA dbMapperA;
#Autowired
#Qualifier("dataSourceB")
private DbMapperB dbMapperB;
public List<Record> getDabaseARecords(){
return dbMapperA.getDatabaseARecords();
}
public List<Record> getDabaseBRecords(){
return dbMapperB.getDatabaseBRecords();
}
}
I had the same issue and could not start my Spring Boot application, and by renaming the offending class and all the layers that dealt with it, strangely the application started successfully.
I have the classes UOMService, UOMServiceImpl UOMRepository and UOMRepositoryImpl. I renamed them to be UomService, UomServiceImpl, UomRepository and UomRepositoryImpl and that solved the problem!
I am trying to get Cucumber working with Spring. In our code, we are already using java based Spring configuration. I am having trouble getting it to work in the following scenario. Can someone please help?
Today , in our integration test classes we use #ContextConfiguration for each class and provide the config class that is declared with in that integration test class for loading the beans. Config class is annotated with #Configuration. Same bean could be instantiated differently in 2 different classes Config classes used in 2 different integration test classes.
So when I use Cucumber, since the Contextconfiguration differs on different classes, it looks for 'Cucumber.xml' . In the xml file, I am using component-scan to scan the cucumber step definition classes by giving the package name that these classes use (both classes have same package name) . Since all beans gets loaded in same context, Cucumber is failing to load the beans when it finds the same bean defined in these different config classes .
How do I get over this problem of creating same bean but in different ways and use them in different classes?
Please note that I am not looking for a solution that creates lot of churn from our existing coding practices, so having per-test-xml file is not an option for me.
Here is how our code looks:
Class NameAndAddressProviderIntegrationTestSteps :-
#ContextConfiguration(locations="classpath:cucumber.xml")
public class NameAndAddressProviderIntegrationTestSteps {
#Configuration
#Import({
xyz.class,
abc.class,
NameAndAddressProvider.class
})
#ImportResource({
"file:configuration/spring-configuration/abc.xml",
"file:configuration/spring-configuration/xyz.xml"
})
public static class Config {
#Bean
AccountHolderDataMap dataMap() {
AccountHolderDataMap data = new AccountHolderDataMap();
data.put(ID,
new AccountHolderData(customerID));
data.get(customerID).setCustomerplaceID(testCustomerplaceID);
return data;
}
}
#Inject
private NameAndAddressProvider provider;
#When("^I call nameandAddress provider with a 'customerId'$")
public void i_call_nameandAddress_provider_with_a_customerId() throws DependencyException {
System.out.println("Entering when method");
names = provider.getNames(customerID);
System.out.println(provider.toString());
}
......
}
Class AddressProviderIntegrationTestSteps:-
#ContextConfiguration(locations="classpath:cucumber.xml")
public class AddressProviderIntegrationTestSteps {
#Configuration
#Import({
abc.class,
xyz.class,
AddressesProvider.class
})
#ImportResource({
"file:configuration/spring-configuration/test-environment.xml",
"file:configuration/spring-configuration/test-logging-config.xml"
})
public static class Config {
#Bean
#DependsOn("Environment")
AccountHolderDataMap data() {
AccountHolderDataMap data = new AccountHolderDataMap();
data.put(testCustomerID,
new AccountHolderData(testCustomerID, testCustomerplaceID,businessType));
return data;
}
}
private static final String testCustomerID = "1234";
private static final String testMarketplaceID = "abc";
#Inject
private AddressesProvider provider;
#When("^I call AddressesProvider provider with a 'CustomerID'$")
public void i_call_AddressesProvider_provider_with_a_CustomerID() throws Throwable {
List<Address> addresses = provider.getAddresses(testCustomerID);
Log.info(addresses.get(0).toString());
assertTrue(addresses.size()==1);
}
}
And here is the nested exception I am getting:-
"nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [....AccountHolderDataMap] is defined: expected single matching bean but found 2: dataMap,data"
Appreciate your help!
I've managed multiple sources for bean-definitions. You can use this at a starting point (or others in the internet as your question is quite old)
I am using spring4, see my other cucumer post for the pom
At the stepdefs use a config.class
#ContextConfiguration(classes = { CucumberConfiguration.class })
public class StepdefsTest123 {
#Autowired bean; // from cucumberBeanContext.xml
#When("^A$")
public void a() throws Throwable {
System.out.println(bean.getFoo());
}
}
in the config-class add aditional beandefinitions
#Configuration
#ComponentScan(basePackages = "package.here.cucumber")
#ImportResource("classpath:cucumberBeanContext.xml")
public class CucumberConfiguration {
// nothing to do here
}