After using gradle-flyway plugin to create test database, how to reference db created in c3p0 config? - gradle

I was trying to accomplish the following
1) Create h2 database using gradle-flyway plugin before tests run. I was able to create it and place it under ${buildDir}
flyway {
url = "jdbc:h2:file:${buildDir}/db/test/xxxdb"
user = 'root'
locations = [
'classpath:sql'
]
}
2) My goal was to write integration tests against this db created in step 1. I am using c3p0 for pooling and here is my configuration.
<?xml version="1.0"?>
<c3p0-config>
<default-config>
<property name="driverClass">org.h2.Driver</property>
**<property name="jdbcUrl">jdbc:h2:file:#buildDir#/db/test/xxxdb</property>**
<property name="user">xxx</property>
<property name="password">xxx</property>
<property name="minPoolSize">1</property>
<property name="maxPoolSize">50</property>
<property name="acquireIncrement">1</property>
</default-config>
</c3p0-config>
Questions:
a) How do I configure c3p0 to reference the h2 database present in the build directory created in step 1. c3p0 wants absolute path in jdbcUrl property.
b) I configured gradle to replace #buildDir# with appropriate value using this below gradle task. So the database jdbcUrl is configured correctly for c3p0 when I do "gradle build". But when I run the tests though intelliJ, it still reads the jdbcUrl with value containing "#buildDir#" as intellij does not run processTestResources task before running the test.
processTestResources {
filter(ReplaceTokens, tokens: [buildDir: buildDir.getAbsolutePath()])
}
Any ideas on how to solve this issue?

Thanks Mark for your comments. For relative paths, this is the syntax I had used and now it works with both gradle and intellij.
jdbc:h2:file:./db/test/xxxdb

Related

Spring: exclude some properties files from context

suppose we have some jars with properties files with the same key/values.
configA.jar:
log4j.A.properties
configB.jar:
log4j.B.properties
The problem: Spring mixes values from the both properties files. So, how to exclude log4j.A.properties from the context and process only log4j.B.properties?
UPDATE (added some stuff): there is a maven build which produces two jars mentioned above. Here in webapp (applicationContext.xml) following setup:
<util:properties id="propertyConfigurer" location="classpath:common.properties,classpath*:edrive.properties,classpath*:job.properties,classpath*:log4j.B.properties"/>
After the startup Spring mixes both jars and takes random (or the last one) jar and it's log4j.properties. But we need only the log4j.B.properties. How to do that?
try adding the config file to be used in your properties file
logging.config=log4j.B.properties
I resolved the issue by myself. I've upgraded logging facility to Log4j2 with following configuration:
log4j2.component.properties in classpath:
log4j.configurationFile=classpath:log4j2.web.xml
That's it.

How to load a secret.properties file in apacheignite/docker stock image

