Spring boot with profiles: javax.sql.DataSource' that could not be found - java

I have application.properties in resource dir
server.port = 8888
Pool bean
#Bean
#Profile("local")
protected DataSource dataSource(#Value("${db.driver}") String driver,...) {
HikariConfig configuration = new HikariConfig();//........
return new HikariDataSource(configuration);
}
Config
#EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class,
DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
Skipped other my configs, because all works without profile annotation.
App runs with
-Dspring.profiles.active=local
How to fix this?

based on information provided, you its not able to create the DataSource bean for which 'db.driver' value is required. This property needs to be mentioned in application properties. Try adding this property in propertySource.
or you provide some default value for this property, something like this:
#Value("${db.driver:'defaultValue'}"
if error still exists, pls add stack trace and code-snippet for info to determine whats going on.

Related

Spring DataSource password in separate properties file causes "Failed to determine a suitable driver class"

I have the following Spring configuration
myprefix.systems[0].name=Some System
myprefix.systems[0].datasource.driverclassname=oracle.jdbc.OracleDriver
myprefix.systems[0].datasource.url=jdbc:oracle:thin:#foo:1521/bar
myprefix.systems[0].datasource.username=username
myprefix.systems[0].datasource.password=password
Which is configured into the following class (annotations are lombok and Spring).
#Configuration
#ConfigurationProperties("myprefix")
public class SystemConfig {
#Getter
#Setter
public static class ConfiguredSystem {
private final DataSourceProperties datasource = new DataSourceProperties();
private String name;
public JdbcTemplate getTemplate() {
return new JdbcTemplate(datasource.initializeDataSourceBuilder().build());
}
}
#Getter
private final List<ConfiguredSystem> systems = new ArrayList<>();
#Bean
public List<ConfiguredSystem> allSystems() {
return Collections.unmodifiableList(tradingSystems);
}
}
This works just fine when all the properties are in one application.properties file. The application starts up properly.
I am trying to move the password line into it's own application-secret.properties file, and keep the other properties in the main application.properties file.
myprefix.systems[0].datasource.password=password
I run with
-Dspring.config.location="C:/my/app/dir/conf/"
-Dspring.profiles.active=secret
However, when I do this I get the following error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (the profiles secret are currently active).
| o.s.b.d.LoggingFailureAnalysisReporter [main]
After putting a breakpoint in getTemplate, it seems the DataSourceProperties only contains the password and none of the other properties. I presume Spring cannot do list comprehension (for lack of a better term), myprefix.systems[0]... across different files?
This won't answer why the initial solution (merging myprefix.systems[0].datasource.password) did not work, but you may solve your problem by:
Creating a db.password property in the application-secret.properties
Use ${db.password} in application.properties.

How to load Application.properties file dynamically based on Profile in Spring MVC?

Hi I am learning Spring MVC and I want to know How to load application.properties file dynamically.
I am adding HibernateConfig.java file and AppConfig.java file. I want to load application properties file dynamically using profiles. For Example: dev, test, prod. I have tried to use dynamic name application-{profile}.properties and also tried profile annotation. but not able to understand how they are actually working. I have created a different application.properties files.
application-dev
application-test
application-prod
This property file contains my DB related data. but I don't know how to set profile and how to load PropertySource based on a profile.
I have set the active profile in my appConfig file. Please help me in understanding how to configure profile and application.properties using spring MVC Java-based configuration. I have searched and found many solutions for XML based configuration but I haven't found any proper answer for java based configuration.
HibernateConfig.java
#Configuration
#EnableTransactionManagement
#ComponentScan({"com.project.configuration"})
#PropertySource(value = {"classpath:application.properties"})
public class HibernateConfiguration {
#Autowired
private Environment env;
#Bean
public LocalSessionFactoryBean sessionFactory(){
return sessionFactory;
}
#Bean
public DataSource dataSource(){
/* loading DB */
return dataSource;
}
#Bean
public Properties hibernateProperties(){
}
}
AppConfig.java
#Override
public void onStartup(ServletContext servletContext) throws ServletException
{
super.onStartup(servletContext);
servletContext.setInitParameter("spring.profiles.active", "dev");
}
I think you cant set this parameter at that time, its already too late. You have to start the app with specified profile (or set it in bootstrap file) . You can pass it as an argument or place it in:
application.properities
Under key: spring.profiles.active
When you set this to 'dev' it will read main application.properities and then the profile one. More about how to set it:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html

How to load property file based on spring profiles

