Dropwizard Migrations: dump non public schema to the migrations.xml postgresql - java

As mentioned in dropwizard-migrations documentation, you can dump you existing schema to migrations.xml using command
java -jar hello-world.jar db dump helloworld.yml
But I am using postgresql which can have multiple schemas, so how can I configure my db to always get status/dump of the default schema i am woking on instead of public schema.
I tried changing the search_path for database but that doesn't worked out.

Liquibase has a defaultSchemaName property. I haven't used dropwizard myself but it seems they use JDBI and a yaml based config file for the db connection.
So, have you tried just putting the option defaultSchemaName into your service configuration file like this:
database:
# the name of your JDBC driver
driverClass: org.postgresql.Driver
# the username
user: pg-user
# the password
password: iAMs00perSecrEET
# the JDBC URL
url: jdbc:postgresql://db.example.com/db-prod
# any properties specific to your JDBC driver:
properties:
charSet: UTF-8
defaultSchemaName: <yourSchemaName>

Jens was very close, you need to specify the currentSchema not defaultSchemaName property for the JDBC driver. like:
database:
driverClass: org.postgresql.Driver
# the other attributes
properties:
currentSchema: <yourSchemaName>

Related

Dockerized Spring Application with environment variables

I am currently trying to run a Java Spring application in a Docker container. This has worked without any problems so far. But now I want that in the application.properties there are no fixed values but only placeholders, which are passed as environment variables to the container. According to the Spring Docs this should be possible but when I try this I always get the error that no database connection can be established to the placeholder ${DB_CONFIG} (Caused by: java.lang.RuntimeException: Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrl, ${DB_CONFIG}).
I already tried to pass the application.properties externally, instead of an env file pass the variables directly as Docker environment variable and instead of a custom variable (DB_CONFIG) for the JDBC url pass the Spring variable (SPRING_DATASOURCE_URL). Neither variant worked for me.
I hope I got my point across correctly and you guys can help me out.
For your information: I don't maintain the source code, I just get it from a CI/CD, copy the changed application.properties to its place and compile the project.
KR,
BlackRose01
docker-compose file:
version: '3'
services:
arrowhead-serviceregistry:
container_name: arrowhead-serviceregistry
image: 'openjdk:11-jre-slim-buster'
restart: always
env_file: '.env'
ports:
- 8443:8443/tcp
volumes:
- ./arrowhead-serviceregistry-4.3.0.jar:/service.jar
depends_on:
- mysql
command:
-java -noverify -XX:TieredStopAtLevel=1 -jar /service.jar
application.properties file:
############################################
### APPLICATION PARAMETERS ###
############################################
# Database connection (mandatory)
# Change the server timezone if neccessary
spring.datasource.url=${DB_CONFIG}
spring.datasource.username=${SERVICEREGISTRY_DB_USERNAME}
spring.datasource.password=${SERVICEREGISTRY_DB_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
# use true only for debugging
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto=none
# Service Registry web-server parameters
server.address=0.0.0.0
server.port=${SERVICEREGISTRY_PORT}
domain.name=${SERVICEREGISTRY_ADDRESS}
domain.port=${SERVICEREGISTRY_PORT}
############################################
### CUSTOM PARAMETERS ###
############################################
# Name of the core system
core_system_name=SERVICE_REGISTRY
# Show all request/response in debug log
log_all_request_and_response=${SERVICEREGISTRY_LOG_REQUESTS}
# Service Registry has an optional feature to ping service providers in a fixed time interval,
# and remove service offerings where the service provider was not available
# use this feature (true/false)
ping_scheduled=${SERVICEREGISTRY_PING_ENABLE}
# how much time the Service Registry should wait for the ping response (in milliseconds)
ping_timeout=${SERVICEREGISTRY_PING_TIMEOUT}
# how frequently should the ping happen, in minutes
ping_interval=${SERVICEREGISTRY_PING_INTERVAL}
# Service Registry has an optional feature to automatically remove service offerings, where the endOfValidity
# timestamp field is in the past, meaning the offering expired
# use this feature (true/false)
ttl_scheduled=${SERVICEREGISTRY_TTL_ENABLE}
# how frequently the database should be checked for expired services, in minutes
ttl_interval=${SERVICEREGISTRY_TTL_INTERVAL}
# Interface names has to follow this format <PROTOCOL>-<SECURITY>-<FORMAT>, where security can be SECURE or INSECURE and protocol and format must be a sequence of letters, numbers and underscore.
# A regexp checker will verify that. If this setting is set to true then the PROTOCOL and FORMAT must come from a predefined set.
use_strict_service_intf_name_verifier=${SERVICEREGISTRY_STRICT_INTERFACE_NAMES}
############################################
### SECURE MODE ###
############################################
# configure secure mode
# Set this to false to disable https mode
server.ssl.enabled=${SSL_ENABLED}
server.ssl.key-store-type=${SERVICEREGISTRY_SSL_KEYSTORE_TYPE}
server.ssl.key-store=${SERVICEREGISTRY_SSL_KEYSTORE}
server.ssl.key-store-password=${SERVICEREGISTRY_SSL_KEYSTORE_PASSWORD}
server.ssl.key-alias=${SERVICEREGISTRY_SSL_KEY_ALIAS}
server.ssl.key-password=${SERVICEREGISTRY_SSL_KEY_PASSWORD}
server.ssl.client-auth=${SERVICEREGISTRY_SSL_CLIENT_AUTH}
server.ssl.trust-store-type=${SERVICEREGISTRY_SSL_TRUSTSTORE_TYPE}
server.ssl.trust-store=${SERVICEREGISTRY_SSL_TRUSTSTORE_PATH}
server.ssl.trust-store-password=${SERVICEREGISTRY_SSL_TRUSTSTORE_PASSWORD}
#If true, http client does not check whether the hostname is match one of the server's SAN in its certificate
#Just for testing, DO NOT USE this feature in production environment
disable.hostname.verifier=${SERVICEREGISTRY_DISABLE_HOSTNAME_VERIFIER}
Environment file:
# Basic settings
DB_CONFIG=jdbc:mysql://127.0.0.1:3306/arrowhead?serverTimezone=Europe/Berlin
SSL_ENABLED=false
# Service Registry settings
SERVICEREGISTRY_ADDRESS=127.0.0.1
SERVICEREGISTRY_PORT=8443
SERVICEREGISTRY_DB_USERNAME=myUser
SERVICEREGISTRY_DB_PASSWORD=xxx
SERVICEREGISTRY_LOG_REQUESTS=false
SERVICEREGISTRY_PING_ENABLE=false
SERVICEREGISTRY_PING_TIMEOUT=5000
SERVICEREGISTRY_PING_INTERVAL=60
SERVICEREGISTRY_TTL_ENABLE=false
SERVICEREGISTRY_TTL_INTERVAL=10
SERVICEREGISTRY_STRICT_INTERFACE_NAMES=false
SERVICEREGISTRY_DISABLE_HOSTNAME_VERIFIER=false
SERVICEREGISTRY_SSL_KEYSTORE_TYPE=PKCS12
SERVICEREGISTRY_SSL_KEYSTORE=classpath:certificates/service_registry.p12
SERVICEREGISTRY_SSL_KEYSTORE_PASSWORD=123456
SERVICEREGISTRY_SSL_KEY_ALIAS=service_registry
SERVICEREGISTRY_SSL_KEY_PASSWORD=123456
SERVICEREGISTRY_SSL_CLIENT_AUTH=need
SERVICEREGISTRY_SSL_TRUSTSTORE_TYPE=PKCS12
SERVICEREGISTRY_SSL_TRUSTSTORE_PATH=classpath:certificates/truststore.p12
SERVICEREGISTRY_SSL_TRUSTSTORE_PASSWORD=123456
While searching for a solution to my problem, I came across the Spring Cloud Config Server (also just a Spring application that is self-hostable). This provides an interface between the configuration file storage location and the Spring application. The application is set up so that instead of a static application.(properties|yml) file, a bootstrap.yml is stored with the URL to the config server. When the application starts up, it then connects to the Config Server and receives it via a REST interface. The configuration files can be stored in Git/a DB or as a file.
Spring Docs - Cloud Config Server
Spring - Instruction for Implementation
Baeldung - Tutorial
Baeldung - Tutorial Bootstrapping

Can not connect from spring boot to postgresql schema - 'org.postgresql.util.PLSQLException: ERROR: schema "test" does not exist'

I have postgresql database, version 11. There I created database schema 'test'.
Sql of that schema:
CREATE SCHEMA TEST
AUTHORIZATION "user-xxx";
ALTER DEFAULT PRIVILEGES IN SCHEMA test
GRANT ALL ON TABLES TO postgres;
ALTER DEFAULT PRIVILEGES IN SCHEMA test
GRANT ALL ON TABLES TO PUBLIC;
My config in spring boot:
datasource:
platform: postgres
jdbc-url: jdbc:postgresql://localhost:5432/BDA
username: user-xxx
password: user-xxx
jpa:
generate-ddl: true
properties:
hibernate:
default_schema: TEST
When launching the application I always get following exception:
Can not connect from spring boot to postgresql schema - 'org.postgresql.util.PLSQLException: ERROR: schema "test" does not exist'
If I don't specify the schema then it works with default database schema, and everything is ok.
I fond the reason. When jpa driver connects to PostgreSQL schema 'TEST' it lowercase the letters, and searches for 'test'. So, I renamed the schema to 'test', and the configuration setting to 'test', and was able to connect then.

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"

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.

Cant connect to database

I'm trying to connect to my database when I start my server in drop wizard. But I get the following error when I try to start the server
org.hibernate.engine.jdbc.internal.JdbcServicesImpl: HHH000342:
Could not obtain connection to query metadata :
Driver:org.h2.Driver#7ed6a46e returned null for
URL:jdbc:mysql://localhost:3306/testDatabase
Here is the code for my .yml (yaml) file
# Database settings.
database:
# the name of your JDBC driver
driverClass: org.h2.Driver
# the username
user: root
# the password
password: superSecretPassword
# the JDBC URL
url: jdbc:mysql://localhost:3306/testDatabase
server:
type: simple
connector:
type: http
port: 8080
What could be the problem here?
You use a wrong JDBC- Driver class: org.h2.Driver You have to use a mysql driver like com.mysql.jdbc.Driver

Categories