Spring Boot testing using in memory db - spring

I have created a Spring web project using Spring Boot.
Would like to understand the practice around testing. I require an in memory embedded database say hsql or h2 for my junits with initial schema.sql.
And on the main application the database could be say mysql or oracle
In a non Spring Boot project, we would normally have a separate applicationcontext.xml one which is referred by the web app and for testing we would use applicationContext-text.xml
Now, in Spring boot as everything is created automatically and Spring Boot is opiniated too. Would like to know how do I setup having an embedded inmemory db for Junits and an external db like MySQL for the application.
One solution I can think of is using Profiles. with 2 properties file application.properties and application-test.properties. and use test profile for my junits.
Any recommendation on the approach I should take.

A profile is, indeed, the recommended approach. What I would do is probably make the in-memory implementation the "default" profile (it's harmless, in the sense that you never change any real data, so it's better to make that the default in case someone accidentally runs it against a real database). Personally, I prefer to put all the external configuration in a single application.yml file, but that's really up to you. In the external configuration you need to supply a valid driver class and URL, e.g.
spring:
datasource:
driverClassName: org.h2.Driver
url: jdbc:h2:mem:test;MODE=PostgreSQL
schema: classpath:/schema.sql
---
spring:
profiles: local
datasource:
url: jdbc:postgresql://localhost/test
username: root
password: changeme
driverClassName: org.postgresql.Driver
schema:
(Note that H2 has a postgres compatibility mode, so it is really nice as a complement to postgres in production.)

Related

How to configure Spring Boot with Liquibase and H2 to use a non-admin account by default

I'm using a JHipster-generated application that uses liquibase to populate a persisted H2 database. As a security requirement, we need to set up and use a non-admin user on the database so that in normal operation, the Spring application uses a limited database account which, for example, would not be able to alter the schema.
Currently there seems to be a default H2 user that is automatically created via SPRING_DATASOURCE_USERNAME and SPRING_DATASOURCE_PASSWORD properties. Presumably this auto-generated user has all the admin power that lets the application create and populate tables via liquibase. Ideally this would continue to work as-is, but all other Spring db operations would work over a different user with more limited permissions.
Playing around with the H2 database, I can see H2 does include commands that make it possible to create new users with very granular levels of access, but it's not clear how to set up Spring to make use of this alternate user.
EDIT: I looked at the solution posted here: (Liquibase & Spring how to use separate user for schema changes), but I'm running into a few issues. The solution proposes setting up an application yaml like the following:
application.yml:
spring:
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://...
username: <app_user>
password: ${DB_PASSWORD}
liquibase:
default-schema: my_schema
user: <admin_user>
password: ${DB_ADMIN_PASSWORD}
I find I also need to add an an 'ADD USER' sql statement to my liquibase changelog, which means I would also need to find a way to propagate a secondary password into the liquibase xml so that it would update on future deployments. But besides that I'm finding if I do not create this alternate login with admin privileges, I get surprisingly odd errors, such as
'org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [call next value for sequence_generator]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement'
I also see an issue during startup, even when I do create this user as an admin:
2020-10-15 18:12:17.953 WARN 86226 --- [ test-task-1] i.g.j.c.liquibase.AsyncSpringLiquibase : Starting Liquibase asynchronously, your database might not be ready at startup!
2020-10-15 18:12:19.530 ERROR 86226 --- [ restartedMain] com.zaxxer.hikari.pool.HikariPool : Hikari - Exception during pool initialization.
org.h2.jdbc.JdbcSQLInvalidAuthorizationSpecException: Wrong user name
or password [28000-200]
It seems like this would be a common use case, so perhaps I'm missing a simpler solution?

(Spring Boot and H2) Can't use h2 database

