Add Gradle properties to application.properties resource - java

I have mutli-module Gradle application and I would to add properties which I've defined in gradle.properties to be available in application.properties of all my subprojects in /src/main/resources folder.
What I've alread tried is adding processResources plugin to subprojects section.
subprojects {
processResources {
expand(project.properties)
}
// ...
As an example, I've defined the following property in gradle.properties file:
appVersion='0.0.1-SNAPSHOT'
Now, I want it to be present in application.properties, so I've added a placeholder as stated here. So, my application.properties looks the following way:
app.version=${appVersion}
Later on, I would like to use it using Spring, e.g.:
#Value("${app.version}")
However, after the project is built, properties are not replaced, so I have no version value in application.properties and still ${appVersion} placeholder. Any suggestions how to do that?

I feel strongly that you should have separate folders for separate purposes. Therefore I suggest moving application.properties to src/main/filteredResources. Then:
import org.apache.tools.ant.filters.ReplaceTokens
processResources {
with copySpec {
from 'src/main/filteredResources'
filter(ReplaceTokens, tokens: project.properties)
}
}

The problem was not in the Gradle configuration, but how my Spring Boot application started. I was running main() method directly from Intellij IDEA, which didn't work for me well, probably some of the tasks were not executed properly.
So, the solution is to run ./gradlew bootRun command. This way properties are getting correctly replaced.

Related

Gradle set name for jar created with spring-boot's assemble

I want to create an executable jar with gradle (kotlin-dsl) and I want to give it a custom name. For the executable jar I'm using the spring boot plugin and ./gradlew :app1:assemble:
plugins {
id("myproject.java-application-conventions")
id("org.springframework.boot") version "2.2.2.RELEASE"
}
dependencies {
implementation(project(":lib"))
}
application {
mainClass.set("org.myproject.app.Main")
}
init created two more files, buildSrc/build.gradle.kts:
plugins {
`kotlin-dsl`
}
repositories {
gradlePluginPortal()
mavenCentral()
}
and buildSrc/src/main/kotlin/myproject.java-application-conventions.gradle.kts:
plugins {
id("lomboker.java-common-conventions")
application
}
With ./gradlew :app1:assemble I can create an executable jar but I don't see how I can set its name.
This question deals with naming jars but I don't know how to apply any answers to my problem.
Adding a jar block to my gradle file does not work: Expression 'jar' cannot be invoked as a function. it is interpreted as sun.tools.jar.resources.jar. So I try tasks.jar instead.
For
tasks.jar {
archiveBaseName.set("myapp")
archiveVersion.set("version")
}
./gradlew :app1:jar while building successful creates no jar (it wouldn't be executable anyway) and ./gradlew :app1:assemble ignores the properties and just creates ./app1/build/libs/app1.jar.
Since I'm not using jar but assemble I guess I should use a tasks.assemble block. But that doesn't recognize archiveBaseName or archiveVersion and I don't know what the API is.
This is the page: https://plugins.gradle.org/plugin/org.springframework.boot but I find no API.
assemble is a lifecycle task which means that it doesn’t create anything. Its role is to trigger other tasks that it depends upon and that do have some output. You can see those tasks by running your build with --console=plain.
The task that creates the Spring Boot fat jar is named bootJar. As you can see from its javadoc, it’s a customization of Gradle’s Jar and can be configured in the same way:
tasks.bootJar {
archiveBaseName.set("myapp")
archiveVersion.set("version")
}

Overriden application.yml in multi-module Spring Boot app

There is a Spring Boot 2 app with such a structure:
parent-module
module-1
src
main
java
resources
- application.yml
module-2
src
main
java
resources
- application.yml
Also, module-1 depends on module-2, specified in pom.xml dependencies section.
The problem is that when I specify some properties in module-2's application.yml - they are not visible in main module-1's components (via #Value annotation).
As was answered here seems like module-1's application.yml overrides module-2's application.yml. There is a workaround - if I use name application.yaml in module-2 everything works fine, but I'm going to add more modules and, finally, it's dirty hack.
What I'm doing wrong? Should such an hierarchy of property files specified somehow?
I will be happy to provide more details if it's needed.
Thank you!
Spring Boot is a runtime framework. I understand that your modules are not spring-boot applications by themselves (you can't make a dependency on a spring boot application packaged with spring boot maven plugin, because it produces an artifact that is not really a JAR from the Java's standpoint although it does have *.jar extension).
If so, they're probably regular jars. So you should have a "special" module that assembles the application. This special module lists both 'module1' and 'module2' in <dependency> section and should contain a definition of spring-boot-maven-plugin in its build section (assuming you're using maven). But if so you shouldn't really have more than one application.yml - it will be misleading. Instead, put the application.yml to the src/main/resources of that "special" module.
If you really have to for whatever reason work with multiple application.yaml files, make sure you've read this thread
I know, this is already a well-aged post.
I just came accross the same issue and the best solution I found was to import the module-specific configurations with the spring.config.import directive as described here.
In this case you still have your module specific configuration in property or yaml files within that specific module and do not have too much unwanted dependencies in your project setup.
application.yml is, as the name indicates, an application-level file, not a module-level file.
It is the build script that assembles the final application, e.g. the .war file, that needs to include a application.yml file, if any.
If modules need properties, and cannot rely on the defaults, e.g. using the : syntax in #Value("${prop.name:default}"), they need to provide a module-level property file using #PropertySource("classpath:/path/to/module-2.properties").
Note: By default, #PropertySource doesn't load YAML files (see official documentation), but Spring Boot can be enhanced to support it. See #PropertySource with YAML Files in Spring Boot | Bealdung.
Alternative: Have the application-level build script (the one building the .war file) merge multiple module-level build scripts into a unified application.yml file.

In Gradle, associating task with a dependency configuration

How can a task be associated to a specific dependency configuration?
If I look the 23.5. Dependency management (gradle java plugin official doc) section part, it states that, for example, compileTestJava task use testCompile configuration.
I just wanted to know how I could achieve that.
gradle is creating these configurations automatically;
if you define a sourceSet, a bunch of things gets created (by convention):
sourceSets {
thing
}
will define configurations: thingCompile, thingRuntime
tasks: compileThingJava, processThingResources, thingClasses
you might want to look at: gradle tasks --all and gradle dependencies
if you want to add dependencies to these configurations
the most preferable to use the generated ones
you may of course create your own configuration and extend from that: configurations { thingCompile.extendsFrom(myConfig) }

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")
}

Gradle with Eclipse - resources are not filtered

I have a gradle configuration setup to filter some resources and substitute properties depending on the environment (e.g. dev, production). These are located at:
src/main/resources/config.xml
WebContent/WEB-INF/web.xml
An example of a property from my web.xml file is below:
<context-param>
<param-name>server.url</param-name>
<param-value>${server_url}</param-value>
</context-param>
An excerpt from my build.gradle is presented below:
apply plugin: 'eclipse-wtp'
processResources {
expand(props) // filter properties by environment
exclude 'log4j.properties'
}
war {
from 'WebContent'
exclude('WEB-INF/web.xml')
webInf {
from 'WebContent/WEB-INF/web.xml'
expand(props)
}
webXml = null
}
This works fine when I build a war from the command-line, but when I use this configuration from Eclipse it does not seem to filter the resource appropriately.
I previously had the Maven plugin working where the resources would get filtered as a part of the Eclipse build. Is it possible to get Eclipse to filter the resources?
You should use webAppDirNameproperty for your project and remove the manuell stuff in war { ... } block. I am not sure which Gradle version introduced this property but at least 2.0. See also http://www.gradle.org/docs/current/userguide/war_plugin.html.
Afterwards gradle eclipse should generate proper Eclipse artifacts to build your war or directly deploy to any server using wtp!

Categories