I used gridgain’s webconsole to create a configuration file for my ignite node (ignite-config.xml). I’d like to see if I can get this running in apache’s docker ignite image (apacheignite/ignite). I’ve created a volume in my compose file that maps to a config folder that houses my ignite-config.xml.
I need to include the secret.properties (that has my jdbc url/username/password) file as well so I put it in the config folder too.
When I do a docker-compose up I get a java.io.FileNotFoundException: class path resource [config/secret.properties] cannot be opened because it does not exist]
This is the part of the xml config that deals with the secret.properties location:
<!-- Load external properties file. -->
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:secret.properties"/>
</bean>
What do I need to change so that the secret.properties file in the config folder is loaded? Is there a better way to do this?
I do not know how to easily deploy the secret.properties file without going through a full build and deploy, but in order to get past that for testing purposes, you could get rid of the secret.properties and use environment variables instead.
Which might look something like this for a JDBC connection to Postgres:
<!-- Data source beans will be initialized from external properties file. -->
<bean id="dsPostgreSQL_Daifcqkp30zkdj" class="org.postgresql.ds.PGPoolingDataSource">
<property name="url" value="#{systemEnvironment['dsPostgreSQL_Daifcqkp30zkdj_jdbc_url']}"/>
<property name="user" value="#{systemEnvironment['dsPostgreSQL_Daifcqkp30zkdj_jdbc_username']}"/>
<property name="password" value="#{systemEnvironment['dsPostgreSQL_Daifcqkp30zkdj_jdbc_password']}"/>
</bean>
Then, just set your environment variables:
IGNITE_VERSION=2.7.5
CONFIG_URI=https://raw.github.com/some/path/to/your/config.xml
OPTION_LIBS=ignite-zookeeper,ignite-rest-http
EXTERNAL_LIBS=https://github.com/some/path/to/your/jdbc-drivers/postgresql-42.2.6.jar?raw=true
dsPostgreSQL_Daifcqkp30zkdj_jdbc_username=0a9suf09asdfkjwel
dsPostgreSQL_Daifcqkp30zkdj_jdbc_password=8faskdfn94noiasnf09_s09fklajfealk
dsPostgreSQL_Daifcqkp30zkdj_jdbc_url=jdbc:postgresql://<host>:<port>/Daifcqkp30zkdj?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory
Had the same issue, probably didn't resolve it the "correct" way (whatever that is), but resolved it this way for a POC nonetheless:
Create a standalone jar file with only the secrets file
Give it the name dsPostgreSQL_Daifcqkp30zkdj_jdbc.jar or similar
Place the jar file in the libs directory
It seems the classpath is just the contents of all JAR files in the \libs subdir, so oblige it... This would have the advantage of allowing for a signed JAR - I believe - which would (in addition to file system permissions, visibility, etc.) at least ensure it isn't tampered with.

where spring defines variable value, which is referred by some xml file

I am trying to understand from where does the value of a variable comes from, when it is referred in Spring xml file.
For example:
<context:property-placeholder location="classpath:/${com.example.deploy.environment}/com.example.config/mysql.properties" ignore-resource-not-found="false" />
Where is the value of com.example.deploy.environment defined? In my project I searched all over, however i couldn't find anywhere where this values is defined.
Any information in understanding this would be of great help.
This value can come from a variety of source:
application.properties file which you can define in PropertyPlaceholderConfigurer bean.
<bean id="mailProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:application.properties" />
</bean>
...
//Inside application.properties
com.example.deploy.environment=prod
You can provide via command-line:
With Maven vm arguments for JVM System property:
mvn package -Dcom.example.deploy.environment=prod
Running Spring Boot Application:
java -jar app.jar --com.example.deploy.environment="prod"
From System Environment variable of the Operating System. You might have to restart after setting environment variable. See below for windows:
Refer this doc and this article for more info.

How to handle multiple build targets, e.g. dev, test, main?

