How to edit app.properties file with build parameter in Jenkins - java

I have a selenium script which I want to run from Jenkins. I have a properties file called app.properties. This file consists properties such as:
browser=chrome
I configured my project as parameterized so when I run my build, it asks for browser parameter. I want to select this parameter(for example firefox), so that it will change browser property in app.properties and will run the automation in Firefox.
Normally, when I change the browser property in app.properties in Intellij, my program runs with that browser. So there is nothing wrong with my program in that sense.
Is there a way to change app.properties with respect to my Jenkins build parameter and run the program with that configuration?
EDIT: I found the following solution:
Install surefire plugin.
Add a browser parameter.
In your property managing class, take browser parameter as
System.getProperty("browser");
From jenkins, configure a browser parameter
Invoke maven command: mvn test "-Dbrowser=${BROWSER}"

You can pass system properties to change configuration.
First you should configure your project to read both system properties and configuration file, where system properties will have higher priority. I'd recommend Apache Commons Composite Configuration. It can look like this:
CompositeConfiguration configuration = new CompositeConfiguration();
try {
configuration.addConfiguration(new SystemConfiguration());
configuration.addConfiguration(new PropertiesConfiguration("app.properties"));
} catch (ConfigurationException e) {
e.printStackTrace();
}
//Read your configuration values here
This way when you provide system property -Dbrowser=chrome it will override value from configuration file.
Secondly, you'll need to configure Jenkins job. Since you're passing a parameter you can use it in your build step definition:
mvn clean test -Dbroswer=${browser-param}

“The way parameters take effect is also different depending on the parameter type you choose ... String parameters are exposed as environment variables of the same name.”
https://wiki.jenkins.io/plugins/servlet/mobile?contentId=34930782#content/view/34930782

Related

Externalizing Run configurations for Grails app

Is there a way to externalize the run config for per environment configurations with Grails 3 applications?
I am aware that there are run config arguments that allow one to run their application under a dev, prod, test, etc environment, but I was wondering if there is a variable, for example "grails.env" that I can change in a properties, YAML, config, or other file that can be read at run time that will do this for me.
This is just to avoid confusion between the application being tested and run in one setting/environment(physical environment like my local machine), then being given to another individual or team to run elsewhere.
The goal is to configure or set this variable so the run team/individual wont need to know or change the run commands.
Im aware of how to configure the environment with the command line, and within intelliJ and Eclipse. I'm wondering if there is a way to default this in perhaps a file that is read instead.
Thanks
I'm not to sure what is confusing you here but let me try and see if I can point you in the right direction
From the documentation here: http://docs.grails.org/latest/guide/conf.html#environments your application can be delivered as a package war file to the target user to have tested, and the war file can be created with any of of the environment configurations
grails test war
Since the command is can be run in the console, you could run with system properties like this:
grails $ENVIRONMENT war
Hope this helps
Update 2
By default the grails run-app runs with the dev environment, but you can force an environment by doing
grails $env run-app
If you want some default configurations to be run when you use the run-app command, then you should make sure that configuration is not in the environment block in either application.yml or application.groovy
Example of configuration in the environment block:
-----------------------------------------------------
environment{
development{
appConfig{
ishybrid = true
}
}
}
Example of configuration not in any environment block:
-------------------------------------------------------
appConfig{
ishybrid = true
}
environment{
development{
//other configs
}
}
So basically depending on what you exclude from the environment block configuration is what will be configured as the default configuration for your application to run.
Hope this helps better?

Spring Boot refuses to pick up application test properties [duplicate]

