brain storm
brain storm

Reputation: 31252

how to set active profile for gradle build of spring boot application?

Here is the DbConfig of my spring-boot application.

@Configuration
@EnableTransactionManagement
public class DBConfig
{

    @Bean
    public LocalSessionFactoryBean sessionFactory()
    {
        ....
    }

    @Bean
    public DataSource aaDataSource()
    {
     .....
    }

public PlatformTransactionManager transactionManager()
    {
        ....
    }

    private Properties hibernateProperties()
    {
       ....
    }
}

Here is my test class

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class ApplicationTests {

    @Test
    public void contextLoads() {
    }
}

Its a gradle project. when I run gradlew clean build locally, I get successful build since my connection settings in application.properties matches my sql connection.

But when I run from jenkins box in our qa environment (the database is qa one), the build fails with following exception.

java.lang.IllegalStateException: Failed to load ApplicationContext
....
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is com.zaxxer.hikari.pool.PoolInitializationException: Exception during pool initialization
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(Abstract
.....
Caused by: com.zaxxer.hikari.pool.PoolInitializationException: Exception during pool initialization
    at com.zaxxer.hikari.pool.BaseHikariPool.initializeConnections(BaseHikariPool.java:544)
    at com.zaxxer.hikari.pool.BaseHikariPool.<init>(BaseHikariPool.java:171)
    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:60)
    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:48)
.....
Caused by: java.sql.SQLException: Access denied for user 'admin1'@'localhost' (using password: YES)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3835)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3771)

I tried running gradlew clean build -Dspring.profiles.active=qa with application-qa.properties in the src/main/resources/ that have qa db settings. The build still failed with same exception.

I have two options.

  1. run the build skipping datasource bean creation. I still need my units tests to be run since they don't rely on datasource

  2. or pass the right settings to gradle build so that application context is created.

I prefer second option to get it working

Upvotes: 2

Views: 11411

Answers (1)

Sam Brannen
Sam Brannen

Reputation: 31207

If your requirement is that you control this externally (i.e., via the command line when launching Gradle), you can then modify your Gradle test task configuration as follows.

test {
    systemProperty("spring.profiles.active", project.properties.get("springProfiles"))
    // ...
}

And then you can set a value for springProfiles like this: gradlew clean build -PspringProfiles=ci (where ci is the name of the profile you want active on the CI server).

The above will make spring.profiles.active available as a JVM system property for your tests; however, you'd still need to set the active profiles for the Spring TestContext Framework.

To do that, you need to annotate your test class with @ActiveProfiles, but instead of passing in static profiles you'd need to implement a custom ActiveProfilesResolver and register it via @ActiveProfiles(resolver = MyCustomResolver.class). Your customer resolver could then read then simply return the value of the spring.profiles.active system property.

Another option is to implement a custom ApplicationContextInitializer that programmatically sets the active profiles (similar to the custom ActiveProfilesResolver). You can configure one of those via @SpringApplicationConfiguration(initializers = MyCustomInitializer.class).

And yet another option would be to programmatically set the active profiles directly in your SpringApplication -- for example, based on a system property or environment variable.

So, you have several options.

Upvotes: 7

Related Questions