189

I am using Spring Boot to develop two applications, one serves as the server and other one is a client app. However, both of them are the same app that function differently based on the active profile. I am using auto configuration feature of Spring Boot to configure my applications.

I want to disable all the database related auto configuration on client app, since it won't be requiring database connection. Application should not try to establish connection with the database, nor try to use any of the Spring Data or Hibernate features. The enabling or disabling of the database auto configuration should be conditional and based on the active profile of the app.

Can I achieve this by creating two different application.properties files for respective profiles?

I tried adding this to my properties file,

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration\
  org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration\
  org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration

But, the application still tries to connect to the database on start. Are those exclusions sufficient for achieving my requirement?

yuva
  • 3,108
  • 4
  • 20
  • 35
  • [This](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-profile-specific-properties) might help. – Rahul Sharma Apr 03 '16 at 16:28
  • Can you disclose your code/configuration? – luboskrnac Apr 03 '16 at 17:53
  • 3
    You can also use your build tool profiles and add the data related dependencies only on one of your profiles. If your package your app using the other profile, since it hasn't the required starter packages present on the classpath, it won't be auto-configured – Ali Dehghani Apr 03 '16 at 18:02

13 Answers13

140

The way I would do similar thing is:

@Configuration
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
@Profile ("client_app_profile_name")
public class ClientAppConfiguration {
    //it can be left blank
}

Write similar one for the server app (without excludes).

Last step is to disable Auto Configuration from main spring boot class:

@SpringBootApplication
public class SomeApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(SomeApplication.class);
    }

    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(SomeApplication.class);
    }
}

Change: @SpringBootApplication into:

@Configuration 
@ComponentScan

This should do the job. Now, the dependencies that I excluded in the example might be incomplete. They were enough for me, but im not sure if its all to completely disable database related libraries. Check the list below to be sure:

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#auto-configuration-classes

starball
  • 20,030
  • 7
  • 43
  • 238
patrykos91
  • 3,506
  • 2
  • 24
  • 30
  • 11
    `@SpringBootApplication` has an `exclude` property, no need for `ClientAppConfiguration`. – Abhijit Sarkar Jan 25 '18 at 10:51
  • Can you do that exclude conditional based on active profile without using ClientAppConfiguration? – patrykos91 Jan 25 '18 at 14:03
  • 1
    Yes. You'd exclude in the `@SpringBootApplication`, and then in the specific package, create a `@Configuration` class which does an `@Import` of the relevant classes and is dependent on `@Profile` or `@Conditional`. That way, you can test each application layer without the autoconfig leaking all over the app. Wanna test DB? Just scan the DB package, configure a mock DB, and you're good to go. – Abhijit Sarkar Jan 26 '18 at 09:23
  • 1
    I am using flyway.. My server fails because it's not able to initialize flyway because of the missing configuration. I tried to add `FlywayAutoConfiguration.FlywayConfiguration.class` but it's not working. Any ideas? ^^ – Stefan Falk Jan 08 '21 at 15:25
129

For disabling all the database related autoconfiguration and exit from:

Cannot determine embedded database driver class for database type NONE

1. Using annotation:

@SpringBootApplication
@EnableAutoConfiguration(exclude = {
    DataSourceAutoConfiguration.class,
    DataSourceTransactionManagerAutoConfiguration.class,
    HibernateJpaAutoConfiguration.class})
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(PayPalApplication.class, args);
    }
}

2. Using Application.properties:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
Jorge López
  • 1,649
  • 1
  • 10
  • 7
  • 7
    the use of Application.properties with Spring Boot 2+ is preferable over the annotation. – Gustavo Rodrigues Feb 10 '20 at 18:29
  • 1
    @GustavoRodrigues can you share some documentation to support your statement? Thanks! – Betlista Mar 04 '20 at 13:31
  • 1
    @Betlista This is because the change that disables the DataSource autoconfiguration can occur in the version of `application.properties` you use for development. The production `application.properties` defines the DataSource. Thus the code is identical in development and production. – Andrew Alcock Oct 29 '20 at 03:26
  • @GustavoRodrigues you can't disable with property because DataSourceAutoconfigurationCondition is triggered on DataSource class available on classpath. – Simon Logic Feb 09 '21 at 15:58
37

Seems like you just forgot the comma to separate the classes. So based on your configuration the following will work:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
    org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
    org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
    org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration

Alternatively you could also define it as follow:

spring.autoconfigure.exclude[0]=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
spring.autoconfigure.exclude[1]=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.autoconfigure.exclude[2]=org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
spring.autoconfigure.exclude[3]=org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration
Julien May
  • 2,011
  • 15
  • 18
25

There's a way to exclude specific auto-configuration classes using @SpringBootApplication annotation.

@Import(MyPersistenceConfiguration.class)
@SpringBootApplication(exclude = {
        DataSourceAutoConfiguration.class, 
        DataSourceTransactionManagerAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class})
public class MySpringBootApplication {         
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApplication.class, args);
    }
}

@SpringBootApplication#exclude attribute is an alias for @EnableAutoConfiguration#exclude attribute and I find it rather handy and useful.
I added @Import(MyPersistenceConfiguration.class) to the example to demonstrate how you can apply your custom database configuration.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
  • 2
    Thanks! This is the most modern answer. Linked to it here: https://konstructcomputers.blogspot.com/2018/10/slimming-down-spring-boot-app-for.html – Joshua Davis Oct 28 '18 at 17:18