I have a spring boot application that I can package in a war that I want to deploy to different environments. To automate this deployment it'd be easier to have the configuration file externalized.
Currently everything works fine with a application.properties file in src/main/resources. Then I use ´mvn install´ to build a war deployable to tomcat.
But I would like to use a .yml file that does not need to be present on mvn install but that would be read from during deployment of the war and is in the same or a directory relative to my war.
24. externalized configuration shows where spring boot will look for files and 72.3 Change the location of external properties of an application gives more detail on how to configure this but I just do not understand how to translate this to my code.
My application class looks like this:
package be.ugent.lca;
Updated below
Do I need to add a #PropertySource to this file? How would I refer to a certain relative path?
I feel like it's probably documented in there as most spring boot documentation but I just don't understand how they mean me to do this.
EDIT
Not sure if this should be a separate issue but I think it's still related.
Upon setting the os variable the error of yaml file not found went away. Yet I still get the same error again as when I had no application .properties or .yml file.
Application now looks like this:
#Configuration
**#PropertySource("file:${application_home}/application.yml")**
#ComponentScan({"be.ugent.lca","be.ugent.sherpa.configuration"})
#EnableAutoConfiguration
#EnableSpringDataWebSupport
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
The application_home OS variable
$ echo $application_home
C:\Masterproef\clones\la15-lca-web\rest-service\target
My application.yml file(part it complains about):
sherpa:
package:
base: be.ugent.lca
Error upon java -jar *.war
All variations upon:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'sherpa.package.base' in string value "${sherpa.package.base}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:808)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1027)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
... 142 more
Using external properties files
The answer lies in the Spring Boot Docs, I'll try to break it down for you.
First of all, no you should not use #PropertySource when working with Yaml configuration, as mentioned here under the Yaml shortcomings :
YAML files can’t be loaded via the #PropertySource annotation. So in the case that you need to load values that way, you need to use a properties file.
So, how to load propery files? That is explained here Application Property Files
One is loaded for you: application.yml , place it in one of the directories as mentioned in the link above. This is great for your general configuration.
Now for your environment specific configuration (and stuff like passwords) you want to use external property files, how to do that is also explained in that section :
If you don’t like application.properties as the configuration file name you can switch to another by specifying a spring.config.name environment property. You can also refer to an explicit location using the spring.config.location environment property (comma-separated list of directory locations, or file paths).
So you use the spring.config.location environment property.
Imagine you have an external config file: application-external.yml in the conf/ dir under your home directory, just add it like this:
-Dspring.config.location=file:${home}/conf/application-external.yml as a startup parameter of your JVM.
If you have multiple files, just seperate them with a comma. Note that you can easily use external properties like this to overwrite properties, not just add them.
I would advice to test this by getting your application to work with just your internal application.yml file , and then overwrite a (test) property in your external properties file and log the value of it somewhere.
Bind Yaml properties to objects
When working with Yaml properties I usually load them with #ConfigurationProperties, which is great when working with for example lists or a more complex property structure. (Which is why you should use Yaml properties, for straightforward properties you are maybe better of using regular property files). Read this for more information: Type-Safe Configuration properties
Extra: loading these properties in IntelliJ, Maven and JUnit tests
Sometimes you want to load these properties in your maven builds or when performing tests. Or just for local development with your IDE
If you use IntelliJ for development you can easily add this by adding it to your Tomcat Run Configuration : "Run" -> "Edit Configurations" , select your run configuration under "Tomcat Server" , check the Server tab and add it under "VM Options".
To use external configuration files in your Maven build : configure the maven surefire plugin like this in your pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dspring.config.location=file:${home}/conf/application-external.yml</argLine>
</configuration>
</plugin>
When running JUnit tests in IntelliJ:
Run → Edit Configurations
Defaults → JUnit
add VM Options -> -ea -Dspring.config.location=file:${home}/conf/application-external.yml
Yes, you need to use #PropertySource as shown below.
The important point here is that you need to provide the application_home property (or choose any other name) as OS environment variable or System property or you can pass as a command line argument while launching Spring boot. This property tells where the configuration file (.properties or .yaml) is exactly located (example: /usr/local/my_project/ etc..)
#Configuration
#PropertySource("file:${application_home}config.properties")//or specify yaml file
#ComponentScan({"be.ugent.lca","be.ugent.sherpa.configuration"})
#EnableAutoConfiguration
#EnableSpringDataWebSupport
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
There is a very simple way to achieve this.
Inside your original application.properties file you can just specify the following line:
spring.config.import=file:Directory_To_The_File/Property_Name.properties
It will automatically sync all the properties from the external property file.
Now lets say that you have a situation where you need to get properties from multiple property files. In that case, you can mention the same line in the external property file which in turn will take the remaining properties from the second property file and so on.
Consider the following example.
application.properties:
spring.config.import=file:Resources/Custom1.properties
Custom1.properties:
server.port=8090
.
.
.
spring.config.import=file:Resources/Custom2.properties
One of the easiest way to use externalized property file using system environment variable is, in application.properties file you can use following syntax:
spring.datasource.url = ${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/"nameofDB"
spring.datasource.username = ${OPENSHIFT_MYSQL_DB_USERNAME}
spring.datasource.password = ${OPENSHIFT_MYSQL_DB_PORT}
Now, declare above used environment variables,
export OPENSHIFT_MYSQL_DB_HOST="jdbc:mysql://localhost"
export OPENSHIFT_MYSQL_DB_PORT="3306"
export OPENSHIFT_MYSQL_DB_USERNAME="root"
export OPENSHIFT_MYSQL_DB_PASSWORD="123asd"
This way you can use different value for same variable in different environments.
Use below code in your boot class:
#PropertySource({"classpath:omnicell-health.properties"})
use below code in your controller:
#Autowired
private Environment env;

Spring Initialized Properties using propertysourcesplaceholderconfigurer referred from another project

I have a mvn project packaged as applicationConfig.jar that contains commonly shared properties across different other projects (WAR's(web application eg: application.war) and JAR's(batch eg: applicationBatch.jar)).
I have used propertysourcesplaceholderconfigurer using annotation to initialize these properties in my applicationConfig.jar
This applicationConfig.jar is now added as dependency in pom.xml's for application.war & applicationBatch.jar
1) The java code in application.war is able to access properties initialized by code executed in applicationConfig.jar on server startup property. No issues here.
2) The applicationBatch.jar which is run from command line on linux machine, is unable to access properties. It appears like the properties initialization code is never executed, when the applicationBatch.jar is run.
Can anyone please help how can i ensure, code sitting in Jar file (applicationConfig.jar responsible for initializing properties using propertysourcesplaceholderconfigurer), is executed, when a batch jar (applicationBatch.jar) is run from command line.
Code Snippet Below:
applicationConfig.jar:
[Attachment ][1]
[Property referenced using annotation and property from properties file][2]
Spring will manage InternalConfig if you import it using #Import or have configured component scan with a base package parent of the InternalConfig one. applicationBatch seems to miss one of this method.
Could you check that ?

