Spring Boot - EnableAutoConfiguration with Exclude not working - java

I am using the latest spring boot version and I am trying to setup an application but I want to disable the DataSource configuration. My configuration class looks like this:
#Configuration
#ComponentScan
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class ApiApplicationConfig { }
but when I run the application, I am getting the following stacktrace:
Caused by: org.springframework.beans.factory.BeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath.
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.getDriverClassName(DataSourceProperties.java:137)
at org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$NonEmbeddedConfiguration.dataSource(DataSourceAutoConfiguration.java:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 31 more
Am I missing anything in my configuration to completely disable datasource configuration? I will be manually setting up a DataSource, so I dont want spring to handle this for me.

This seems to be a weird situation where DataSourceAutoConfiguration.NonEmbeddedDataSourceCondition finds a DataSource class loader, but no DataSource. We had this problem with spring-boot 1.2.2 while running an integration test.
Anyway, we ran gradle dependencies to find out what was pulling in tomcat-jdbc and ended up replacing our spring-boot-jdbc dependency with plain spring-jdbc. If you don't have tomcat-jdbc in your dependencies, it may help to set a breakpoint in DataSourceAutoConfiguration.NonEmbeddedDataSourceCondition.getDataSourceClassLoader() to find out what driver it finds.

When you manually configure your datasource, spring Boot will use your configuration and wouldn't try to initialize embedded datasource.
BTW, Spring boot by default uses these properties from application.properties to create datasource bean:
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
Take a look at this section of Spring Boot docs for more details about data source auto-configuration

The only thing that helped my exclusion problem was to exclude the tomcat jdbc dependency from the spring configuration:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>

I had an issue when using #Configuration, #EnableAutoConfiguration and #ComponentScan while trying to exclude specific configuration classes, the thing is it didn't work!
Eventually I solved the problem by using #SpringBootApplication, which according to Spring documentation does the same functionality as the three above in one annotation.
#SpringBootApplication(exclude= {Foo.class})
public class MySpringConfiguration {}

#Configuration
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
By using this we can disable the spring boot embedded database configuration.

Its because when you disable the datasource config, spring boot uses in-memory database which is not present in your classpath. You have to add in-memory database dependency in your classpath -
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
This is the same issue occurs when you using #DataJpaTest for testing.

Related

Spring Cloud Configuration - Access shared properties file in all microservices

Inside my spring cloud config server application.properties. I have passed #EnableConfigServer in my application class
spring.application.name=CONFIG_SERVER
server.port=1080
spring.cloud.config.server.git.uri=PATH_TO_GITHUB_REPO
spring.cloud.config.server.git.username=USNM
spring.cloud.config.server.git.password=PWD
spring.cloud.config.server.git.skip-ssl-validation=true
Inside my git repo application.properties
third-party-cred=MY_VALUE
In my spring cloud config client bootstrap.properties
server.port=1081
spring.application.name=MY_SERVICE
spring.cloud.config.uri=http://localhost:1080
I am trying to access property present in git repo using #Value inside my microservice but it is giving error Could not resolve placeholder 'third-party-cred' in value "${third-party-cred}"
Solution
bootstrap.properties is not enable by default. Please add this dependency inside your microservice.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

Type JdbcDaoSupport cannot be resolved. It is indirectly referenced from required .class files error

I wanted to follow this answer from SO and tried to add the following code:
public class CustomJdbcUserDetailsService extends JdbcDaoImpl {
#Override
public List<GrantedAuthority> loadUserAuthorities(String username) {
return super.loadUserAuthorities(username);
}
}
in my Spring-Boot Project. Sadly I get the output:
The type org.springframework.jdbc.core.support.JdbcDaoSupport cannot be resolved. It is indirectly referenced from required .class files
So on research I tried to add some new dependencies (like suggested here)
e.g.:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
but it does not help. I tried to refresh (clean) the project but nothing changed. Can someone relate to this issue? I am using Spring Tool Suite btw.
Since you are using SpringBoot ,you can simply add the JDBC starter to your pom.xml in order to have JDBC support.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
It will transitively give you spring-jdbc , spring-tx and HikariCP
You also need to include the JDBC driver in your pom.xml depending on what DB you are using.
Also remember to configure the DB access info in your application.properties , for example in case of Postgresql:
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/
spring.datasource.username=admin
spring.datasource.password=password
spring.datasource.driver-class-name=org.postgresql.Driver
You can try below steps in order:
Add spring-jdbc dependency
Do maven force update
Delete .m2/repository folder and then do maven update as this can also happen due to corrupted local maven repository

Spring boot - disable Liquibase at startup

I want to have Liquibase configured with my Spring Boot application, so I added dependencies to pom.xml and set the path to master.xml in application.properties. This works fine and Spring Boot runs Liquibase at startup. The problem is that now I want to run Liquibase manually, not at startup of application. Should I completely disable auto-configuration for Liquibase or can I use it and only disable running evaluations at startup?
The relevant property name has changed between Spring versions:
For Spring 4.x.x: the liquibase.enabled=false application property disables Liquibase.
For Spring 5.x.x: the spring.liquibase.enabled=false application property disables Liquibase.
P.S. And for Flyway:
Spring 4.x.x: flyway.enabled=false
Spring 5.x.x: spring.flyway.enabled=false
Add liquibase.enabled=false in your application.properties file
Reference
But if you don't want to use liquibase from application anymore, remove liquibase starter altogether from pom.
If you see on the LiquibaseProperties, there is a prefix like
prefix = "spring.liquibase"
So, My suggestion is to use
spring.liquibase.enabled=false
It solved my problem with spring boot 2.0.0.RC1
I faced an issue where I wasn't able to disable Liquibase from properties for some reason, so this is how I disabled Liquibase with #Bean annotation:
#Bean
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setShouldRun(false);
return liquibase;
}
There is one more programmatic approach.
#EnableAutoConfiguration(exclude = LiquibaseAutoConfiguration.class)
on Application main class
If you want to run Liquibase manually, you could use the liquibase maven plugin. Just add something like this to your pom.xml:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>${liquibase.version}</version>
<configuration>
<changeLogFile>src/main/liquibase/master.xml</changeLogFile>
<propertyFile>src/main/liquibase/liquibase.properties</propertyFile>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
</configuration>
</plugin>
You can take a look at the plugin documentation for the configuration details.
And don't use the liquibase support from Spring Boot, as it is only meant to be used in runtime. Just remove the liquibase starter and/or any related dependencies as you'll only need the maven plugin.
You can use the spring.liquibase.enabled=true/false
Whilst the documented Spring Boot solution is spring.liquibase.enabled=false, it didn't work for me. To disable liquibase you can also use the following property:
liquibase.shouldRun=false
I passed this as a command line parameter when launching the Spring Boot jar
-Dliquibase.shouldRun=false
see https://docs.liquibase.com/parameters/should-run.html

