Corey
Corey

Reputation: 1133

Spring Profiles not recognized in a Web Application

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

Answers (2)

Corey
Corey

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:

https://github.com/overattribution/spring-profile-test/blob/f895a8bc67dc1f6ba2fcedb58b73a19cc5cf8cf7/src/main/java/com/example/config/WebAppInitializer.java

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

pgiecek
pgiecek

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

Related Questions