How to pass spring.config.location="somepath" while building SpringBoot application with command-line Gradle (6.4) build - spring-boot

I have a SpringBoot application where I have application.properties file outside of project (it's not in usual place src/main/resources).
While building application with gradle clean build, it fails as code is not able to find properties files.
I have tried many command to pass vm args, gradle opts but its not working.
gradle clean build -Djvmargs="-Dspring.config.location=/users/home/dev/application.properties" //not working
It fails on test phase when it creates Spring application context and not able to substitute property placeholders. If I skip test as gradle clean build -x test it works.
Though I can run the app with java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties
Please help how I can pass spring.config.location=/users/home/dev/application.properties in gradle build using command line so that build runs with all Junit tests

If I were you, I would not get involved the actual properties to junit test. So I would create a test properties for the project under src/test/resources/application-test.properties and in junit test I would load the test properties.
Example:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MyProperties.class)
#TestPropertySource("classpath:application-test.properties")
public class MyTestExample{
#Test
public void myTest() throws Exception {
...
}
}

System properties for running Gradle are not automatically passed on to the testing framework. I presume this is to isolate the tests as much as possible so differences in the environment will not lead to differences in the outcome, unless explicitly configured that way.
If you look at the Gradle API for the Test task, you can see that you can configure system properties through through the systemProperty method on the task (Groovy DSL):
test {
systemProperty "spring.config.location", "/path/to/my/configuration/repository/application.properties"
}
If you also want to read a system property from the Gradle command line and then pass that the test, you have to read it from Gradle first, e.g. as a project property, and then pass that value to the test:
test {
if (project.hasProperty('testconfig')) {
systemProperty 'spring.config.location', project.getProperty('testconfig')
}
}
Run it with gradle -Ptestconfig="/path/to/my/configuration/repository/application.properties" build
However, I would discourage using system properties on the build command line if you can avoid it. At the very least, it will annoy you greatly in the long run. If the configuration file can be in different locations on different machines (depending on where you have checkout out the repository and if it is not in the same relative path to your Spring Boot repository), you may want to specify it in a personal gradle.properties file instead.

I think there is a misunderstanding.
spring.config.location is used at runtime
As you validated:
java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties
spring.config.location is used or required at runtime, not at build time.
When your spring boot app is building, an application.properties is required. An approach could be use an src/main/resources/application.properties with template values, but at runtime you will ignore it spring.config.location=file...
For unit tests
In this case as #nikos-bob said, you must use another properties, commonly inside of your src/test/resources
Environment variables instead external properties
We don't want to have hardcoded values in our main git repository src/main/resources/application.properties so the first idea is use an external properties. But this file must be stored in another git repository (equal to main repository ) or manually created.
Spring and other frameworks give us an alternative: Use environment variables.
So instead of manually external creation of application.properties or store it in our git repository, your spring boot app always must have an application.properties but with environment variables:
spring.datasource.url=jdbc:oracle:thin:#${DATABASE_HOST}:${DATABASE_PORT}:${DATABASE_SID}
spring.datasource.username=${DATABASE_USER}
spring.datasource.password=${DATABASE_PASSWORD}
spring.mail.host = ${MAIL_HOST}
spring.mail.username =${MAIL_USERNAME}
spring.mail.password =${MAIL_PASSWORD}
Advantages:
No manually creation of application.properties allowing us a more easy devops automations
No spring.config.location=file.. is required

Related

How to get the Gradle build directory in a Java annotation processor

I am writing a custom annotation processor in Java which needs to create a file.
It seems to me the best location for that file would be in a new folder inside the Gradle's $buildDir.
For a project without modules, the environment property "user.dir" seems to hold a value I could use.
However, that environment property changes if the project has modules and the gradlew build command is executed either from inside or outside a module.
What is the best approach to actually get in Java the Gradle build directory of the module in which the annotation processor is declared ?
P.S.
I do not want to create that file in the "build/generated" folder (this is what processingEnv.getFiler().createSourceFile(..) does).
You should do it the other way around : choose a location and set it up in your build.gradle
tasks.withType(JavaCompile) {
options.annotationProcessorGeneratedSourcesDirectory = file("your/custom/path")
}

How do you run micronaut from gradle with local properties

I want to run Micronaut server from Gradle command line with "local" environment variables.
The regular command
.\gradlew.bat run
will use default variables defined in application.yml file.
I want to override some of them with values for my local environment and therefore need to specify system property micronaut.environments=local to use overriding values from application-local.yml file.
.\gradlew.bat run -Dmicronaut.environments=local
The command above won't work as Gradle will take only -Dmicronaut for the system property and the rest ".environments=local" will be considered as another task name:
Task '.environments=local' not found in root project 'abc'
What would be the correct way to pass such system property to the java process?
Command below works for unix, probably it should work also for windows:
MICRONAUT_ENVIRONMENTS=local gradle run
or use gradle wrapper
MICRONAUT_ENVIRONMENTS=local .\gradlew.bat run
P.S. also, you can find the same approach for Spring Boot
My approach is to add a gradle task.
task runLocal(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = "dontdrive.Application"
jvmArgs '-Dmicronaut.environments=local'
}
then start with:
./gradlew runLocal

