How do I just change the contents of a resource file in the war plugin?


(Mike Smithson) #1

I have an xml file where I want to just change a single line in the file and nothing else. I am able to change the content of the file but I can’t seem to figure out how to preserve that change while keeping the file name and location the same. Any ideas?


(Shinya Mochida) #2

How about using Groovy’s GStringTemplateEngine. (see detail)

for example.

Project structure is following.

.
├── build.gradle
├── src
│   └── main
│       ├── java
│       │   └── com
│       │       └── sample
│       │           └── model
│       │               └── Person.java
│       ├── resources
│       │   └── application.properties
│       └── webapp
│           ├── WEB-INF
│           │   └── web.xml
│           └── index.html
└── template
    └── application.properties

And if you wish to change application.properties file, when creating war file.

build.gradle file is as following.

// declaration of plugins/dependencies/repositories

import groovy.text.GStringTemplateEngine

task prepareApplicationProperties {
    // load template file
    def template = file('template/application.properties')
    // changing file via stage
    def appProperties = file('src/main/resources/application.properties')
    outputs.file appProperties
    outputs.upToDateWhen {
        false
    }
    doLast {
         // change contents via cli options
        def env = project.hasProperty('appPort') ? appPort : 'dev'
        def port = env == 'dev' ? 8080 : appPort as int
        def binding = [port: port]
        // change file contents
        def tmp = new GStringTemplateEngine()
            .createTemplate(template)
            .make(binding)
        appProperties.write(tmp.toString(), 'UTF-8')
    }
}

tasks.idea.dependsOn 'prepareApplicationProperties'
tasks.war.dependsOn 'prepareApplicationProperties'

This script generates application.properties file before idea task(if you use eclipse change idea to eclipse) and war task.

Template file is following.

server.port=$port

if you run idea task (thus this is develop environment), without -PappPort option…

$ ./gradlew idea

Then application.properties will becomes as follows.

server.port=8080

If you run war task with -PappPort option…

$ ./gradlew war -PappPort=9999

Then the contents of WEB-INF/classes/application.properties file becomes

server.port=9999

(Mark Vieira) #3

You can leverage Groovy’s SimpleTemplateEngine by just passing a map to any Copy task’s expand() method.

war {
    expand hostname: 'server.foo.org'
}

(Mike Smithson) #4

Unfortunately, we cannot use templating in the file that needs to have its content replaced, we would need to do some sort of replace(). I think it boils down to my limited knowledge of Gradle and Groovy.


(Lance Java) #5

Possibly easiest to use with(CopySpec) in either the war or processResources tasks (depending on the target folder)

war {
   with copySpec {
      from 'src/template/webapp' 
      filter(ReplaceTokens, tokens: ['someToken':'someValue']) 
   } 
} 
processResources {
   with copySpec {
      from 'src/template/resources' 
      filter(ReplaceTokens, tokens: ['someToken':'someValue']) 
   }
} 

(Vic Seedoubleyew) #6

Link to stackoverflow post for better quality : https://stackoverflow.com/questions/33464577

To complement Lance_Java's answer, I found this idiom more simple if there’s only one value you are looking to change:

task generateSources(type: Copy) {
    from 'src/replaceme/java'
    into "$buildDir/generated-src"
    filter { line -> line.replaceAll('xxx', 'aaa') }
}