12

If using application.yml:

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
      - org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
      - org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration
Bojan Vukasovic
  • 2,054
  • 22
  • 43
10

Way out for me was to add

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})

annotation to class running Spring boot (marked with `@SpringBootApplication).

Finally, it looks like:

@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class Application{

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
 }
ryzhman
  • 674
  • 10
  • 22
8

Another way to control it via Profiles is this:

// note: no @SpringApplication annotation here
@Import(DatabaseConfig.class)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@Configuration
@Import({DatabaseConfig.WithDB.class, DatabaseConfig.WithoutDB.class})
public class DatabaseConfig {

    @Profile("!db")
    @EnableAutoConfiguration(
            exclude = {DataSourceAutoConfiguration.class,   DataSourceTransactionManagerAutoConfiguration.class,
                HibernateJpaAutoConfiguration.class})
    static class WithoutDB {

    }

    @Profile("db")
    @EnableAutoConfiguration
    static class WithDB {

    }
}
D-rk
  • 5,513
  • 1
  • 37
  • 55
  • 1
    Can you tell me how to put a logger inside WithoutDB and WithDB class so that when I start the application print somemessage. Thank you – ankur pramanik Jun 11 '20 at 10:21
3

I had the same problem here, solved like this:

Just add another application-{yourprofile}.yml where "yourprofile" could be "client".

In my case I just wanted to remove Redis in a Dev profile, so I added a application-dev.yml next to the main application.yml and it did the job.

In this file I put:

spring.autoconfigure.exclude: org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration

this should work with properties files as well.

I like the fact that there is no need to change the application code to do that.

Sylvain
  • 639
  • 5
  • 26
2

In my case the spring-boot-starter-jpa dependency was being loaded from other dependency. I did this to disable the DataSource:

  1. Check the dependency tree with mvn dependency:tree
[INFO] com.backend.app:crud-manager:jar:0.1-SNAPSHOT
[INFO] +- ...
[INFO] \- com.backend.app:crud-libraries:jar:0.1-SNAPSHOT:compile
[INFO]    +- org.springframework.boot:spring-boot-starter.data-jpa:jar:2.1.6.RELEASE:compile
[INFO]    +- ....
  1. There was a sub-dependency. Add an exclusion
<dependency>
  <groupId>com.backend.app</groupId>
  <artifactId>crud-libraries</artifactId>
  <exclusions>
    <exclusion> 
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusion>
  </exclusions>
</dependency>
  1. Exclude DataSourceAutoConfiguration.class in the Application file
import org.springframework.boot.autoconfigure.jdbc. DataSourceAutoConfiguration;

// add exclude
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ...
  1. Ensure there is no spring-boot-starter-jpa in pom.xml

** Apart, in case you also need to make it work with spring-boot-starter-batch

In the BatchConfig file:

// add extends DefaultBatchConfig
public class BatchConfig extends DefaultBatchConfig {

//add override
@Override
public void setDataSource(DataSource dataSource) {}
user9869932
  • 6,571
  • 3
  • 55
  • 49
2

By default in Spring, all the defined beans, and their dependencies, are created when the application context is created.

In contrast, when we configure a bean with lazy initialization, the bean will only be created, and its dependencies injected, once they're needed.

spring:
  main:
    lazy-initialization: true
  jpa:
    properties:
      hibernate: # lazy-initialization works with this dialect property to avoid run issues if DB is Down
        dialect: org.hibernate.dialect.Oracle10gDialect
MedElmaachi
  • 916
  • 7
  • 7
1

I add in myApp.java, after @SpringBootApplication

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})

And changed

@SpringBootApplication => @Configuration

So, I have this in my main class (myApp.java)

package br.com.company.project.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class SomeApplication {

public static void main(String[] args) {
    SpringApplication.run(SomeApplication.class, args);
}

}

And work for me! =)

0

I was getting this error even if I did all the solutions mentioned above.

 by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfig ...

At some point when i look up the POM there was this dependency in it

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

And the Pojo class had the following imports

import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id;

Which clearly shows the application was expecting a datasource.

What I did was I removed the JPA dependency from pom and replaced the imports for the pojo with the following once

import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document;

Finally I got SUCCESSFUL build. Check it out you might have run into the same problem

Tadele Ayelegn
  • 4,126
  • 1
  • 35
  • 30
  • This is not a solution to the problem discussed. The issue is not about removing the JPA support from the application all together but rather enable/disable it based on a condition (such as a Spring profile) - without changing the code or Maven project configuration. You were getting the data source related error because, apparently, you forgot to define and activate the Spring profile that would load the "no-datasource" configuration **instead** of loading the DS/JPA-related classes. The JPA libraries should still remain in the distribution. – cvnew Jun 09 '18 at 15:25
  • 1
    I do not think you read my post completely. On the last line i am suggesting it may be similiar issue but not saying that is the answer – Tadele Ayelegn Jun 09 '18 at 18:13
0

Also if you use Spring Actuator org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthContributorAutoConfiguration might be initializing DataSource as well.

Vity
  • 241
  • 3
  • 15