Changing your production source code location - java

According to the gradle user guide: http://www.gradle.org/docs/current/userguide/userguide.pdf top of page 41 "Gradle expects to find your production source code under src/main/java". How can I customize gradle to use with my current and different directory structure?

Take a look at the Gradle docs regarding source sets. You can specify your source directory like so:
sourceSets {
main {
java {
srcDir 'path/to/java/src'
}
}
}

Related

Gradle copy command deprecated, breaks build

In Gradle 3.x I was able to get some xml mapping files to copy into the classes directory prior to build/jar via the following block:
copy{
from 'src/main/java/com/company/mapping'
into 'build/classes/main/java/com/company/mapping'
include '**/*.xml'
}
In Gradle 4.9 this has been deprecated in favor of:
task copyMappings(type: Copy){
from 'src/main/java/com/company/mapping'
into 'build/classes/main/java/com/company/mapping'
include '**/*.xml'
}
The copyMappings task succeeds, but build/jar does not wait for copyMappings to finish. I have tried variations on build.dependsOn and doFirst{ copyMappings } doLast{ build } but nothing seems to get me the desired effect of having the copied files in place in the 'into' path prior to jar.
This is for Windows 10.
This works for me with Gradle 4.9 on Mac OS:
apply plugin: 'java'
task copyMappings(type: Copy) {
from 'src/main/java/com/company/mapping'
into 'build/classes/main/java/com/company/mapping'
include '**/*.xml'
}
jar.dependsOn copyMappings
jar.doFirst {
assert new File("${projectDir}/build/classes/main/java/com/company/mapping/abc.xml").exists()
assert new File("${projectDir}/build/classes/main/java/com/company/mapping/def.xml").exists()
}
command line is gradle clean jar
I like to model things around source sets where appropriate as doing so let's the build work more reliably with a wide range of plugins and use cases. For example, imagine you want to run an application direct from its class files and resources rather than packaging it as a JAR first. You could make sure that the "run" task depends on the copy as well, but you'd have to do that for every instance where this is a requirement.
Source sets are the ideal solution because they have the concept of a runtime classpath, which will work for packaging, instrumentation, running, testing and so on.
With that in mind, I would go for this simple declaration and get rid of the copy task:
sourceSets {
main {
resources {
srcDir "src/main/java"
include "**/*.xml"
}
}
}
The XML files will end up in a different directory from your current approach, but that shouldn't matter unless you have tasks that assume the location rather than using the source set model to get the necessary information.
Note The above include directive applies to all the resources in src/main/resources as well. So if you have properties files or text files or anything else in there, they will be excluded. The simplest solution is to add all required resource file patterns to the include directive.

gradle compile multipe source

This is straight from Gradle 3.2.1 specifying_multiple_files. Why this does not work ? Why it cannot pick up files from ../shared/java during compilation. Compilation fails for sources in src/main/java depend on ../shared/src
The example is straight from Gradle
task compile(type: JavaCompile)
compile {
// Add some source directories use String paths
source 'src/main/java', 'src/main/groovy'
// Add a source directory using a File object
source file('../shared/java')
// Add some source directories using a closure
source { file('src/test/').listFiles() }
}
Unfortunately that page is written to show how you can work with files, but not necessarily how to configure the Java Compiler.
https://docs.gradle.org/current/userguide/java_plugin.html
That page will give you the details for what you are trying to solve. What you need is to instead just define the sourceSet.
sourceSets {
main {
java {
srcDirs = ['src/main/java', '../shared/java']
}
}
}

gradle / intellij - shared test resource(s)

