I want to write unit test in my Spring project.
There is only one application config in the whole project.
The application run well, but I get a "Caused by: java.sql.SQLException: No suitable driver" exception in unit test.
How can I setup a driver into the test?
The only annotation used in unit test:
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
The db connection settings in application.yml:
spring:
main:
allow-bean-definition-overriding: false
application:
name: application
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.sybase.jdbc4.jdbc.SybDriver
password: xxx
url: jdbc:sybase:Tds:localhost:3268/my_db
username: admin
hikari:
connection-test-query: SELECT 1
liquibase:
change-log: liquibase/changelog.sql
user: admin
password: xxx
jpa:
database: SYBASE
database-platform: org.hibernate.dialect.SybaseAnywhereDialect
hibernate:
ddl-auto: none
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
I finally find out the reason.
Since I had added a test configuration class into test folder, the extra configuration is also loaded into the single annotation "#SpringBootTest" test and the db connection setup fail.
When I comment the #TestConfiguration in the extra test configuration class file, the test with single #SpringBootTest can work normally.
Related
Not sure what I'm doing wrong here, but I have the following value that points to the URL of a micro service.
#Value("${url.dispenseRoot}")
private String dispenseRoot;
And I am setting up my dev profile in my application.yml file such:
---
spring:
datasource:
url: jdbc:h2:mem:test
username: sa
password: sa
driverClassName: org.h2.Driver
config:
activate:
on-profile: dev
mpesa:
host: sandbox.safaricom.co.ke
port: 443
url:
dispenseRoot: https://localhost:8844/dispense
---
Then, in accordance with my answer here: How do I activate a Spring Boot profile when running from IntelliJ?, I set up the spring boot profile on the run configuration as such:
And then run the following test to test my configuration:
#SpringBootTest
public class PaymentApplicationTests {
#Test
public void contextLoads() {
}
}
And I get:
... 111 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'url.dispenseRoot' in value "${url.dispenseRoot}"
Now, if I copy and paste the following lines:
url:
dispenseRoot: https://localhost:8844/dispense
Above my profile where I'm setting up the general settings that are true for everything, it works fine. Therefore, I'm certain it has something to do with profiles, but I can't figure out what it is.
Please advise...
I am trying to get run application.yml instead of application.properties. But it fails. Please help. The same thing works in application.properties.
My application.yml looks like this:
spring:
profiles: container
jpa:
show-sql: true
database: MYSQL
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: update
datasource:
url: jdbc:mysql://mysql57:3308/hello_java
username: demo_java
password: 1234
driver-class-name: com.mysql.jdbc.Driver
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-04-03 10:40:26.671 ERROR 12600 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
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 (no profiles are currently active).
Process finished with exit code 1
This is my config file quartz.properties
org.quartz.scheduler.instanceName= LivingOrdering
org.quartz.scheduler.instanceId=99199
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=3
org.quartz.context.key.QuartzTopic=QuartzPorperties
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix=qrtz_
org.quartz.jobStore.dataSource=quartzDataSource
org.quartz.dataSource.quartzDataSource.driver=org.postgresql.Driver
org.quartz.dataSource.quartzDataSource.URL=jdbc:postgresql://localhost:5432/quartz
org.quartz.dataSource.quartzDataSource.user=admin
org.quartz.dataSource.quartzDataSource.password=admin
org.quartz.dataSource.quartzDataSource.maxConnections=300
I am getting error at the line -:
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
Error: org.quartz.SchedulerException: Could not initialize DataSource: quartzDataSource
SpringBoot has Quartz auto configuration, you don't need to configure Quartz using quartz.properties as it knows nothing about Spring so you cannot just put a datasource name in there. Read the documentation.
All you need to get started with Quartz is to include the starter in you pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
Configure your standard Spring datasource (application.properties):
spring.datasource.url = jdbc:postgresql://localhost:5432/quartz
spring.datasource.username = admin
spring.datasource.password = admin
Then add (in application.properties):
spring.quartz.job-store-type=jdbc
# Add the below line to have Spring Boot auto create the Quartz tables
spring.quartz.jdbc.initialize-schema=always
If you want to pass additional properties to Quartz you can prefix the property name with spring.quartz.properties like so:
spring.quartz.properties.org.quartz.scheduler.instanceName=LivingOrdering
I know the question is old, but since I ended up here looking for a solution, and that it wasn't clear what to do, I will provide my solution for the others still looking for one.
Project config:
JDK: 18.0.1
Maven: 3.6.3
Spring boot: 2.7.4
Quartz: spring-boot-starter-quartz
The below config works if you want to have a single datasource for your app and quartz.
I use it for tests for example.
spring:
datasource:
url: jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
driverClassName: org.h2.Driver
username: sa
password: sa
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: never
properties:
org:
quartz:
jobStore:
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
tablePrefix: TB_PR_QRTZ_
Also don't forget to tag your datasource bean with #QuartzDatasource.
#Primary
#Bean
#QuartzDataSource
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource defaultDatasource (){
return DataSourceBuilder.create().build();
}
But if you need 2 datasources, you have to specify a custom datasource in spring.quartz.properties.org.quartz.dataSource.
Here is my config for the app:
spring:
datasource:
byq:
url: jdbc:oracle:thin:#//app-db/schema-name
driverClassName: oracle.jdbc.OracleDriver
username: ZZZ
password: XXX
quartz:
job-store-type: jdbc
wait-for-jobs-to-complete-on-shutdown: true
jdbc:
initialize-schema: never
properties:
org:
quartz:
dataSource:
quartzDataSource:
URL: jdbc:postgresql://scheduler-db/scheduler
driver: org.postgresql.Driver
user: ZZZ
password: XXX
jobStore:
dataSource: quartzDataSource
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
tablePrefix: TB_QRTZ_
As a note here, in the quartz.properties file, the properties names start with org.quartz... ; with the later versions of quartz (after 2.5.6 if I'm not wrong) they start with spring.quartz.properties.org.quartz... .
Just had this issue when I've updated the SpringBoot version from 2.1.2 to 2.6.3 (including quartz libraries) and the error was the same as in this post question.
get rid of spring.datasource.* from application.properties file and , add spring.datasource.name= quartzDataSource works for me.
you may have to configure your org.quartz.dataSource.quartzDataSource.provider as well (hikaricp or c3po-default)
I have spring boot server with 2 property files: application-local.properties and application-test.properties
In each file I have configs for dev machine and for test. Start it like this:
-Dspring.profiles.active=local
But in new spring boot project I use .yaml config file. And I do not understand how can I use profiles with .yaml. I tried read documentation but understood nothing. Can you explain what to do, step by step?
I need have two files?
application-local.yaml and application-test.yaml
Or I need write all in one application.yaml file? If in one file how can I separate configs? It is my config:
server:
path: ***
port: ***
cxf:
path: ***
spring.datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: oracle.jdbc.OracleDriver
url: ***
username: ***
password: ***
hikari:
minimumIdle: 5
maximumPoolSize: 20
idleTimeout: 30000
poolName: SpringBootJPAHikariCP
maxLifetime: 2000000
connectionTimeout: 30000
connection-test-query: SELECT 1 FROM DUAL
spring.jpa:
show-sql: false
database-platform: org.hibernate.dialect.Oracle10gDialect
properties.hibernate.jdbc.batch_size: 30
properties.hibernate.cache.use_second_level_cache: false
hibernate:
ddl-auto: validate
spring.cache:
ehcache:
config: classpath:ehcache.xml
#app configs
my:
messages-max-count: 5
messages-delay: 100
schedulers-charge-delay: 100
client:
first-server-address: ***
second-server-address: ***
last-server-address: ***
enabled-client: FirstClient
I want create test profile and change database url (or change to postgreSql), change maximumPoolSize property
Create application.yaml and define all default properties there.
Create application-local.yaml and override properties needed for the local profile.
Create application-test.yaml and override properties needed for the test profile.
Set spring.profiles.active by either passing it as a system property (-D for java) or defining it within application.yaml.
When you are running an app with a {PROFILE}, Spring will parse application-{PROFILE}.yaml after application.yaml.
Yes, you can create multiple profiles even with single file
Profile are separated with 3 DASH (---)
logging:
level:
.: error
org.springframework: ERROR
spring:
profiles:
active: "dev"
main:
banner-mode: "off"
server:
port: 8085
---
spring:
profiles: dev
---
spring:
profiles: prod
As I currently see it I have 5 possible database profiles
CI testing -> h2 mem
developer environment (could be test or app run) -> h2 mem, or h2 file, or postgres
production -> postgres (ideally credentials not stored in the git/war)
currently I have postgres configured for running the application, and h2 configured for testing via having a different application.properties in java/resources vs test/resources
what's the simplest way to have the database connection information change for these scenarios?
As M. Deinum mentions in his comment, the simplest way to do this is to use profile specific configuration.
Spring Boot allows you to have one common configuration file (application.properties) and then multiple other files, each specific to a profile (application-${profile}.properties).
For instance:
application.properties - Common configuration
application-dev.properties - Configuration for dev profile
application-ci.properties - Configuration for ci profiles
If your application runs with "ci" profile for instance, the default configuration file as well as the ci configuration file (which would contain the datasource configuration properties for ci profile) will be loaded.
To switch profiles you can use one of the following options:
JVM property: -Dspring.profiles.active=ci
Command line switch: --spring.profiles.active=dev
For unit tests you can use #ActiveProfiles("test") annotation on your test classes to tell Spring that unit tests should be run with test profile.
Also if you don't want to store production database credentials along with your source code, you can specify external configuration file when you deploy your app in production:
Using command line switch: --spring.config.location=/srv/myapp/config.properties
Using a JVM property: -Dspring.config.location=/srv/myapp/config.properties
Compact answer for the above scenario would be by creating a single application.yml file and creating different profiles based on the requirement, in your case -dev, -ci and -prod and providing the DB information accordingly.
Sample example is:
spring:
profiles.active: development
---
spring:
profiles: development
datasource:
db-person:
url: jdbc:oracle:thin:#db_person_dev
username: username
password: pwd
driver-class-name: oracle.jdbc.OracleDriver
test-on-borrow: true
validation-query: SELECT 1 FROM dual
db-contract:
url: jdbc:oracle:thin:#db_contract_dev
username: username
password: pwd
driver-class-name: oracle.jdbc.OracleDriver
test-on-borrow: true
validation-query: SELECT 1 FROM dual
---
spring:
profiles: test
datasource:
db-person:
url: jdbc:oracle:thin:#db_person_test
username: username
password: pwd
driver-class-name: oracle.jdbc.OracleDriver
test-on-borrow: true
validation-query: SELECT 1 FROM dual
db-contract:
url: jdbc:oracle:thin:#db_contract_test
username: username
password: pwd
driver-class-name: oracle.jdbc.OracleDriver
test-on-borrow: true
validation-query: SELECT 1 FROM dual
---
spring:
profiles: production
datasource:
db-person:
url: jdbc:oracle:thin:#db_person_prod
username: username
password: pwd
driver-class-name: oracle.jdbc.OracleDriver
test-on-borrow: true
validation-query: SELECT 1 FROM dual
db-contract:
url: jdbc:oracle:thin:#db_contract_prod
username: username
password: pwd
driver-class-name: oracle.jdbc.OracleDriver
test-on-borrow: true
validation-query: SELECT 1 FROM dual
---
For further understanding and simple example you can refer this link.