Spring boot inject mongodb datasource

I am trying to deploy a spring boot application connected to a mongodb instance to cloud foundry.
cf create-service MongoService default my-mongo
cf push myapp --no-start
cf bind-service myapp my-mongo
cf start myapp
The connection details to the mongodb instance are in the VCAP_SERVICES environment variable. When deploying my application to cloudfoundry spring boot is trying to access mongodb on localhost:27017 and obviously fails.
I would like to parse the VCAP_SERVICES environment variable, construct some mongodb connection details from it and provide this as a spring bean. Which class should I use for these configuration details?
With Spring Boot, you don't need to manually parse VCAP_SERVICES. If you are using MongoTemplate or MongoRepository, it will automatically connect to the bound instance.
Make sure that you have spring-boot-starter-parent identified as the parent artifact in your pom.xml.
You can add the following to your pom.xml to ensure that the cloud connector code is getting picked up:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cloud-connectors</artifactId>
</dependency>
Of course, you also need the MongoDB Spring Data dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
You may want to try setting up the configuration parameters, like a workaround I had to implement with MySQL, check this question.
For me it all came down to properly defining following properties:
spring:
datasource:
url: jdbc:mysql://${vcap.services.mydb.credentials.host}:${vcap.services.mydb.credentials.port}/${vcap.services.mydb.credentials.name}
driver-class-name: com.mysql.jdbc.Driver
username: ${vcap.services.mydb.credentials.user}
password: ${vcap.services.mydb.credentials.password}

Issues Converting Mule Tomcat WAR to Spring Boot

I've been going through the process of converting my Mule project to a Spring Boot application, and have hit a snag I can't seem to figure out.
I'm pretty new to Spring Boot so I'm not sure if my issues lie with it, or with the way I'm doing my mule stuff.
Here is my sample project I've been trying to convert: https://github.com/JustinBell/mule-webapp-example
When I deploy this to a tomcat instance it works great, the issue comes when I try to run it as a Spring Boot application I'm getting this exception:
ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
Just as a note I'm moving from mule 3.6.1 to 3.7.0-M1 as that's required (from my understanding) to use Spring Boot.
I've tried looking around for support on this issue which seems to pretty common, but none of the suggestions I've found have solved the issue.
Thanks for any help with these issues!
There are a few things that aren't quite right in your code as it stands.
If you want to build a web app with Spring Boot, you'll typically want to add a dependency on spring-boot-starter-web. This provides, among other things, the embedded servlet container:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
Your app's dependency on org.mule.transports:mule-transport-servlet pulls in a very old version of Tomcat's Coyote module. You need to exclude this to avoid it clashing with the up-to-date dependency that's provided by spring-boot-starter-web:
<dependency>
<groupId>org.mule.transports</groupId>
<artifactId>mule-transport-servlet</artifactId>
<version>${mule.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>coyote</artifactId>
</exclusion>
</exclusions>
</dependency>
Your Application class is trying to run MuleContextInitializer which it also declares as a bean. It should be running Application.class:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
// ...
}
Your Application class is also in the default package. You should avoid using the default package as it will cause Spring Boot to scan then entire classpath looking for your application's classes and configuration. Moving it into a package of its own to stop this from happening.
Lastly, the app fails to launch as it's looking for a file named mule-config.xml. Renaming mule-webapp-demo.xml to mule-config.xml addresses this.
I believe autodelete is an Enterprise feature, perhaps you are using ftp rather than ftp-ee.

Categories