I have a gradle based project with 8 subprojects. Each of these has test code that relies on a folder with a number of .csv files for content. I'd rather not copy this folder into the test path of each subproject.
Is there a way to tell gradle to look for the files in a common location?
How about for IntelliJ? I tried indicating the files were a 'test resource' but haven't figured out how to get each sub-module to find them (without resorting to '../..' style notation)
I did that providing the path to the common files folder on sourceSets in the build.gradle file:
sourceSets {
test {
resources {
srcDirs = ["src/test/resources", "src/main/resources/db"]
}
}
Not sure if that's a clean way to do that, but for me it's better than copypasting the same files over multiple locations.

How do I specify an extra folder to be on the classpath for gradle's application plugin 'run' task?

I've successfully configured my gradle build script to create a zip distribution of my application with an extra 'config' folder at the root. This folder contains (at least right now) only one properties file in use by the application, and is on the classpath for the application.
What I'm looking for now, however, is a way to do the same with the 'run' task in the application plugin. When I try to run my application this way, (for testing), my program fails to run because of a class trying to access this properties file on the root of the classpath.
A bonus would be if I could get IntelliJ or Eclipse to also add this folder to its classpath just like the other folders (src/main/java, src/main/resources, ...) so I can run and debug my code from within the IDE without invoking a gradle task. I want to try to avoid as much as possible tying this code to any one IDE, so that when anybody needs to work on the project, they just need to import the build.gradle file and have the IDE make the appropriate config files it needs.
Here is my build.gradle file:
apply plugin: 'application'
mainClassName = "MainClass"
startScripts {
// Add config folder to classpath. Using workaround at
// https://discuss.gradle.org/t/classpath-in-application-plugin-is-building-always-relative-to-app-home-lib-directory/2012
classpath += files('src/dist/config')
doLast {
def windowsScriptFile = file getWindowsScript()
def unixScriptFile = file getUnixScript()
windowsScriptFile.text = windowsScriptFile.text.replace('%APP_HOME%\\lib\\config', '%APP_HOME%\\config')
unixScriptFile.text = unixScriptFile.text.replace('$APP_HOME/lib/config', '$APP_HOME/config')
}
}
repositories {
...
}
dependencies {
...
}
Likely what needs to happen is that I need to have the /src/dist/config folder to be copied into the build directory and added to the classpath, or have its contents be copied into a folder that is already on the classpath.
I ended up taking Opal's suggestion as a hint, and came up with the following solution. I added the following to my build.gradle file:
task processConfig(type: Copy) {
from('src/main/config') {
include '**/*'
}
into 'build/config/main'
}
classes {
classes.dependsOn processConfig
}
run {
classpath += files('build/config/main')
}
Alternatively, a simpler approach would be to add a runtime dependency to my project as such:
dependencies {
...
runtime files('src/main/config')
}
I didn't end up doing it this way, however, because my distribution package ended up having .properties files in the lib folder... and I'm just picky that way.
As you can see in the docs run is a task of type JavaExec. So classpath for it can be modified. Try to add config folder to the classpath. See here.

Deploy additional files in Gradle Application Plugin

I have a small Java/Gradle project. I'm using the Application plugin to create a zip distribution (using the distZip task). Using the standard configuration I get the following directories in my zip file:
/bin - The scripts to start the application go in here
/lib - Contains my project code in a JAR file and all dependency JAR files.
The trouble is that I would like a third directory: /conf where I can put my configuration files (instead of having them packaged inside my application JAR file.
I imagine that this is a pretty common requirement because things like log4j.xml and hibernate.properties would be better placed outside the JAR file. I just can't figure out how I can customise the behavior of the Application plugin to do this however.
I revisited this problem several months later and I finally have an elegant solution. The following code should be added to the gradle file:
distZip {
into(project.name) {
from '.'
include 'conf/*'
}
}
This adds an additional include to the distZip task. This copies the "conf" directory (including contents) into the Zip distribution.
The generated zip file contains a single directory which is the same as the project name. This is why the "into" part is required.
Actually, create a dist dir under the src dir in your project. Anything in this dir is copied by the application plugin (under applicationDistribution) when installApp or distZip is run.
Or edit applicationDistribution to do other things, if a simple copy is not enough.
For me, a simple
applicationDistribution.from("src/main/config/") {
into "config"
}
did the job. Of course you need to have your properties loaded correctly from within code. Especially if you move them from src/main/resources where they have been usable via classpath, into the new location. I circumvented this by adding a command line parameter which points to the configuration file.
I am not sure whether you can customize the application plugin, I have never used it. There is however other ways to achieve what you want to achieve.
You may create a /conf directory like this:
confDir = new File("$buildDir/conf")
You can then copy the files you need into this directory like this:
task copyConfFiles(type: Copy) {
from _wherever your files reside_
into confDir
include('**/*.properties') // your configuration files
}
You may then hook this copy task into the process like this:
distZip.dependsOn copyConfFiles
And last if you do not want your configurations in the final zip, you can do this:
distZip {
exclude('**/*.properties') // your configuration files
}
Again, there might be a better way. This is a way.
OP's self-answer may be good for his use case, but there are a few things I'd like to improve on:
His answer suggests that he has a directory conf parallel to the build.gradle. There is no such thing in the Maven Standard Directory Layout. The general consensus is to have a src/main/conf as had been hinted to in the docs:
If there are other contributing sources to the artifact build, they
would be under other subdirectories: for example src/main/antlr would
contain Antlr grammar definition files.
The target directory name is NOT project.name as had been pointed out in a comment.
If resource filtering is required, and it often is, then having a separate task is desirable. During local development, this task can be run to generate the filtered files. The distribution would merely use the output of this task (and unlike OP's answer, this also makes conf available to the tar distribution).
def props = new Properties()
file("src/main/filters/application.properties")
.withInputStream { props.load(it) }
import org.apache.tools.ant.filters.ReplaceTokens
task copyConf(type: Copy) {
from("src/main/conf/")
into("$buildDir/conf")
filesMatching("**/*.y*ml") {
filter(tokens: props, ReplaceTokens)
}
}
distributions {
main {
contents {
from(copyConf) {
into("conf")
}
}
}
}

Categories

Resources