Setting system property get agent in teamcity maven build - java

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.

Related

Can I change a database depending on the branch I am on (specified in Dockerfile)?

I would like to have my:
spring.datasource.url = jdbc:mysql://666.666.666.666/prod_very_wow
Change into:
spring.datasource.url = jdbc:mysql://666.666.666.666/dev_very_wow
According to the branch I am currently on. I think I should also have it specified within the Dockerfile - I should have a property added next to docker's RUN which should determine which data source ought to be activated.
Namely, I would like my app to be connected to prod_very_wow when I am on master branch and dev_very_wow everytime I am checking out to dev or creating a new feature branch and have it all determined by a property added to RUN mvn package within the Dockerfile.
I apologise if the question makes no sense, but, frankly - I am a little bit clueless how to ask this question and so I have troubles googling for answers.
I just found a couple of leads about "environmental variables", but I can't find any connection between the datasource connected to and the branch I am currently on.
The best way to handle different configuration based on environment is to have decoupled your code from your configuration that is one of the twelve-factor apps principles. In this case you should have an external config server, like spring cloud config server, that will host the configurations files for the different environments and the application will ask this config server for the proper config file depending on the environment where it is deployed.
However, if you don't want to follow this approach you can create the different configuration files in the application and use an environment variable that tells spring which file to use. For example, in your case you can have an application-local.yaml and application-prod.yaml, and then if you want to specify it in the dockerfile in the mvn package command, you can use:
RUN mvn -Dspring.profiles.activ=local package
RUN mvn -Dspring.profiles.activ=prod package

Java Microprofile change properties on already deployed app (Wildfly)

I have an ear artifact deployed on a wildfly server. On some beans I used the following configuration injection
#Inject
private Config config;
I want to change the properties specified on the "microprofile-config.properties" file on runtime. It is not necessary to change the file itself, I just want to change the properties. I think there might be a way using the console, but I cannot find if there is any.
If you take a look at the spec or even at articles like this, you will see that, by default, Microprofile config reads configuration values from the following 3 places in this order - i.e. from wherever it finds it first:
System.getProperties()
System.getenv()
The configuration file
So, you can override values in the configuration file in 2 ways:
Defining -D command line arguments to the VM (e.g. java -DXXX=yyy ...)
Defining system environment variables (e.g. export XXX=yyy in bash or set XXX=yyy in Windows)
Note that there are some rules for defining environment variables and matching them to actual configurations, e.g. for a configuration aaa.bbb.ccc you may need to set an environment variable as AAA_BBB_CCC. Read ch. 5.3.1 in the specs, and experiment a little.
You can always extend the configuration sources with your own custom ones (to read configuration from JNDI, DB, Zookeeper, whatever).

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

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

Need in understanding classpath in resource location and variable value set

Although I have been working in java for a while, there are many small things I have been ignoring, which at times have become bottleneck in productivity. I have difficulty in understanding this:
This is one of the bean.xml which gets placed in the final .war file (in a web application, built with spring framework).
<context:property-placeholder
location="classpath:/${deploy.env}/com.example.config/db.properties"
ignore-resource-not-found="false" />
I have following doubts:
1) At the time of building the code, i did like this for passing value of deploy.env
mvn clean install -Ddeploy.env=local
I ran the mvn in debug mode and could see this set to local. Now, the thing is, in the .war that gets generated, it is still ${deploy.env} (see above snippet). Doesn't this get replaced in the final .war? If not, then how do we pass the value which we intend to set?
2) what does "classpath:/${deploy.env}/com.example.config/db.properties" mean? Who sets the value of classpath? Are classpath capable of providing the location of resource files as well?
Assuming deploy.set --> local, so would this get translated to:
classpath:"/local/com.example.config/db.properties"
So does this mean db.properties would be present at: /local/com.example.config/db.properties
Any inputs to understand this would be of great help.
deploy.env is either environment variable or system property available to the JVM at run time.
The classpath:/${deploy.env}/com.example.config/db.properties will be resolved at run when your war is running in the container.
Set deploy.env=whatever in the shell from where you starting the tomcat or set in the environment of the user which starts the tomcat.
mvn clean install -Ddeploy.env=local here the deploy.env system property is available at build time. This will not replace the value of your spring config.
classpath is where all your classes and libraries bundled in the war are available along with the tomcat libraries. The spring property configurer will look for the db.properties file in the classpath at location e.g. /local/com.example.config
Spring documentation to learn more
Some explanation on my blog post
As stated in the Oracle Web site: The CLASSPATH variable is one way to tell applications, including the JDK tools, where to look for user classes.
That classpath: is referring to that location in particular, whatever it is, so it will start looking for those resources defined by Spring from that location and on, until it finds the first match.
Also, if you have that as a property in Maven, the value can be replaced with the right plug-in and configuration; not quite useful when you want a build that can be used with many values within those .properties files for different environments.
You can use other prefixes as file:, http:, etcetera. But you are just wondering about classpath:.

Setting OSGi storage directoy (org.osgi.framework.storage) does not work in Maven triggered JUnit test

In my code I start multiple OSGi frameworks using EquinoxFactory. By setting the property "org.osgi.framework.storage" to "#user.home/osgi-frameworks/framework-x", where x is different for every framework, each framework uses a different directory:
frameworkProperties.put("osgi.clean", "true");
frameworkProperties.put("osgi.console", "true");
frameworkProperties.put("org.osgi.framework.storage",
"#user.home/osgi-frameworks/osgi-framework-"
+ numberOfFramework);
framework = new EquinoxFactory().newFramework(frameworkProperties)
This works perfectly when running the actual application. Also the JUnit tests in the IDE run without any problems.
However, when I start the Maven build for my project, the JUnit tests fail since all frameworks use the same directory ("osgi-frameworks/framework-0").
I added logging to the application to check whether the property "org.osgi.framework.storage" does really have different value in the OSGi property map. Everything looks fine in the log, but when checking the file space, only one directory has been created.
Since I would like to include the application in Jenkins, I would rather not skip the tests.
Has anyone an idea what could be wrong? Do I have to set other parameters for the framework? Is there any considerable difference between Junit in the IDE and in Maven?

Categories