Setting system property get agent in teamcity maven build

I am trying to create plugin, which deploys my application in pre-integration-phase and runs the test against it. Now my application requires some property called LOOKUPLOCATOR which should be unique per envrionment. Now i have multiple agents configured in teamcity and many builds can run in parallel and if all the builds will have same property they will interfere with each other and test results will be unexpected.
Is there a way so that when my build run and in my java code if somehow get to know the agent name, and i will maintain a hardcoded value for LOOKUPLOCATOR for each agent, we can set that value. So my property will be per agent
Teamcity has some pre-defined variables which are available while a build is running. Agent name can be found in %teamcity.agent.name%.
Here is how to set agent-specific parameters
If additional applications/libraries are available in the environment, the administrator can manually define the property in the /conf/buildAgent.properties file. These properties can be used for setting various build configuration options, for defining build configuration requirements (for example, existence or absence of some property) and inside build scripts.

spring boot log4j file external to jar?

how to pass? The only way I can get this to work is to put log4j.xml on the classpath.
passing: -Dlog4j.configuration=file:///c:\log4j2.xml on the command line doesn't work (although it does in a non spring-boot test application just fine).
I also tried putting this as an environment variable/property in spring.
Try to put this line into your application.properties:
logging.config=file:log4j.xml
Second option is to pass system variable to -Dlogging.config=file:log4j.xml
In this case it is expected to be located in current directory outside of the JAR file.
you must put the "-Dlog4j" before the "-jar XXXX.jar".i try it my own .work for me.
If you are using gradle, and trying to run a test method you will have to add following to the build.gradle. This enables the test method to pick -Dlog4j.configurationFile= to be picked during the test run :
test {
systemProperty "log4j.configurationFile", System.getProperty("log4j.configurationFile")
}

Categories