Spring-boot, by database platform custom property - java

I want to have spring boot init-sql dynamic property by vendor or platform. Is this possible?
spring.datasource.tomcat.mysql-initSQL=mysql query
spring.datasource.tomcat.h2-initSQL=h2 query
I do know that is possible with other properties for example with flyway migrations:
flyway.locations=db/migration/{vendor}
or with sql initilization file
schema-${platform}.sql

You can do this using the Spring Profiles.
Create 2 profiles.
1) H2 2) MySQL
Create two init sql files in your class path schema-h2.sql, schema-mysql.sql
Add the spring.datasource.platform property to the profiles
In H2 Profile => "spring.datasource.platform = h2"
In MySQL Profile => "spring.datasource.platform = mysql"
This works as below.
When you application is started with h2 profile (spring.profile.active=h2) then the schema-h2.sql is picked for initialization.
When you application is started with mysql profile (spring.profile.active=h2) then the schema-mysql.sql is picked for initialization.

Related

spring boot + docker + kubernetes

we have three environment as (dev, test and prod) and we have database configuration as below
spring:
jpa:
hibernate:
ddl-auto: update
datasource:
url: ${URL}
username: ${USERNAME}
password: ${PASSWORD}
What i am trying is that i create the jar and then build the image and when deploying in to the kubernetes , i will be using the dev , test and prod respective deployment.yaml in which i will be loading the url,username and password to env so the application will read it during prod start up
So when i am trying to build jar application try to connect to the database and it failed to create the jar.
Please let me know my understanding is wrong or right if wrong then how to correct it and just one thing is that i can't change the process i.e jar+ image + kubernetes
In Kubernetes you can put your configuration in Configmap or Secret. You can package the spring boot application and provide the Configmap entry as env variable of your container as exposed here
Using Spring Cloud Kubernetes you can also read these properties without any configuration on the container as explained in this article

What is the jdbc connection string for h2 database?

