Unable to externalize Hikari properties with Spring Cloud Config in Client - spring-boot

I have this property file which I store in a GitHub repo:
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.jdbcUrl=*DB URL*
spring.datasource.username=*USERNAME*
spring.datasource.password=*ENCRYPTED PASSWORD*
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.maximum-pool-size=10
My config server pulls up the details from this repo.
Now I have a client that requires these properties to configure the HikariDataSource.
but when I start the client I get the following Error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Cannot determine embedded database url for database type NONE
Action:
If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
Seems to me like Hikari is unable to get these properties at start-up.
I was configuring my Hikari DataSource like so in my config class:
#Bean
#ConfigurationProperties("spring.datasource")
public HikariDataSource dataSource() {
return (HikariDataSource) DataSourceBuilder.create().type(HikariDataSource.class).build();
}
After removing this bean I still get the same error.
Any idea about what I should be doing here?
Thanks.

I was able to fix this by adding #EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) to the main class.

Related

Error setting custom trust store for Eureka Discovery client by overriding DiscoveryClient.DiscoveryClientOptionalArgs

I am upgrading a spring-boot project from an old version (2.2.9.RELEASE + Spring Cloud HOXTON.SR12) to v2.6.1 + Spring Cloud 2021.0.0
The issue I am currently hitting is with Trust Store enabled Eureka clients. In my old version, all eureka registering applications would use
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; and be tagged with
#EnableDiscoveryClient
To use a custom trust store, I'd then include the following beans in a configuration class:
#Bean
public DiscoveryClient.DiscoveryClientOptionalArgs getTrustStoredEurekaClient(SSLContext sslContext) {
DiscoveryClient.DiscoveryClientOptionalArgs args = new DiscoveryClient.DiscoveryClientOptionalArgs();
args.setSSLContext(sslContext);
return args;
}
#Bean
public SSLContext sslContext() throws Exception {
return new SSLContextBuilder().loadTrustMaterial(new File(trustStore).toURI().toURL(), trustStorePassword.toCharArray()).build();
}
using import com.netflix.discovery.DiscoveryClient;
Following the upgrade, any microservice which attempts to use this custom truststore will not start, with the error thrown below:
*************************** APPLICATION FAILED TO START
Description:
Field optionalArgs in
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration
required a bean of type
'com.netflix.discovery.AbstractDiscoveryClientOptionalArgs' that could
not be found.
The injection point has the following annotations:
#org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type
'com.netflix.discovery.AbstractDiscoveryClientOptionalArgs' in your
configuration.
It doesn't seem to matter if I try to autowrire in a separate bean of type DiscoveryClientOptionalArgs and set the context to this, and I am currently unable to resolve this.
I could solve this by setting the following in the gateway's application.properties:
eureka.client.tls.enabled=true
eureka.client.tls.key-store=file:<path-to-key-store>
eureka.client.tls.key-store-password=<password>
eureka.client.tls.keyStoreType=PKCS12
eureka.client.tls.keyPassword=<password>
eureka.client.tls.trust-store=file:<path-to-trust-store>
eureka.client.tls.trust-store-password=<password>
What's not clear to me is why a keystore in addition to the truststore needs to be set (as above, it was only necessary to configure a trust store for the SSL context of the DiscoveryClient override for the previous versions using Zuul), which suggests I haven't fully understood what's actually happening here.

SpringBoot and setting system properties

