Reputation: 1133
I'm trying to implement Spring Profiles to load a specific class implementation based on the profile specified. The profile to use is specified as a property (spring.profiles.active) within a properties file included in the classpath.
Source here: https://github.com/overattribution/spring-profile-test
public interface MyService {
public void doSomething();
}
@Service
@Profile("preprod")
public class MyServicePreProdImpl implements MyService {
private final Logger LOG = LoggerFactory.getLogger(MyServicePreProdImpl.class);
@Override
public void doSomething() {
LOG.debug("Doing something in " + MyServicePreProdImpl.class.getName());
}
}
@Service
@Profile("prod")
public class MyServiceProdImpl implements MyService {
private final Logger LOG = LoggerFactory.getLogger(MyServiceProdImpl.class);
@Override
public void doSomething() {
LOG.debug("Doing something in " + MyServiceProdImpl.class.getName());
}
}
However, I'm getting the following error: No qualifying bean of type [com.example.profileservice.MyService] found for dependency.
What am I missing?
UPDATE 1:
I'm manually setting the active profile during web application initialization, but I'm still getting the "No qualifying bean found" error. Changes can be seen here: https://github.com/overattribution/spring-profile-test/commit/09175a10b28ea8e5a08b43ad1416431bcf094c9d
Upvotes: 2
Views: 2357
Reputation: 1133
Ok I got it to work. Profiles need to be set within the root context (as opposed to servlet context) during web application initialization. I have done so in my WebAppInitializer class like so:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* Overriding to include setting active profile.
*/
@Override
protected WebApplicationContext createRootApplicationContext() {
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
String[] activeProfiles = getActiveProfiles();
rootAppContext.getEnvironment().setActiveProfiles(activeProfiles);
rootAppContext.register(configClasses);
return rootAppContext;
}
else {
return null;
}
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {
ApplicationConfig.class
};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] {
WebMvcConfig.class
};
}
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return new Filter[] {characterEncodingFilter};
}
protected String[] getActiveProfiles() {
PropertySource propertySource = null;
try {
propertySource = new ResourcePropertySource("classpath:application.properties");
String profilesString = (String) propertySource.getProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME);
return profilesString.split(",");
} catch (IOException e) {
throw new ResourceAccessException("application.properties is not available on the classpath");
}
}
}
Upvotes: 3
Reputation: 8200
A profile is a named logical grouping that may be activated programmatically via ConfigurableEnvironment.setActiveProfiles(java.lang.String...) or declaratively through setting the spring.profiles.active property, usually through JVM system properties, as an environment variable, or for web applications as a Servlet context parameter in web.xml.
I would say that it is not possible to specify active profile as a property within your properties file unless you use Spring Boot that also enables you to set the active profile in application.properties
file.
Try to use one of the options above.
Upvotes: 1