Issue
I'm having an issue using Profiles in Spring, basically, we use them to stub some parts of our microservice, which uses both a connection to DB and a connection to another webservice.
Previously I used one stub profile for both the DB and external webservice :
class="lang-java prettyprint-override"> @Configuration
@EnableAutoConfiguration
@Profile("stub")
@ComponentScan(
basePackages = {"com.consumption.backend"},
excludeFilters = {
@ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.consumption.backend.*.persistence.*"),
@ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.consumption.backend.databackendapi.*")
})
public class StubConfiguration {
@Bean
public DataApi consumptionApi() { return new DataStubApi(); }
@Bean
public RefDayDao refDayDao() { return new RefDayInMemoryDao(); }
@Bean
public RefTypeHourDao refTypeHourDao() { return new RefTypeHourInMemoryDao(); }
}
and this works fine, however I would like to separate this stub into two stubs, one for the DB and one for the external webservices to ensure greater flexibility in our tests.
Stub for the DAO:
@Configuration
@EnableAutoConfiguration
@Profile("stubconfv3")
@ComponentScan(
basePackages = {"com.consumption.backend"},
excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.consumption.backend.*.persistence.*")
)
public class StubConfV3Configuration {
@Bean
public RefDayDao refDayDao() { return new RefDayInMemoryDao(); }
@Bean
public RefTypeHourDao refTypeHourDao() { return new RefTypeHourInMemoryDao(); }
}
Stub for the external webservice :
@Configuration
@EnableAutoConfiguration
@Profile("stubdatabackend")
@ComponentScan(
basePackages = {"com.consumption.backend"},
excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.consumption.backend.databackendapi.*")
)
public class StubDataBackendConfiguration {
@Bean
public DataApi consumptionApi() { return new DataStubApi(); }
}
The stub for the DAO seems to work fine, however I seem to have an issue with the external webservice API not excluding the implementation properly:
- If I launch my application with
stub
profile everything works fine - If I launch my application with
stubconfv3
andstubdatabackend
I get an issue with injection, as two classes are found :
Parameter 0 of constructor in com.consumption.backend.service.DataService required a single bean, but 2 were found:
dataBackendApi: defined in file [C:\code\consumption-backend\databackend-api\target\classes\com\consumption\backend\databackendapi\DataBackendApi.class]
consumptionApi: defined by method 'consumptionApi' in class path resource [com/consumption/backend/application/configuration/StubDataBackendConfiguration.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Either the exclusion is not working or there is some tricky thing as it seems to find the .class file in target instead of finding it at runtime in a class loader
Most likely, I do some stupid mistake and am not seeing it ...
EDIT : I noticed if I misstype stubconfv3
profile in StubConfV3Configuration
, the injection issue doesn't appear anymore, so I guess you can't combine exclusionFilters in @ComponentScan
in two different classes...
The first class will do a componentscan on everything but what she excludes, and the second will do the same, so packages excluded by the second class with still be scanned by the first class.
Solution
You could try to annotate your DataBackendApi with
@Profile("!stubdatabackend")
to include it when that profile is not used and exclude it otherwise
Answered By - Johannes
Answer Checked By - Gilberto Lyons (JavaFixing Admin)