I'm currently migrating from Maven to SBT, and I'm struggling to understand how I can handle multiple build targets (dev, test, train, prod etc).
For example, I have a persistence.xml that looks like this:
<properties>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="javax.persistence.jdbc.url" value="${db.connectionURL}"/>
<property name="javax.persistence.jdbc.user" value="${db.username}"/>
<property name="javax.persistence.jdbc.password" value="${db.password}"/>
<property name="eclipselink.target-database" value="Oracle10"/>
</properties>
With Maven, it was really easy to handle this using profiles.
I've already tried what was suggested here for SBT, but I'm not having any success with that approach.
How to Add Environment Profile Config to SBT.
Also, using that approach I would need a new directory for each new environment. I just think that there has to be a better way to handle this kind of setup using SBT?
tl;dr Use ivyConfigurations to add custom configs and resourceGenerators to process files per environment.
All credits goes to Eugene Yokota for the answer to How to Add Environment Profile Config to SBT. There are some modification that make the solution of mine...cough...cough...slightly better.
The following build.sbt defines two new configurations - dev and qa. It also defines resourceGenerators per configuration that effectively gives a way to access what configuration the new resourceGenerator executes in:
val Dev = config("dev") extend Runtime
val Qa = config("qa") extend Runtime
ivyConfigurations ++= Seq(Dev, Qa)
// http://www.scala-sbt.org/0.13.5/docs/Howto/generatefiles.html#resources
lazy val bareResourceGenerators: Seq[Setting[_]] = Seq(
resourceGenerators += Def.task {
val file = resourceManaged.value / "demo" / "myapp.properties"
println(s"Inside ${configuration.value}")
val contents = s"config=${configuration.value}"
IO.write(file, contents)
Seq(file)
}.taskValue
)
inConfig(Dev)(Defaults.configSettings ++ bareResourceGenerators)
inConfig(Qa)(Defaults.configSettings ++ bareResourceGenerators)
Inside the new resourceGenerator you can do whatever you want and the per-configuration processing is possible with the configuration setting that gives you the name of the configuration:
> show dev:configuration
[info] dev
> show qa:configuration
[info] qa
Now when you execute show qa:resources you'll see that there are two files generated with target/scala-2.10/resource_managed/qa/demo/myapp.properties with the content that's specific to a configuration:
> show qa:resources
Inside qa
[info] List(/Users/jacek/sandbox/envs/target/scala-2.10/resource_managed/qa/demo/myapp.properties, /Users/jacek/sandbox/envs/src/qa/resources)
The trick now is to use the resourceGenerator to meet your needs and since you're in Scala code you can do whatever you want - just use configuration.value as the qualifier for a configuration-specific code.
Say, you want to use a qa-specific properties file in the standard src/main/resources directory. Just know where the value is bound to (what configuration and setting the value comes from). It's just compile:resourceDirectory.
> show compile:resourceDirectory
[info] /Users/jacek/sandbox/envs/src/main/resources
Just use resourceDirectory in Compile whenever you need a "stable" (aka configuration-fixed) value like src/main/resources.
val props = (resourceDirectory in Compile).value / s"${configuration.value.name}.properties"
println(s"Read files from $props")
With the above lines you'd get:
> show qa:resources
Inside qa
Read files from /Users/jacek/sandbox/envs/src/main/resources/qa.properties
[info] List(/Users/jacek/sandbox/envs/target/scala-2.10/resource_managed/qa/demo/myapp.properties, /Users/jacek/sandbox/envs/src/qa/resources)
> show dev:resources
Inside dev
Read files from /Users/jacek/sandbox/envs/src/main/resources/dev.properties
[info] List(/Users/jacek/sandbox/envs/target/scala-2.10/resource_managed/dev/demo/myapp.properties, /Users/jacek/sandbox/envs/src/dev/resources)

Can I default a system property for a constructor-arg in a spring config file?

I have a spring config file which includes the following elements:
<context:property-placeholder location="classpath:default.properties"/>
<bean id="theVar" class="java.lang.String">
<constructor-arg value="${varName}"/>
</bean>
"varName" is now moved from the properties file to a system property. It is being added when I start a Maven build:
mvn clean install -DvarName=data
I want to also run my build without specifying varName:
mvn clean install
Is there some way to default varName in my spring config? Though this does not work, a conceptual example of what I am looking for is:
<bean id="theVar" class="java.lang.String">
<constructor-arg value="${varName}" default="theDefaultValue"/>
</bean>
Spring 3.0.x supports a syntax like this:
value="${varName:defaultValue}"
References:
SPR-4785
Changes in version 3.0.0.RC1 (2009-09-25) (PropertyPlaceholderConfigurer supports "${myKey:myDefaultValue}" defaulting syntax)
It turns out that in spring v2.5+, if there is a system property defined, it can be used instead of a property defined in the properties file. You just need to ensure the same name is used and that the 'override' option is enabled.
For example, given:
<!-- my spring config file -->
<context:property-placeholder location="classpath:default.properties" system-properties-mode="OVERRIDE"/>
And:
# default.properties file
theVariable=One
When I execute:
mvn clean install
"One" is picked-up for theVariable. If I execute:
mvn clean install -DtheVariable=Two
"Two" is picked-up instead.
I'm not sure If this will help but if you are annotating classes and want a default value when a system property is not present this is what I currently do:
#Value("#{systemProperties['fee.cc']?:'0.0225'}")
public void setCcFeePercentage(BigDecimal ccFeePercentage) {
this.setCcFeePercentage(ccFeePercentage);
}
It can be done as #sebastien has described but in the configuration file as you want:
<bean id="theVar" class="java.lang.String">
<constructor-arg value="#{systemProperties['varName'] == null ? 'default_value' : systemProperties['varName']}"/>
</bean>
If your varName variable is not present, default value will be set.

Resources