I am learning spring-boot by reading tutorials on the official website http://spring.io. When I tried to implement a service discovery client, I got this error information:Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.. I read lots of solutions on Google but none of them helped. Can you give me some advice? I am new to spring-boot.
Here is my code:
- The spring-boot application class
#EnableDiscoveryClient
#SpringBootApplication
public class DiscoveryClientApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(DiscoveryClient.class, args);
}
}
The controller class:
#RestController
public class Controller {
#Autowired
private DiscoveryClient discoveryClient;
#RequestMapping("service-instances/{appName}")
public List<ServiceInstance> serviceInstanceByApplicationName(#PathVariable
String applicationName) {
return this.discoveryClient.getInstances(applicationName);
}
}
And the application.properties
server.port = 20000
eureka.instance.prefer-ip-address = true
eureka.client.register-with-eureka = true
eureka.client.fetch-registry = true
eureka.client.service-url.default-zone = http://localhost:8761/eureka
spring.application.name = service-discovery-client
spring.jpa.hibernate.ddl-auto = create
spring.datasource-url = jdbc:mysql://localhost:3306/spring-test
spring.datasource.username = root
spring.datasource.password = 80966cc9
spring.jpa.database = MYSQL
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
My project is a maven project and the discovery client is a sub-project, it's pom.xml is inherited from the father project. In the father project, I added all dependencies. The two other sub-projects run normally, only this service can't run.
I have a spring boot application, using spring-data-mongodb.
With the following MongoDB config in application.properties, the mongoRepository read/write documents into the correct database: product_db. Everything is correct so far.
#MongoDB Config
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.authentication-database=product_db
spring.data.mongodb.username=demo
spring.data.mongodb.password=demo
spring.data.mongodb.database=product_db
Then I introduced spring-cloud-config, and I moved the exact same MongoDB config to my-service.propertiesso the config client can get these from config server. The weird thing is that now mongoRepository read/write document from/into database: test
Where does spring-cloud-config-server specific the database name? How to config to ask mongoRepository to use the correct database?
Code snippet as following
Config Server
#SpringBootApplication
#EnableDiscoveryClient
#EnableConfigServer
public class ConfigServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServiceApplication.class, args);
}
}
application.properties for config server
server.port=2000
spring.application.name=config-server
eureka.client.service-url.defaultZone=http://localhost:8260/eureka
spring.profiles.active=native
spring.cloud.config.server.native.search-locations=file:///${user.home}/Project/configuration
my-test.properties
server.port=2100
spring.application.name=service-sample
eureka.client.service-url.defaultZone=http://localhost:8260/eureka
logging.level.org.springframework=INFO
#MongoDB Config
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.authentication-database=product_db
spring.data.mongodb.username=demo
spring.data.mongodb.password=demo
spring.data.mongodb.database=product_db
For my-service as the config client:
#EnableDiscoveryClient
#SpringBootApplication
#EnableMongoRepositories(basePackages = "com.mydemo.service.sample.repositories")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
bootstrap.properties for config client:
server.port=2100
spring.application.name=my-service
eureka.client.service-url.defaultZone=http://localhost:8260/eureka
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=config-server
As mentioned before, if I remove the bootstrap.properties, and use the following application.properties file for my-service, everything is good.
server.port=2100
spring.application.name=service-sample
eureka.client.service-url.defaultZone=http://localhost:8260/eureka
logging.level.org.springframework=INFO
#MongoDB Config
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.authentication-database=product_db
spring.data.mongodb.username=demo
spring.data.mongodb.password=demo
spring.data.mongodb.database=product_db
How to programmatically tell Spring Boot to load configuration yaml files from custom location when doing JUNIT Test.
In program, I could use properties of SpringApplicationBuilder to specify my custom yaml file .
#Configuration
#SpringBootApplication
#ComponentScan
public class SampleWebApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(SampleWebApplication.class)
.properties("spring.config.name:application,conf",
"spring.config.location=classpath:/viaenvironment.yaml")
.build().run(args);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
System.out.println(environment.getProperty("app.name"));
}
}
When doing JUNIT Test, how should I configure it?
I'm using spring boot 1.5.1.
Please use this option to set the spring.config.location through #TestPropertySource:
#TestPropertySource(properties = { "spring.config.location = classpath:<path-to-your-yml-file>" }
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?
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
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
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
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.
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);
}
}
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
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 {
}
}
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.
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! =)
In my case the spring-boot-starter-jpa dependency was being loaded from other dependency. I did this to disable the DataSource:
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] +- ....
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>
Exclude DataSourceAutoConfiguration.class in the Application file
import org.springframework.boot.autoconfigure.jdbc. DataSourceAutoConfiguration;
// add exclude
#SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ...
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) {}
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
Also if you use Spring Actuator org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthContributorAutoConfiguration might be initializing DataSource as well.
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
I'm trying to share configuration between Spring Cloud clients with a Spring Cloud config server which have a file-based repository:
#Configuration
#EnableAutoConfiguration
#EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
// application.yml
server:
port: 8888
spring:
profiles:
active: native
test:
foo: world
One of my Spring Cloud client use the test.foo configuration, defined in the config server, and it is configured like below:
#SpringBootApplication
#RestController
public class HelloWorldServiceApplication {
#Value("${test.foo}")
private String foo;
#RequestMapping(path = "/", method = RequestMethod.GET)
#ResponseBody
public String helloWorld() {
return "Hello " + this.foo;
}
public static void main(String[] args) {
SpringApplication.run(HelloWorldServiceApplication.class, args);
}
}
// boostrap.yml
spring:
cloud:
config:
uri: ${SPRING_CONFIG_URI:http://localhost:8888}
fail-fast: true
// application.yml
spring:
application:
name: hello-world-service
Despite this configuration, the Environment in the Spring Cloud Client doesn't contains the test.foo entry (cf java.lang.IllegalArgumentException: Could not resolve placeholder 'test.foo')
However it's works perfectly if i put the properties in a hello-world-service.yml file, in my config server file-based repository.
Maven dependencies on Spring Cloud Brixton.M5 and Spring Boot 1.3.3.RELEASE with spring-cloud-starter-config and spring-cloud-config-server
From Spring Cloud documentation
With the "native" profile (local file system backend) it is
recommended that you use an explicit search location that isn’t part
of the server’s own configuration. Otherwise the application*
resources in the default search locations are removed because they are
part of the server.
So i should put the shared configuration in an external directory and add the path in the application.yml file of the config-server.
// application.yml
spring:
profiles:
active: native
cloud:
config:
server:
native:
search-locations: file:/Users/herau/config-repo
// /Users/herau/config-repo/application.yml
test:
foo: world