Setting gradle system property in .gradle file - gradle

I have a "general.gradle" file that sets the common properties for all of my projects.
This file is committed to git repository and shared among many users.
I would like to add a system property to is so it will be common to all the users
such options like systemProp.http.nonProxyHosts
is there a way?

You could make another file, like general.properties, add your system properties there prefixed by systemProp and then in general.gradle load the properties from that file, like so:
FileInputStream fileInputStream = new FileInputStream(new File('{YOUR_PATH}/general.properties'))
Properties properties = new Properties()
properties.load(fileInputStream)
fileInputStream.close()
properties.stringPropertyNames().forEach({key -> ext.set(key, properties.getProperty(key))})
and then load it to your root build.gradle file in projects, like so:
apply from: '{YOUR_PATH}/general.gradle'
You can retrieve it from the ext property. Following this example, if you put general.properties in your project and add there,for example: spring=dev. Then you put the property loading code in general.gradle and apply it in your build.gradle, if you add a task like this in your build.gradle:
task testProp << {
String profile = getProperty('spring')
System.setProperty('Spring.profiles.active', profile)
String prop = System.getProperty('Spring.profiles.active');
println prop
}
then the task execution should print out dev.

Related

How do you access gradle.ext properties in Plugin Java source code?

I need a property to (one) be available when a plugin is applied and (two) allow for a calculated override value in the settings.gradle file. A project property would be ideal as it can have a default set in gradle.properties:
# gradle.properties
myProp=originalValue
This is great because it can be overrode with a command line argument like -PmyProp=newValue, but I was not able to find a good way to override the property in the settings.gradle file before the build.gradle executes (i.e. before the plugins are applied).
For instance all of these leave rootProject.myProp unaltered at plugin application:
// settings.gradle
rootProject.getProperties.put("myProp", "overrideValue")
settings.ext.myProp = "overrideValue"
settings.extensions.myProp = "overrideValue"
gradle.startParameters.projectProperties.myProp = "overrideValue"
We cannot do any magic in the build.gradle either because no logic can exist before the plugins block:
// build.gradle
plugins {
id 'com.myCompany.myPlugin' version 1.0.0 // 'myProp' must be set by now
}
One workaround I can think of would be to use:
// settings.gradle
gradle.ext.myProp = "overrideValue"
... but there doesn't seem to be a good way to access gradle.ext properties in Java source code (for a plugin), or is there?
This seems to work for the gradle.ext.myProp use case, but it is surprising to me that the only workable approach is to cast the Gradle object to an ExtensionAware object:
// MyPlugin.java
String myProp = (String) project.getRootProject().getProperties().getOrDefault("myProp", null);
Gradle gradle = project.getRootProject().getGradle();
if ((myProp == null) && (gradle instanceof ExtensionAware)) {
ExtensionAware gradleExtensions = (ExtensionAware) gradle;
myProp = (String) gradleExtensions.getExtensions().getExtraProperties().get("myProp");
}
It seems like what I'm trying to do should be commonplace, so is there a better way like solely using project properties?
If so, then how do you change the values in the settings.gradle file?
This is probably not what you’re looking for but maybe it still helps: have you considered an initialization script? In such a script it is possible to override a project property.
Example:
$ ./gradlew -PmyProp=originalValue properties | grep myProp
myProp: originalValue
$ ./gradlew -PmyProp=originalValue -I init.gradle properties | grep myProp
myProp: overrideValue
… where init.gradle is the following:
allprojects {
project.ext.myProp = 'overrideValue'
}
Note that there are also other ways of specifying the init script.

Activate profile while submitting Apache storm topology of a maven project (Without recompiling)

I have to activate the profile while submitting the jar to storm like we do for a spring/boot project. like below
java -jar project-xyz.jar --spring.profiles.active=dev.
It is a maven project with multiple sub modules. we have the resources structured
Anything that is common to all the profiles will go in the root directory of resources, and anything that is specific to a profile (like DB connections) will go in that particular profile directory.
The root directory file will have the place holders for profile specific properties and will be replaced by the actual properties defined in profile directory.
Ex: ${mysql.host} will be resolved to localhost when local profile is active.
This final file will be placed in the classpath when we build the jar using
mvn clean install -P{profile}
And then the topology is submitted to storm like the following.
storm jar project-xyz.jar path.to.class.containing.main.method
The final properties file generated by maven will be read by a property reader, stored and served whenever requested.
private static final Map<String, Properties> properties = new HashMap<>();
public static String getProperty( String file, String key )
{
try {
if ( !properties.containsKey( file ) ) {
synchronized ( properties ) {
if ( !properties.containsKey( file ) ) {
loadProps( file );
}
}
}
return properties.get( file ).getProperty( key );
} catch ( IOException e ) {
throw new PropertyException( "There was a problem getting " + key + " from " + file + ".properties", e );
}
}
private static void loadProps( String file ) throws IOException
{
InputStream inputStream = PropertyFileHandler.class.getClassLoader().getResourceAsStream( file + ".properties" );
if ( inputStream == null ) {
throw new FileNotFoundException( "Property file " + file + ".properties not found" );
}
Properties prop = new Properties();
prop.load( inputStream );
properties.put( file, prop );
}
I've already gone through this question and its different in a way that I use maven and I have to activate the profile instead of providing specific property.
So, is there a way I can activate the profile while submitting the jar to storm somewhat like the following?
storm jar project-xyz.jar --profiles.active=dev
If not, what can I do to achieve this without re-compiling the source? Does converting it to a spring boot project help?
You won't be able to do this as long as you're using Maven to generate a jar containing a single properties file. That jar can only be used in the environment you generated it for.
Instead, you could include all the possible properties files in the jar, and decide which one to read based on a system or environment property.
A better option is probably that you generate the property files separately to the jar, and then put the jar plus property file into Storm. You can pass the property file path to your Storm submission code as a command line argument to your main method. You would then read the properties into memory, and pass them to your bolts/spouts. You need to do this loading eagerly (i.e. read the entire properties at topology submission time, rather than when you need a specific property), so your lazy loading configuration code should be discarded.
You might want something like Flux for convenience:
To enable property filtering, use the --filter command line option and
specify a .properties file. For example, if you invoked flux like so:
storm jar myTopology-0.1.0-SNAPSHOT.jar org.apache.storm.flux.Flux
--local my_config.yaml --filter dev.properties
With the following dev.properties file:
kafka.zookeeper.hosts: localhost:2181
You would then be able to reference those properties by key in your
.yaml file using ${} syntax:
- id: "zkHosts"
className: "org.apache.storm.kafka.ZkHosts"
constructorArgs:
- "${kafka.zookeeper.hosts}"
See the documentation at https://storm.apache.org/releases/2.1.0/flux.html.

