I'm using Spring REST Docs to generate documentation for our API.
I've added everything to build.gradle from tutorial here http://docs.spring.io/spring-restdocs/docs/current/reference/html5/
ext {
snippetsDir = file('build/generated-snippets')
}
test {
outputs.dir snippetsDir
}
asciidoctor {
attributes 'snippets': snippetsDir
inputs.dir snippetsDir
outputDir "build/asciidoc"
dependsOn test
sourceDir 'src/main/asciidoc'
}
jar {
dependsOn asciidoctor
from ("${asciidoctor.outputDir}/html5") {
into 'static/docs'
}
}
After I do gradle build I can see that in build/asciidoc directory files are generated and also in build/generated-snippets.
But when I run from IDEA gradle task bootRun and trying to access localhost:8080/docs/index.html I'm getting not found 404. Just for test I've tried to put some index.html file under resources/static directory and then do bootRun and I can access localhost:8080/index.html file after that.
If I open my .jar file I can see static files under directory BOOT-INF/classes/static/docs so they are packed into jar.
Maybe somebody had the same issue?
There are two things that you need to do so that the documentation is served when using bootRun. The first is to copy the generated documentation into a location that's on the classpath used by bootRun:
task copyRestDocs(type: Copy) {
dependsOn asciidoctor
from "${asciidoctor.outputDir}/html5"
into "${sourceSets.main.output.resourcesDir}/static/docs"
}
Note that this new task depends on the asciidoctor task. This ensures that the documentation has been generated before it's copied.
Secondly, the bootRun task must depend on the new copyRestDocs task:
bootRun {
dependsOn copyRestDocs
}
Related
I have a project where Gradle is not copying all test resources to the output dir, and I don't know if I am doing something wrong or if this is a bug in Gradle. I managed to create a simplified test case; the directory structure is as follows:
gradle/ # (contains Gradle wrapper files)
src/
hello/
Hello.java
tests/
hello/
hello.txt
foo/
bar.txt
build.gradle
gradlew
gradle.bat
The contents of build.gradle are as follows:
apply plugin: 'java'
sourceSets {
main {
java.srcDirs = ['src']
resources.srcDirs = ['src']
resources.excludes = ['**/*.java']
}
test {
java.srcDirs = ['tests']
resources.srcDirs = ['tests']
resources.excludes = ['**/*.java']
}
}
task staging (type: Copy) {
from processResources
from processTestResources { include 'foo/' } // Offending line
into "${buildDir}/staging"
}
task run (type: JavaExec) {
dependsOn staging
// [...]
}
When I run:
./gradlew processTestResources # or just ./gradlew test
Only the resources from tests/foo are copied to the output folder. The resources from tests/hello are not copied.
However, if I comment out the line marked as "Offending line" in the staging task, then all resources are copied.
Is this the expected behaviour? Looks like Gradle is trying to calculate which resources are needed, and sees that only tests/foo are necessary for the staging task. But I am not running the staging task; I should be able to run the processTestResources or test tasks and have all test resources copied to the output folder.
Is this a bug in Gradle?
Update:
Here's a link to the relevant issue in GH (closed as invalid since this is not really a bug, as explained in the accepted answer).
The issue is the way Groovy interprets the "offending line":
Without parenthesis, Groovy interprets everything after from as the argument.
And so it fetches the reference to the processTestResources task, applies the configuration closure to it, and then passes the result to from.
So the end result is that you configured in-line the processTestResources instead of configuring the from.
Adding parenthesis changes the meaning by clearly indicating that the result of calling from with a task is what is to be configured:
from(processTestResources) { include 'foo/' }
I have seen this post Gradle multi project distribution but still have some doubts.
I would like to create the following project layout
root
|--lib-java-module
|--spring-boot-module
|--3PP_A_module # not java
| |-- custom scripts, config
|--3PP_B_module # not java
| |-- custom scripts, config
|--dist-module
As you might have guessed, I want the dist-module to build myapp-dist.tar.gz with libjava.jar, sprintbootapp.jar, 3pp-a.tar, 3pp-b.tar.
myapp-dist.tar.gz
libjava.jar
sprintbootapp.jar
3pp-a.tar
3pp-b.tar.
The 3pp-a-module and the 3pp-b-module only contain some configuration files and startup scripts. No java or any compiled code. How to package them individually into tar files (no compression)?
How to define dependencies in dist-module to the other modules? Is it possible to get the other modules built when build is triggered from dist-module?
Update:
I setup my test project based on #marco-r's answer and it works except for packaging the war file. Checkout the test project from github https://github.com/KiranMohan/study-spring-boot.
This is the project setup of interest.
include ':sb-2.1-multi-package', ':sb-2.1-multi-package:hello-rest-lib',
':sb-2.1-multi-package:hello-rest-standalone-jar',
':sb-2.1-multi-package:hello-rest-war'
include 'sb-2.1-3pp-resources'
include 'sb-2.1-build'
However adding hello-rest-war to sb-2.1-build.tar.gz fails.
Instead of war files, its the dependencies that are getting packaged.
dependencies {
archivesDeps project(path: ':sb-2.1-3pp-resources', configuration: 'archives')
javaDeps project(":sb-2.1-multi-package:hello-rest-war")
}
...
task copyJavaDeps(type: Copy) {
inputs.files(configurations.javaDeps)
from configurations.javaDeps
into "${ARCHIVE_DIRECTORY}/lib"
}
...
// create distribution bundle
distributions {
main {
contents {
from ARCHIVE_DIRECTORY
into "/springapp/multimodule"
}
}
}
Contents of the package
springapp/multimodule/lib/classmate-1.4.0.jar
springapp/multimodule/lib/hello-rest-lib-0.0.1-SNAPSHOT.jar
springapp/multimodule/lib/hibernate-validator-6.0.16.Final.jar
...
springapp/multimodule/lib/tomcat-embed-websocket-9.0.17.jar
springapp/multimodule/lib/validation-api-2.0.1.Final.jar
springapp/multimodule/sb-2.1-3pp-resources/config/3pp.json
How to package war file (hello-rest-war module) and without all the transitive dependencies?
This is multiple question scenario, so I am going to address it in parts.
Since all 3PP_X_module have the same building requirements create a build.gradle in each of the submodules that refer to an actual build gradle that have the common functionality required:
apply from: '../tarArtifact.gradle'
In the parent folder create the previously referred tarArtifact.gradle to have the functionality to TAR the contents of a subfolder (arbitrarily chosen as contents) of a referring subproject:
apply plugin: 'base'
task tarContents(type: Tar) {
from 'contents'
archiveName = "${project.name}.tar"
destinationDir file('build/tar')
}
artifacts {
archives file: tarContents.archivePath, type: 'tar', builtBy: tarContents
}
Since the archives configuration is wired to the output of the tarContents (builtBy: tarContents), then the archives configuration can be used to retrieve the desired TAR as the output of building this project naturally.
Create in dist-module the following build.gradle file:
apply plugin: 'distribution'
plugins.withType(DistributionPlugin) {
distTar {
compression = Compression.GZIP
extension = 'tar.gz'
}
}
configurations {
wholeProjectDist
}
dependencies {
wholeProjectDist project(path: ':3pp-a-module', configuration: 'archives')
wholeProjectDist project(path: ':3pp-b-module', configuration: 'archives')
wholeProjectDist project(':lib-java-module')
wholeProjectDist project(':spring-boot-module')
}
distributions {
main {
contents {
from configurations.wholeProjectDist
}
}
}
This gradle file includes the following:
Applies the Distribution plugin, so we can generate the final tar.gz file from the artifacts generated by all the other subprojects.
Configures the distTar task (of the DistributionPlugin plugin) to compress any generated TAR using it by using GZIP.
Creates the configuration wholeProjectDist to capture the dependencies of dist-module itself; which we will use with the distribution plugin's tasks.
Declares the dependencies of dist-module as the artifacts output by the siblings' subprojects; using the newly created wholeProjectDist.
Configures the distribution's plugin main configuration to have as contents all the files from configurations.wholeProjectDist
Create a settings.gradle file under dist-module to allow it to access its siblings modules using includeFlat:
includeFlat '3pp-a-module', '3pp-b-module', 'lib-java-module', 'spring-boot-module'
Include in the parent folder a settings.gradle file to include all children submodules (as the root project):
includeFlat '3pp-a-module', '3pp-b-module', 'lib-java-module', 'spring-boot-module'
Build the desired tar.gz files by invoking the gradle command (from the root folder):
gradle :dist-module:distTar
Hope this helps.
We are migrating from Ant to Gradle. In the starting Gradle looked promising, when I started migrating targets from Ant to Gradle, facing similar issues, earlier having with Ant.
The Ant Build Flow looks like -
We have a Java application - Ant used to clean, compile and build jar of the project.
Next we have few targets to copy built jar and some other resources files to windows server.Its just a windows server not a nexus like repo.
These copy targets are release based(internally using macrodefs) - if alpha, it has to copy to different folder and for stable release different folder.
Another macrodef was to just backup the existing files present in server to a backup folder before copying new files there.
Migrating to Gradle-
I liked the way Gradle does the tasks of clean, compile and build. I am using Java plugin for this.
I am facing issues in next tasks to copy files to windows server and taking backup of old files before copying new files.
In Gradle I created few custom tasks like copyJarAlpha, copyJarStable,backupJarAlpha,backupJarStable etc..
Internally they are doing the same thing just copying files from source to destination and some print statements. But it looks repetitive. I was looking for ways like macrodef in ant.
task deployAlpha {
doFirst {
isJenkinsAvailable(deployDirAlpha)
}
doFirst {
if(isDeployLibsTaskRequired(outputDir,deployDirAlpha)) {
tasks.findByName('deployLibsAlpha').execute()
}
}
doLast {
println "Deploying corejar jar to : ${deployDirAlpha}"
copy {
from "${outputDir}/${corejar}"
into "${deployDirAlpha}"
}
println "Deploying evan-core jar to : ${deployDirAlpha}/lib"
copy {
from "${externalLibsDir}/core2.jar"
into "${deployDirAlpha}/lib"
}
println "Deploying test resource files to : ${deployDirAlpha}"
copy {
from "./test-resources/logback-test.xml", "./test-resources/JUnit-TestSuiteResults.xsl"
into "${deployDirAlpha}"
}
}
}
I have similar snippets at few places. Its not looking nice.
Is there any way we can reuse methods/functions in gradle? or I am assuming wrong things here.. Or I am trying to use gradle for things its not inteded for? What could be the best way to accomplish these tasks of copying and backing up files if not using custom tasks in gradle?
Here's a couple of options.
Create a plugin (See writing custom plugins)
public class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.with {
apply plugin: 'x'
dependencies {...}
task deployAlpha{...}
}
}
}
Usage
apply plugin: MyPlugin
Or a script plugin
apply from: 'path/to/script.gradle'
You can also attach functions to domain objects via the ext of a domain object (see ExtraPropertiesExtension)
allprojects {
ext.doProjectStuff = { String arg -> return "project${arg}"}
dependencies.ext.doSependenciesStuff = { String arg -> return "dependencies${arg}"}
}
Usage
def foo = doProjectStuff('x')
dependencies {
def bar = doDependenciesStuff('y')
}
I have a gradle project that has an xslt file in resources:
src/main/resources/xslt.sec/sec_report.xslt
At time of build w/ gradle I'd like to use that file to overwrite:
src/test/resources/sec_report.xslt
That way my unit tests are always consuming the latest version/there is one source of truth for this file. What is the right way to make this happen? Write a shell script and execute it from gradle or maybe add it to the build task?
You can add your file to your test source set in your build.gradle:
sourceSets {
test {
resources {
srcDir 'src/test/resources'
include 'src/main/resources/xslt.sec/sec_report.xslt'
}
}
}
I am using Gradle build in my java application. My project has the elasticsearch intergation test. Following is my gradle.build
jar {
baseName = 'myproject'
version = 'V.4.0.0'
manifest {
attributes 'Main-Class': 'com.myapp.Application'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
test {
systemProperties = System.properties
systemProperty 'tests.security.manager', 'false'
}
When i give gradle build it executed the test and created the myproject-V.4.0.0.jar. but when i run the
java -cp myproject-V.4.0.0.jar;junit-4.11.jar junit.textui.TestRunner com.myapp.test.testclassname
i got class not found exception for com.myapplication.test.testclassname.
I extracted the myproject-V.4.0.0.jar and can not find the test class.
My question is, How can i include the test class also in my application jar?
This is a deliberate behaviour of gradle java projects. A jar is your production artifact, so usually you want to test it during the build, but you do not want to run your tests in production, so I do not recommend doing it. Having said that, there is a way of doing it in gradle, like this:
task myJar(type:Jar) {
from {sourceSets.main.output + sourceSets.test.output}
}