I develop SpringBoot app that conntects to Oracle Coherence cluster. App, as coherence node need some JVM properties to connect to cluster. I wanted to set this properties (taken from properties file) in spring boot custom starter. I set system properties in #Configuration class and I can read those without problem but coherence doesn't see one property tangosol.pof.enabled and it fails. When I call System.getProperty(..) it is there but not working (property is not seen by coherence).
It works when I #Autowire configuration class in some other bean in my application or when I have this configuration class not in spring boot starter but in my application.
This is my code:
Configuration class in starter (it works)
#Configuration
#PropertySource("coherence-app.properties")
public class EnvironmentConfig {
public static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentConfig.class);
public EnvironmentConfig(Environment environment, ConfigurableApplicationContext ctx){
Properties props = new Properties();
ConfigsHelper.TANGOSOL_COHERENCE_CONFIGS.stream()
.forEach(prop -> props.setProperty(prop, environment.getProperty(prop)));
if (!ConfigsHelper.setTangosolCoherenceProperties(props)){
LOGGER.error("Can't set coherence props");
System.exit(1);
}
}
}
Then when I try to connect to cluster:
CacheFactory.ensureCluster();
I have error:
2017-08-09 13:17:56.049/7.494 Oracle Coherence GE 12.2.1.0.2
(thread=Cluster, member=n/a): Failed to deserialize the config Message
received from member 1. This member is configured with the following
serializer: com.tangosol.io.DefaultSerializer
{loader=sun.misc.Launcher$AppClassLoader#18b4aac2}, which may be
incompatible with the serializer configured by the sender.
java.io.StreamCorruptedException: invalid type: 100 at
com.tangosol.util.ExternalizableHelper.readObjectInternal(ExternalizableHelper.java:2477)
at
com.tangosol.util.ExternalizableHelper.readObject(ExternalizableHelper.java:2464)
at
com.tangosol.io.DefaultSerializer.deserialize(DefaultSerializer.java:66)
at
com.tangosol.coherence.component.util.daemon.queueProcessor.Service.readObject(Service.CDB:1)
at
com.tangosol.coherence.component.net.Message.readObject(Message.CDB:1)
at
com.tangosol.coherence.component.util.daemon.queueProcessor.service.grid.ClusterService$ServiceJoining.read(ClusterService.CDB:14)
at
com.tangosol.coherence.component.util.daemon.queueProcessor.service.Grid.deserializeMessage(Grid.CDB:20)
at
com.tangosol.coherence.component.util.daemon.queueProcessor.service.Grid.onNotify(Grid.CDB:21)
at
com.tangosol.coherence.component.util.daemon.queueProcessor.service.grid.ClusterService.onNotify(ClusterService.CDB:3)
at com.tangosol.coherence.component.util.Daemon.run(Daemon.CDB:45)
at java.lang.Thread.run(Thread.java:748)
It is connected with tangosol.pof.enabled=false property.
Strange is that when I call
System.getProperty("tangosol.pof.enabled")
before ensureCluster it's true.
This code works properly when it's not in starter. Then configuration bean is initializing earlier and works.
Do you have any idea how to solve this problem.

springboot + JDBTemplate (No datasource specified error even though specified in application.properties

Application.properties
spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=
i placed this application.properties in resources folder.
Java Class
#Component
public class data{
#Autowired
private JdbcTemplate jdbcTemplate;
public void queryData(){
String sql = "select * from DEPOSIT";
jdbcTemplate = new JdbcTemplate();
jdbcTemplate.execute(sql);
}
}
I am getting
java.lang.Illegal Argument Exception:No Data Source Specified
I am getting this error message even though i specified data source in application.properties
I am using Spring Boot for this task. I Have added almost all the dependencies required in POM.
Not sure why i am not able to access data source. basically trying to access data from DB using Spring boot, MySQL, jdbcTemplate.
Not sure whats wrong here.
Do i have to add anything in the code so that data source can be specified in java class?
Add below properties to your application.properties file. This specifies the data source for your application. Do check if mysql is running on your machine before starting your application.
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=yourusername
spring.datasource.password=yourpassword
For additional information refer to below link:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html

Spring Boot JPA Connection Closed after period of inactivity

I have a spring boot application that is deployed to Azure. This application uses JPA to connect to a SQL Server database. Everything seems to work nicely, until after ~30 minutes of inactivity. My guess is the database is closing the connection and the spring boot (tomcat) container isn't properly handling this situation.
I'm injecting the datasouce properties via:
#Bean
#Primary
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource getDataSource() {
return DataSourceBuilder.create().build();
}
My application.properties are:
spring.datasource.url=jdbc:sqlserver://xxxxxx:1433;database=xxxxxx
spring.datasource.username=xxxxxxx
spring.datasource.password=xxxxxxxx
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.tomcat.test-on-borrow=true
spring.datasource.tomcat.validation-query=SELECT 1
spring.datasource.tomcat.validation-interval=0
spring.datasource.tomcat.removeAbandoned=true
spring.datasource.tomcat.removeAbandonedTimeout=120
spring.datasource.tomcat.timeBetweenEvictionRunsMillis=34000
spring.datasource.tomcat.minEvictableIdleTimeMillis=55000
spring.datasource.tomcat.initialSize=4
spring.datasource.tomcat.maxActive=16
However after a period of inactivity i'm getting SQLExceptions:
com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
I'm trying to determine the cause of this. I'm guesses connection validation isn't working correctly, but as I understand this, the connection should be validate by tomcat before the application is allowed to use it. Any help would be greatly appreciated.

How to disable H2's DATABASE_TO_UPPER in Spring Boot, without explicit connection URL

I'm aware that H2 has a boolean property/setting called DATABASE_TO_UPPER, which you can set at least in the connection URL, as in: ;DATABASE_TO_UPPER=false
I’d like to set this to false, but in my Spring Boot app, I don’t explicitly have a H2 connection URL anywhere. Implicitly there sure is a connection URL though, as I can see in the logs:
o.s.j.d.e.EmbeddedDatabaseFactory: Shutting down embedded database:
url='jdbc:h2:mem:2fb4805b-f927-49b3-a786-2a2cac440f44;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false'
So the question is, what's the easiest way to tell H2 to disable DATABASE_TO_UPPER in this scenario? Can I do it in code when creating the H2 datasource with EmbeddedDatabaseBuilder (see below)? Or in application properties maybe?
This is how the H2 database is explicitly initialised in code:
#Configuration
#EnableTransactionManagement
public class DataSourceConfig {
#Bean
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScripts("db/init.sql", "db/schema.sql", "db/test_data.sql")
.build();
}
}
Also, I'm telling JPA/Hibernate not to auto-generate embedded database (without this there was an issue that two in-memory databases were launched):
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=none
You can't w\ the generateUniqueName, but if you call setName("testdb;DATABASE_TO_UPPER=false") you can add parameters. I doubt this is officially supported, but it worked for me.
The spring code that generates the connection url is like this:
String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false", databaseName)
You may want abandon using explicit creation via EmbeddedDatabaseBuilder. Spring Boot creates H2 instance automatically based on configuration. So I would try this in application.properties:
spring.datasource.url=jdbc:h2:file:~/testdb;DATABASE_TO_UPPER=false

Resources