Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring profile default behaviour

I have a spring profile "DEV" and thats the only profile I have and I do NOT want to create a "production" profile. So only when profile is "DEV" I would like a certain type of bean for spring security is initiated (which is an in memory guest user and a userdetails bean)

But if no spring profile is provided in my tomcat startup, which is the case in production, I would like my app to continue what it is already doing(using ldap authenticatin provider).

Is there a way to define a "default" bean behaviour without actually needing to provide a profile at start up? Or you can look at my code below and suggest a different solution maybe.

@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth, final AuthenticationProvider provider) throws Exception {

        auth
                .eraseCredentials(false)
                .authenticationProvider(provider)
                .authenticationProvider(jwtConfig.jwtAuthenticationProvider());
}


@Bean
public UserDetailsService userDetailsService() {
    final LdapUserDetailsService ldapUserDetailsService = new LdapUserDetailsService(ldapUserSearch(), ldapAuthoritiesPopulator());
    return new CompositeUserDetailsService(Arrays.asList(technicalUserDetailsService(), ldapUserDetailsService));
}

@Bean
@Profile("DEV")
public UserDetailsService devUserDetailsService() {
 useAnonymous = true;
        InMemoryUserDetailsManagerBuilder b = new InMemoryUserDetailsManagerBuilder()
                .withUser("user").password("password").authorities(ROLE_USER, ROLE_ADMIN).and();

        return new CompositeUserDetailsService(Arrays.asList(b.build(),
                technicalUserDetailsService()));

}
@Bean
public AuthenticationProvider ldapAuthenticationProvider() {
    final BindAuthenticator ba = new BindAuthenticator((BaseLdapPathContextSource) contextSource());
    ba.setUserSearch(ldapUserSearch());
    return new LdapAuthenticationProvider(ba, ldapAuthoritiesPopulator());
}
like image 221
Spring Avatar asked Apr 06 '17 10:04

Spring


People also ask

What is the default profile in spring?

The default profile is always active. Spring Boot loads all properties in application. yml into the default profile. We could rename the configuration file to application-default.

How does Profiles work in Spring Boot?

Spring Boot will automatically load the properties in an application. properties file for all profiles, and the ones in profile-specific . properties files only for the specified profile. In this way, we can easily provide different configurations for different environments.

What is Spring Boot default configuration?

By default, Spring Boot uses the 8080 port number to start the Tomcat. Let us learn how change the port number by using command line properties. Step 1 − After creating an executable JAR file, run it by using the command java –jar <JARFILE>.

Which of the following features are enabled using @SpringBootApplication annotation?

A single @SpringBootApplication annotation can be used to enable those three features, that is: @EnableAutoConfiguration : enable Spring Boot's auto-configuration mechanism. @ComponentScan : enable @Component scan on the package where the application is located (see the best practices)


1 Answers

I think there is a misunderstanding of what @Profile does. Beans marked with @Profile are only loaded when that profile is active, but all other beans (without a @Profile) are still always loaded, regardless of the chosen profile.

I see a few ways to solve this:

1) Mark all those beans with a @Profile("dev") also with @Primary so Spring knows which one to pick when two beans of the same type are loaded (since you donot want to use a production profile).

2) Mark the beans that should not be loaded when profile dev is active with @Profile("!dev") -- only applicable for Spring 3.2 and higher (see https://github.com/spring-projects/spring-framework/commit/bcd44f3798ed06c0704d2a3564b8a9735e747e87).

Or...

3) Use a production profile and simply activate it in for example the web.xml file (something which you probably don't use locally).

Simply create multiple @Configuration classes and mark the entire class with a profile (it also helps to keep related stuff together). A typical example is for the database. Create one configuration class for the production database (something with JNDI and Oracle) and one for local development and testing (HSQLDB).

You mark the JNDI Configuration class with @Profile("production") and the other with @Profile("dev") -- no need to mark individual beans, just split them logically amongst two different @Configuration classes.

This worked really well for us, also when combined with integration testing.

like image 96
john16384 Avatar answered Nov 18 '22 17:11

john16384