I'm learning Spring boot and I'm trying to create a very simple RESTful API that access an in-memory database and perform CRUD actions.
However, everytime I try to Connect or Test Connection on http://localhost:8080/h2-console, I get this error:
"Database "C:/Users/XXX/test" not found, and IFEXISTS=true, so we cant auto-create it [90146-199] 90146/90146"
https://imgur.com/a/oYgkK1C
I followed EXACTLY the instructions from http://www.springboottutorial.com/spring-boot-crud-rest-service-with-jpa-hibernate. I have tried everything I could find online: using jdbc:h2:mem:test as JDBC URL etc, but none of them worked for me and I'm not sure what am I doing wrong.
I didn't install h2 database from the official website as I read it is not necessary to use the in-memory module (and I still don't know if I should've installed it or not, as there is not a single mention of it online, as far as I checked).
Any thoughts? I'm a beginner when it comes to Spring Boot and I'm really lost. I just want to test CRUD actions and I don't care about the persistence of the DB.
I have provided my application.properties below.
Thank you! :)
# H2
spring.h2.console.enabled=true
spring.h2.console.path=/h2
# Datasource
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.username=user
spring.datasource.password=user
spring.datasource.driver-class-name=org.h2.Driver
Make sure your url in h2-console(refer screenshot below) is same as your 'spring.datasource.url=jdbc:h2:mem:test'.
It worked for me.
UPDATE: Other alternative solution is,
you can avoid setting spring.datasource.url property. Spring will automatically set this default JDBC url for you.
happy learning.. Upvote, if it is sovled your issue.
In your spring application.properties file, set the property
spring.datasource.url=jdbc:h2:~/test
Then restart the application and open http://localhost:8080/h2-console/
Click on Test Connection button, you should see "Test successful".

spring-boot actuator refresh and in memory db

Is there a way to somehow configure spring-boot (2.1.1) actuator refresh or hikari/datasource so it reexecutes logic responsible for inmemory database (h2 for instance) creation?
At the moment after the /actuator/refresh I do not have previously created tables (hbm2ddl: create-drop or hbm2ddl: create) anymore.
There is no sample code of your implementation.
But Your problem seems to be not a problem as this is how the In-Memory Dbs are supposed to work.
These Dbs(H2,Hsql) are used for testing and not prefered for production but if you need for some small data than these are absolutely fine.
Also,
(hbm2ddl: create-drop or hbm2ddl: create)
Here, with this it will always recreate the db after the service is restarted.
change it to
(hbm2ddl: update) The syntax might not be correct.
Also taking into consideration you are using hibernate
I think actuator is meant for different things, to get an understanding of what happens in a microservice instance in a runtime mainly.
/actuator/refresh
indeed manages beans with Refresh Scope, it just recreates them without recreating the whole application context (which can be an expensive operation) if the configurations have changed (like in spring boot cloud config service).
So it has nothing to do with the lifecycle of H2 DataSource which is indeed used mainly for tests as our colleague Shubham has kindly stated, and and this makes the question even more confusing :)

Configuring Wildfly datasource for a JHipster application

I am to deploy a JHipster application to Wildfly (v. 9.0.2) servers and need to use JNDI data sources.
The basic connection setup is pretty straightforward: I set up new data source in Wildfly's standalone.xml to mimic the out-of-the-box ExampleDS, then included a reference to it into application-dev.yml and slightly modified DatabaseConfiguration.java. Now, that works well.
The problem is that application-xxx.yml files also contain JPA configuration, and I don't know where to stick it into Wildfly (I guess it must be in Wildfly).
To be more precise, I have no idea where to move the following JPA parameters:
jpa:
database-platform
database
openInView
show_sql
generate_ddl
hibernate:
ddl-auto
naming-strategy
properties:
hibernate.cache.use_second_level_cache
hibernate.cache.use_query_cache
hibernate.generate_statistics
hibernate.cache.region.factory_class
I know that Wildfly advises this to be defined in persistence.xml, in which case, can I just drop it into the project?
Thank you in advance.

Is it possible to configure pool size for batch job workflows database in spring-xd

I have configured Sql Server to be used as batch job workflows database. I followed the suggestion in documentation and it works well.
I wanted to know if the datasource connection is pooled so I can connect to XD in debug mode and catch one of the JdbcTemplate.update(..) calls. I can see that the DataSource implementation is org.apache.tomcat.jdbc.pool.DataSource and that there is a pool size already configured. Is it possible to have some control over this configuration?
answer to question:
On page 20 of the spring-xd-reference there a note that says:
"Until full schema support is added for Oracle, Sybase and other database, you will need to put
a .jar file in the xd/lib directory that contains the equivalent functionality as these DDL scripts"
Basically you create 2 files with the name pattern of the other examples and place then in the same classpath. The pattern you use in your configuration is used to fetch the file.
spring:
datasource:
url: jdbc:sqlserver://192.168.3.23:1433;databaseName=jobdb
username: asdf
password: asdf
driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
So just copy both files from mysql and change the mysql part to sqlserver

Resources