I'm trying to connect to an h2 database on my local machine to create a sql DataSource object. I'm running windows and i'm having some issues defining the path to the data file in my projects app.properties file.
Say the path to the local directory data file is:
D:\projects\myproject\data\project
How would one go about defining a connection url for this?
I've tried the many things including the following:
project.db.url = jdbc:h2:tcp://localhost\\\\D:\\projects\\myproject\\data\\project
Then I thought maybe it's the JDBC URL that's the issue, so I tried:
project.db.url = jdbc:h2:tcp:\\\\localhost\\\\D:\\projects\\myproject\\data\\project
Change application.properties to the following:
spring.jpa.open-in-view=true
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
Set H2 Console to the following:
jdbc:h2:mem:testdb
As per documentation, default JDBC connection string is
jdbc:h2:~/test
And, for TCP connection
jdbc:h2:tcp://localhost/~/test
==Update==
But, if you wanted to create/read h2 database to/from specific folder, then it should be
jdbc:h2:tcp://localhost/<path_to_database>
That means,
jdbc:h2:tcp://localhost/D:/myproject/data/project-name
Thanks #Sam for sharing info.
If you are using Spring Boot and don't want to change the default name you can look out for this log statement and copy the JDBC connection info from there:
2021-08-31 20:27:13.295 INFO 12032 --- [ restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:4c0a3d2c-9aab-4c06-ab22-da777660ab4a'
So in this example the connection string is "jdbc:h2:mem:4c0a3d2c-9aab-4c06-ab22-da777660ab4a"

Unable to connect database schema hibernate, gradle

I'm unable to get spring boot to automatically load my database schema when I start it up.
I follow this example: https://spring.io/guides/gs/accessing-data-mysql/#scratch
Here is my application.properties:
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/sakila
spring.datasource.username=root
spring.datasource.password=root1
sakila it is a default database included in mysql
enter image description here
Error:
Unable to create initial connections of pool

How to one-off run #DataJpaTest against real database instead of in-memory with Spring Boot

I am using Spring Boot 1.4.3 and have a whole bunch of tests that are annotated with #DataJpaTest. By default, they run against an in-memory database. I would like to be able to run all of them against a local MySQL temporarily. How can I do this in an easy way?
I have found that I can make it work for one by adding #ActiveProfiles("local") where I have an application-local.properties that points to my local MySQL, but it is just too much work to add that everywhere, run the tests and then remove it again (since I only want to run this manually against MySQL, the CI environment will run against the in memory db).
I am using Maven if that would matter.
UPDATE:
So I have an application-local.properties which contains the db properties to connect to my local MySQL database (Which I use already to run my application against the local MySQL)
Then I right-click in IntelliJ on a package and select "Run all tests in package". In the settings of that run configuration, I add -Dspring.profiles.active=local to the "VM options" field.
I would have thought that this would activate the local profile during the tests, but it does not. If I stop the local MySQL, the tests still run fine.
In the docs it states that you are able to remove the autoconfigured h2 datasource with #AutoConfigureTestDatabase(replace= Replace.NONE) on the test class https://docs.spring.io/spring-boot/docs/1.4.2.RELEASE/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test.
Also you then need to provide your db setup in properties, so that it does not use your app properties e.g.:
# Database
spring.datasource.url=jdbc:mariadb://localhost:3303/test
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
i put this in application.properties in the test package
You can add the profile with the MySQL datasource properties in the same application.properties (or .yml) as:
application.yml
# Existing properties
---
spring:
profiles: h2
# More h2-related properties
---
spring:
profiles: postgres
database:
driverClassName: org.postgresql.Driver
datasource:
url: jdbc:postgresql://localhost:5432/db_dvdrental
username: user_dvdrental
password: changeit
jpa:
database: POSTGRESQL
generate-ddl: false
# More postgres-related properties
and either use #ActiveProfiles("postgres") in an integration test class or start teh container using VM argument as:
java -Dspring.profiles.active=h2 ...
Add application.yml(properties) with jdbc connection into src/test/resources
Run your JPA test with #AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE) - it disables using embedded database (h2), otherwise :
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'dataSource': Invocation of init method
failed; nested exception is java.lang.IllegalStateException: Failed to
replace DataSource with an embedded database for tests. If you want an
embedded database please put a supported one on the classpath or tune
the replace attribute of #AutoConfigureTestDatabase.

How to configure two instance mongodb use spring boot and spring data

The First instance is the embedded MongoDb, the second instance is the live MongoDb.
How do it configure use spring data and spring boot. How to switch easily these instances by properties file??
UPDATE
By default application should start build-in database and store data
into APPDIR/db directory
It should be possible to let application know that external database
will be used by configuring mongo.url property. In this case no need
to start internal database. Instead of that external connection
should be used
Paste some configuration, please.
UPDATE
I have:
<!--Embedded MongoDB-->
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>1.50.5</version>
</dependency>
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.uri=mongodb://localhost/test
spring.data.mongodb.database=test
# EMBEDDED MONGODB (EmbeddedMongoProperties)
#spring.mongodb.embedded.storage.databaseDir=c:/db
#spring.mongodb.embedded.version=3.2.2
if I'll specify external mongodb, then i want embedded mongodb shouldn't to startup.
java.io.IOException: Could not start process: <EOF>
at de.flapdoodle.embed.mongo.AbstractMongoProcess.onAfterProcessStart(AbstractMongoProcess.java:79) ~[de.flapdoodle.embed.mongo-1.50.5.jar!/:?]
at de.flapdoodle.embed.process.runtime.AbstractProcess.<init>(AbstractProcess.java:114) [de.flapdoodle.embed.process-1.50.2.jar!/:?]
at de.flapdoodle.embed.mongo.AbstractMongoProcess.<init>(AbstractMongoProcess.java:53) [de.flapdoodle.embed.mongo-1.50.5.jar!/:?]
at de.flapdoodle.embed.mongo.MongodProcess.<init>(MongodProcess.java:50) [de.flapdoodle.embed.mongo-1.50.5.jar!/:?]
at de.flapdoodle.embed.mongo.MongodExecutable.start(MongodExecutable.java:44) [de.flapdoodle.embed.mongo-1.50.5.jar!/:?]
at de.flapdoodle.embed.mongo.MongodExecutable.start(MongodExecutable.java:34) [de.flapdoodle.embed.mongo-1.50.5.jar!/:?]
at de.flapdoodle.embed.process.runtime.Executable.start(Executable.java:101) [de.flapdoodle.embed.process-1.50.2.jar!/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_05]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_05]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_05]
at java.lang.reflect.Method.invoke(Method.java:483) ~[?:1.8.0_05]
I think you can use Spring profiles.
Here's the documentation.
Spring Profiles provide a way to segregate parts of your application
configuration and make it only available in certain environments.
UPDATE
Note : Everything that I will talk about below is indicated in the documentation I mentioned above... You should really take a look to this documentation. This documentation is great (no joke).
From Appendix A. Common application properties (Spring boot documentation)
Here's how to configuration remote MongoDB instance in application.properties :
# MONGODB (MongoProperties)
spring.data.mongodb.authentication-database= # Authentication database name.
spring.data.mongodb.database=test # Database name.
spring.data.mongodb.field-naming-strategy= # Fully qualified name of the FieldNamingStrategy to use.
spring.data.mongodb.grid-fs-database= # GridFS database name.
spring.data.mongodb.host=localhost # Mongo server host.
spring.data.mongodb.password= # Login password of the mongo server.
spring.data.mongodb.port=27017 # Mongo server port.
spring.data.mongodb.repositories.enabled=true # Enable Mongo repositories.
spring.data.mongodb.uri=mongodb://localhost/test # Mongo database URI. When set, host and port are ignored.
spring.data.mongodb.username= # Login user of the mongo server.
And here's how to configure embedded MongoDB instance in application.properties:
# EMBEDDED MONGODB (EmbeddedMongoProperties)
spring.mongodb.embedded.features=SYNC_DELAY # Comma-separated list of features to enable.
spring.mongodb.embedded.storage.databaseDir= # Directory used for data storage.
spring.mongodb.embedded.storage.oplogSize= # Maximum size of the oplog in megabytes.
spring.mongodb.embedded.storage.replSetName= # Name of the replica set.
spring.mongodb.embedded.version=2.6.10 # Version of Mongo to use.
From Change configuration depending on the environment (Spring boot documentation)
To do the same thing with properties files you can use
application-${profile}.properties to specify profile-specific values.
You can define the MongoDB embedded configuration into application-dev.properties and the MongoDB remote configuration into application-prod.properties
UPDATE II : The return
I'm assuming that you start your embedded MongoDB instance in a class like (from documentation) :
import de.flapdoodle.embed.mongo.config.ArtifactStoreBuilder;
...
MongodStarter starter = MongodStarter.getDefaultInstance();
String bindIp = "localhost";
int port = 12345;
IMongodConfig mongodConfig = new MongodConfigBuilder()
.version(Version.Main.PRODUCTION)
.net(new Net(bindIp, port, Network.localhostIsIPv6()))
.build();
MongodExecutable mongodExecutable = null;
You can assign a spring profile to this class like (from documentation) :
#Configuration
#Profile("dev")
public class ProductionConfiguration {
// ...
}
This way, your embedded MongoDB is started only when you choose dev profile.

Categories