Gradle multi-project build: how to specify different build files?

Gradle multi-project build: how to set different build files? e.g.
/foo/bar/build-hello.gradle
/foo/bar/build-world.gradle
settings.gradle
include 'hello'
project(':hello').projectDir = new File('/foo/bar')
project(':hello').buildFile = new File('/foo/bar/build-hello.gradle')
include 'world'
project(':world').projectDir = new File('/foo/bar')
project(':world').buildFile = new File('/foo/bar/build-world.gradle')
Error: can not set readOnly property buildFile.
How to specify a different build file other than the default build.gradle?
EDIT:
https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:projectDir
File projectDir (read-only)
The directory containing the project build file.
projectDir is also readOnly. But no error in setting its value. Why?
The settings.gradle file operates on a Settings object, whose project() method returns ProjectDescriptor instances, because the Project instances are not created at this point of the Gradle build.
The read-only buildFile property of the ProjectDescriptor instances is created from the two writable properties projectDir and buildFileName:
include 'hello'
project(':hello').projectDir = new File('/foo/bar')
project(':hello').buildFileName = 'build-hello.gradle'
include 'world'
project(':world').projectDir = new File('/foo/bar')
project(':world').buildFileName = 'build-world.gradle'

TeamCity server url from build script

I heed to use TC API from build script (gradle). I can read user name and password, from project properties, but I have to read serverUrl as well. But I did not find property teamcity.serverUrl described in doc (right there)
May be this property is missed only on our build TC server?
This very parameter is a configuration parameter
Such parameters can be used in web UI, but are not implicitly passed to Gradle build
In your case, use Additional Gradle Command Line Parameters field in build step configuration and add following flag:
-PserverUrl=%teamcity.serverUrl%
This will pass the value explicitly. You can access server url in gradle like this:
println("Server url is $project.serverUrl")
UPD
If customising paramteres is not an option, you can use another way. There is a system property teamcity.configuration.properties.file that contains path to a file, that contains all the configuration parameteres in usual properties format. So, inside Gradle do something like:
def configFilePath = project["teamcity.configuration.properties.file"]
def props = new Properties();
props.load(new File(configFilePath).newDataInputStream())
def serverUrl = props["teamcity.serverUrl"]

Getting Gradle 'rootProject' object to honor env vars

I ran across the following configuration in a Gradle project's buildfile (build.gradle):
codenarcMain {
configFile = rootProject.file("gradle/codenarc/CodeNarcMain.groovy")
}
When I Google "Gradle rootProject" I find this link which makes it look like rootProject is a ProjectDescriptor instance.
But looking at ProjectDescriptor, I don't see any property called file. I see a buildFile and projectDir, but no file property.
Ultimately, I am trying to get Gradle to load the CodeNarc config file from outside the build directory. On my system I have an env var called $CODENARC_HOME with the following directory structure:
CODENARC_HOME/ (say this is /home/myuser/tools/codenarc/)
CodeNarcMain.groovy
CodeNarcTest.groovy
README.md
Now I would like to change the CodeNarc config in Gradle to look something like this:
codenarcMain {
configFile = rootProject.file("CODENARC_HOME/CodeNarcMain.groovy")
}
And then, no matter where CODENARC_HOME is defined, the Gradle build will still be able to locate the config file.
So my questions:
What is the file property on rootProject, and why don't I see it in the API docs (linked above)?; and
How to get rootProject.file(...) to honor system/env vars inside its file path string argument?
rootProject in settings.gradle is-a ProjectDescriptor. rootProject in build.gradle is-a Project. Environment variables and system properties can be accessed in the standard Java way:
codenarcMain {
configFile = rootProject.file("${System.getenv("CODENARC_HOME")}/CodeNarcMain.groovy")
// or: System.getProperty("codenarc.home")
}

Resources