How to create project architecture to support multiple envionment. Each environment will have different datasource from different property file like(dev-propertfile,test-propertyFil,Production-propertyfile) with help of spring's
org.springframework.core.env.Environment;
I'll give step by step procedure for Spring boot applications.
Inside /src/main/resources/application.properties mention spring.profiles.active=dev (or Prod)
Create /src/main/resources/application-dev.properties and give your custom dev configurations here.
Create /src/main/resources/application-prod.properties and give your custom prod configurations here.
Run.
Put property file in same location as application.property and follow
the naming convention application-{profile}.properties like
application-dev.properties,application-test.properties,
application-prod.properties
And in application.properties set spring.profiles.active=dev,test etc
For Spring Boot applications it will work easily even by using a YAML File
spring:
profiles: dev
property: this is a dev env
---
spring:
profiles: prod
property: this is a production env
---
However, for a Spring MVC application, it needs more work. Have a look at this link
Basically, it involves 2 steps
Get the Spring Profile within servlet context
If you have set the profile on the server and want it to retrieve it within your application you can use System.getProperty or System.getenv methods.
Here is the code which fetches the profile and defaults it to a local profile, if no profile has been found.
private static final String SPRING_PROFILES_ACTIVE = "SPRING_PROFILES_ACTIVE";
String profile;
/**
* In local system getProperty() returns the profile correctly, however in docker getenv() return profile correctly
* */
protected void setSpringProfile(ServletContext servletContext) {
if(null!= System.getenv(SPRING_PROFILES_ACTIVE)){
profile=System.getenv(SPRING_PROFILES_ACTIVE);
}else if(null!= System.getProperty(SPRING_PROFILES_ACTIVE)){
profile=System.getProperty(SPRING_PROFILES_ACTIVE);
}else{
profile="local";
}
log.info("***** Profile configured is ****** "+ profile);
servletContext.setInitParameter("spring.profiles.active", profile);
}
To access the application-dev.properties, say now you will need to use
#Profile("dev") at the class level
The following code will fetch the application-dev.properties and common.properties
#Configuration
#Profile("dev")
public class DevPropertyReader {
#Bean
public static PropertyPlaceholderConfigurer properties() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[] { new ClassPathResource("properties/common.properties"), new ClassPathResource("properties/application-dev.properties") };
ppc.setLocations(resources);
ppc.setIgnoreUnresolvablePlaceholders(true);
return ppc;
}
}
For accessing say application-prod.properties you have to use #Profile("prod") at the class level. More details can be found here
Take a look at Spring Profile. You will define a set of profiles configurations, like Test, Dev, Production. And then, when you launch the application, you can define wich profile it should use.
Here are some tutorials of how to use.
And this guys had the same problem as yours: How to config #ComponentScan dynamic?
We wanted a way to load different properties from application-<your_env>.properties file depending on the environment (spring profile) in a Spring MVC project, so we implemented a configuration class something like this.
#Configuration
#PropertySource({ "classpath:application-${envTarget:dev}.properties" })
#Data
public class EnvironmentConfig {
#Value("${files.s3.accessId:}")
String s3AccessId;
#Value("${files.s3.accessToken:}")
String s3AccessToken;
.
.
.
}
Then we loaded the EnvironmentConfig in the class where we needed to use it.
While running the application, you just need to pass the -DenvTarget=<your_env>, and it will pick up the application-<your_env>.properties file from src/resources folder of the project.
In the above code, it will load values from application-dev.properties files when no envTarget is specified.
Thanks to Karthikeyan Muthurangam for suggesting this clever solution.

Properties not found with Spring PropertySource

Config
#Configuration
#PropertySources({
#PropertySource("classpath*:properties/test-database.properties")
})
public class DataSourceConfiguration {//...
}
Prop location
D:\Projects\opti\dao\src\main\resources\properties\test-database.properties
D:\Projects\opti\dao\src\main\resources marked as resource folder.
To avoid this kind of problem the issue is to set the jboss.server.config.dir in VM arguments like that :
-Djboss.server.config.dir="[jboss_repository]/server/[default-all-standard-standalone]/conf" –server
and u set PropertySource like this :
#Configuration
#PropertySource("file:${jboss.server.config.dir}/file.properties")
Or you set ur property like that
#PropertySource(value = "classpath:application.properties")
When executed, properties will be imported from the application.properties file, located in the classpath root.
It isn't clear well the your problem considering the details of your question, but a typical problem whit #PropertySource is that yuo have configure a spring bean for manage the properties. In old years in which xml was the best way for configure Spring you used a namespace configuration that configure a spring bean for use proeprties in your bean, mainly with #Value. In java config for benefit of same behaviour you have configure a bean like belove:
#Bean
public static PlaceholderConfigurerSupport propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
I hope that this can help you

Setting a tomcat property using spring boot application properties

I want to set the maxSwallowSize property for boot supplied tomcat.
My application.properties has this line:
server.context-parameters.maxSwallowSize=20971520
Doesn't work for some reason. Other properties like server.port work well.
Debugging the creation in TomcatEmbeddedServletContainerFactory I see that there is a ServletContexInitializer (InitParameterConfiguringServletContextInitializer) with this property but it doesn't seem to be used in any way. (Even though it's in a variable name initializersToUse, ironic ;p)
I don't like the kill of a connection when the upload exceeds the max size set by
multipart.max-request-size=10MB
multipart.max-file-size=2MB
Is this the correct way of setting this property? During debuggin I can see that the IdentityInputFilter has the default value of 2MB.
newest version of org.springframework.boot:spring-boot-starter-web
server.context-parameters (as defined in the documentation can be used to specify the init parameters of the servlet context). maxSwallowSize is a property of the connector. That's a different thing I guess.
We don't have an explicit property for that but you can always configure it via your own TomcatEmbeddedServletContainerFactory.
#Bean
public TomcatEmbeddedServletContainerFactory containerFactory() {
return new TomcatEmbeddedServletContainerFactory() {
protected void customizeConnector(Connector connector) {
super.customizeConnector(connector);
if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol) {
(AbstractHttp11Protocol <?>) connector.getProtocolHandler()).setMaxSwallowSize(value);
}
}
};
}
The configuration like above didn’t help me(I’m using Spring Boot 1.5.10)
I found that the solution was to set
application.properties:
spring.http.multipart.max-file-size=10MB
spring.http.multipart.max-request-size=10MB
and all uploads works OK without configurating Tomcat.
Configuration spring.http.multipart.max-request-size is not the same as maxSwallowSize. The former configures the application and the latter configures the Tomcat server.
So in addition to spring.http.multipart configuration you also should provide configuration for maxSwallowSize, which can simply be done for Spring Boot 2 by setting application property:
server.tomcat.max-swallow-size=100MB

Categories

Resources