How to pass system properties to the tests in gradle in the smart way?

build.gradle
tasks.withType(Test){
systemProperties=System.properties
println systemProperties['param']
}
Now I can either pass parameters in the command line:
gradle test -Dparam=10
or put them in gradle.properties:
systemProp.param=15
Ideally I would like to put the defaults in the gradle.properties, and be able to overwrite them from the command line. Unfortunately if I do that, the gradle.properties has precedence, and -Dparam=10 is ignored.
Could you offer any solutions on that?
https://issues.gradle.org/browse/GRADLE-2122
It works since 2.12 or 2.13 "the smart way" already!
The example above is working, the command line -D option overdrives the defaults in gradle.properties
I am using gradle 2.12 and sharing how I used it:
test {
// support passing -Dsystem.property=value to bootRun task
systemProperties = System.properties
}
I have JUnit tests that I wanted to skip unless a property was used to include such tests. Using JUnit Assume for including the tests conditionally:
//first line of test
assumeThat(Boolean.parseBoolean(System.getProperty("deep.test.run","false"),true)
Doing this with gradle required that the system property provided at the time of running gradle build, shown here,
gradle build -Ddeep.test.run=true
was indeed passed through to the tests.
Hope this helps others trying out this approach for running tests conditionally.

How to work with JMeter and Junit

I am very new to JMeter
I am trying to use Junit Request sampler in JMeter.In my project we have a class called PayloadProcessorTest.java. from these class methods i am calling some other class methods.It has lot of dependencies
How can i create jar file for PayloadProcessorTest.java with dependencies
I saw many examples for JMeter with Junit Request sampler. But, those all examples are independent classes
Can any one please help me
There are several ways of creating a .jar file:
Using Maven
Using Ant
Using Eclipse
.jar files are basically ZIP archives so you can just compile your PayloadProcessorTest.java and put resulting PayloadProcessorTest.class into /lib/junit/test.jar file keeping package structure. After restart JMeter will pick up the class. Don't forget to add any 3rd-party jars used in PayloadProcessorTest (if any) to JMeter classpath. For more information check out How to Use JUnit With JMeter guide.
If you want to get the dependencies with Maven you can run
mvn install dependency:copy-dependencies, which will create a folder inside your target folder called 'dependency' filled with the dependencies. To speed this up you can add the command as External Tool in Eclipse using Run > External Tools > External Tools Configurations.
Or if you want to use Eclipse you can choose File > Export > Java > Runnable JAR file and select the option 'Copy required libraries into a sub folder next to the generated JAR'. However to do this you will need to add a main class, and run it once as a Java Application before trying to export. The Main class can be empty or not.
package test;
public class Main {
public static void main(String[] args) {
}
}
Really, it depends what packaging capabilities you have.
You need to compile your classes in one or more jars, and then put them in the %JMETER_HOME%/lib/ext folder.
Or use maven to do it all for you.

maven spring test application contexts

I want to use the applicationContext.xml in my src/main/resources directory from within my test harness in src/test/java. How do I load it? I have tried:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations="classpath:applicationContext.xml")
public class TestService {
...
}
but get a file not found error. I'm using Maven and Spring. Thanks.
Try this (note the asterisk):
#ContextConfiguration("classpath*:applicationContext.xml")
The Maven test classpath uses the files in target/test-classes. That folder contains Java classes from src/test/java and resources from src/test/resources.
The way to go is to create a test specific app context and store it under src/main/resources.
You may try to reference the file directly using file: i.e. something like file:src/main/resources/applicationContext.xml but to me this is an ugly hack.
Also, you can of course use the Maven resources plugin to copy applicationContext.xml prior to test execution.
Here's how I do it, it may or may not be the best way for you. The main thing is it works in both Eclipse and Maven:
Keep exactly one copy of each applicationContext-xxx.xml file per project. NEVER copy-and-paste them or their contents, it'll create a maintenance nightmare.
Externalize all environmental settings to properties files (e.g. database-prod.properties and database-test.properties) and place them in src/main/resources and src/test/resources respectively. Add this line to your app contexts:
<context:property-placeholder location="classpath:**/*.properties"/>
Create a superclass for all test classes and annotate it with a context configuration:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:applicationContext.xml"})
#Ignore
public class SpringEnabledTest {
// Inheritable logger
protected Logger logger = LoggerFactory.getLogger(this.getClass());
}
Add <additionalClasspathElements> to your maven-surefire-plugin configuration to make sure surefire picks up appContext and the right properties files. I've created an example here.
Add the location(s) of the app context files and src/test/resources to your Eclipse classpath so you can execute unit tests in Eclipse as well.
NEVER add src/main/resources to your Eclipse classpath, it's only a convenient place for Maven to package additional source files, it should have no bearing on Eclipse. I often leave this directory blank and create additional folders (e.g. env/DEV, env/UAT and env/PROD) outside of the src/ folder and pass a parameter to the build server and let it know from which folder it needs to copy files to src/main/resources.
Add the src folder to the classpath of your testing tool. If it's in Eclipse, I think you can do it from the project properties. You may have to change it to classpath:**/applicationContext.xml as well.

Resources