Spring Boot Gradle quickbuild that skips the non-essentials - java

Java 8 and Gradle 4.6 here. I have a Spring Boot app with the following build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.8.RELEASE")
}
}
plugins {
id 'java-library'
id 'checkstyle'
id 'jacoco'
}
apply plugin: 'org.springframework.boot'
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
configurations {
dev
}
dependencies {
compile(
,'ch.qos.logback:logback-classic:1.2.3'
,'org.slf4j:jul-to-slf4j:1.7.25'
,'org.apache.logging.log4j:log4j-to-slf4j:2.9.1'
,'org.apache.commons:commons-lang3:3.7'
,'org.springframework.boot:spring-boot-starter-actuator'
,'org.apache.commons:commons-text:1.2'
,'commons-beanutils:commons-beanutils-core:1.8.3'
)
testCompile(
'junit:junit:4.12'
,'org.mockito:mockito-core:2.23.0'
)
dev('org.springframework.boot:spring-boot-devtools')
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
String buildName = 'myapp'
jar {
baseName = buildName
}
bootRun {
if(project.hasProperty('debugMode')) {
jvmArgs = [ "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" ]
}
classpath = sourceSets.main.runtimeClasspath + configurations.dev
}
checkstyle {
toolVersion = '8.12'
ignoreFailures = false
}
jacocoTestReport {
reports {
xml.enabled false
html.enabled true
html.destination file("${buildDir}/reports/jacoco/")
}
}
check.dependsOn jacocoTestCoverageVerification
jacocoTestCoverageVerification.dependsOn jacocoTestReport
So this is a Spring Boot Java app that also uses the Checkstyle and Jacoco Gradle plugins.
I consider a "full build" to be an invocation that:
Compiles
Runs Checkstyle
Runs unit tests (JUnit)
Runs Jacoco for code coverage analysis
Uses Spring Boot's libraries to build a "fat" (self-contained) executable jar
Given my current Gradle build file, I run a full build like so:
./gradlew clean build
However this can take several minutes to run through all the unit tests and has become cumbersome. I would like to introduce a
"quick build" option that only compiles the code and creates the Spring Boot fat jar for me. This will help speed up development
time tremendously.
I'm hoping to invoke the quick build like so:
./gradlew clean quickbuild
So far I've got this:
tasks.register("quickbuild") {
doLast {
// ???
}
}
But not sure how to link the compilation and fatjar tasks to it (and more importantly; skipping all the other stuff that I don't want!). Any ideas as to what I'm missing?
Update
The bootJar task doesn't seem to exist or be configured (please check my build.gradle file provided above!):
$ ./gradlew clean bootJar
FAILURE: Build failed with an exception.
* What went wrong:
Task 'bootJar' not found in root project 'myapp'. Some candidates are: 'bootRun'.
* Try:
Run gradlew tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 0s
When I try to run bootRun:
$ ./gradlew clean bootRun
It tries to actually run my app! That's not what I want! I just want to compile and build the fat jar!

See documentation from the Java plugin here : https://docs.gradle.org/current/userguide/java_plugin.html#lifecycle_tasks
You could create a new task (quickbuild) and make it depend on the desired task (in your case it could be the assemble lifecycle task, I guess, or maybe bootJar task (for SpringBoot v2.x) or bootRepackage (for SpringBoot v1.5.x) )
tasks.register('quickbuild'){
dependsOn assemble
}
But if the only purpose of quickbuild task is to trigger the creation of the Jar, the simpliest solution is to execute assemble directly
./gradlew clean assemble

Related

Gradle task --help printed to console instead of my application execution

This is my build.gradle file:
plugins {
id 'org.springframework.boot' version '2.1.11.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example.ProjectJar'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
jar {
from {
(configurations.runtime).collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes("Main-Class": "com.example.ProjectJar.ProjectJar.FileSend" )
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compile 'io.minio:minio:6.0.11'
}
But instead of execution of my main class that does have a main function, I get the following output:
Task :help
Welcome to Gradle 5.6.4.
To run a build, run gradle ...
To see a list of available tasks, run gradle tasks
To see a list of command-line options, run gradle --help
To see more detail about a task, run gradle help --task
For troubleshooting, visit https://help.gradle.org
BUILD SUCCESSFUL in 43ms
What should I do to have my main class execute instead of this?
Try these :
gradle clean build
This command creates the spring-boot jar file to the build/libs directory or the target directory.
we can start our application by running the following command at the command prompt:
java -jar spring-boot-web-application.jar
Another way
./gradlew bootJar
This command creates the spring-boot jar file
To run the application is by executing the following Gradle command:
./gradlew bootRun

Launch TestNG debug with JVM args from build.gradle

I have a Gradle project where the tests run using TestNG. (I use Intellij IDEA)
I need an aspectjweaver to be launched each time on tests execution. The aspectjweaver is defined as JVM argument and added to applicationDefaultJvmArgs in Build.gradle:
version '1.0'
apply plugin: 'application'
def aspectjVersion = "1.8.7"
mainClassName = 'exa.tags.runner.TestManager'
applicationDefaultJvmArgs=["-javaagent:APP_HOME_PLACEHOLDER/lib/aspectjweaver-${aspectjVersion}.jar"]
dependencies {
compile "org.aspectj:aspectjweaver:${aspectjVersion}"
}
def weaver = configurations.compile.find { it.name.contains("aspectjweaver") }
startScripts << {
unixScript.text = unixScript.text.replace('APP_HOME_PLACEHOLDER', '\$APP_HOME')
windowsScript.text = windowsScript.text.replace('APP_HOME_PLACEHOLDER', '%APP_HOME%')
}
run {
doFirst {
jvmArgs = jvmArgs.grep {
!it.contains('APP_HOME_PLACEHOLDER')
}
jvmArgs = jvmArgs << "-javaagent:$weaver"
}
}
So when I launch tests using this run task, everything works fine for me.
But the problem is that when I right click on a test and select TestNG Run or Debug, the aspectj is not launched.
When I used maven, the aspectjweaver was added as an argLine to the maven-surefire-plugin and worked each time (debug, run single test or execute mvn test goal).
So, what is the proper way and place to set the JVM argument to the actual version of AspectJ? I tried to add the path to aspecj.jar as default arg in Edit configurations. That worked, but in such a case I depend on a specific cached file.
Can this be done somewhere in project files without changing the IDE configurations?
UPDATE
I tried to add a test task in my build.gradle:
def weaver = configurations.compile.find { it.name.contains("aspectjweaver") }
test {
useTestNG()
testLogging.showStandardStreams = true
println "Adding aspectJ weaver: ${weaver}"
jvmArgs = jvmArgs << "-javaagent:$weaver"
}
And now I see this output on each task execution (e.g. when I run clean task).
But when I right click on test and select Debug
I do not see the output.
Looks like the task 'test' is not executed when I select run one test with TestNG.

Unable to run Gradle app engine tasks

I'm really confused about converting an old Google App Engine project to Gradle.
I'm trying to follow the instructions on this page. It advises to start with this build script:
buildscript { // Configuration for building
repositories {
jcenter() // Bintray's repository - a fast Maven Central mirror & more
mavenCentral()
}
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:+' // latest App Engine Gradle tasks
}
}
repositories { // repositories for Jar's you access in your code
maven {
url 'https://maven-central.storage.googleapis.com' // Google's mirror of Maven Central
// url 'https://oss.sonatype.org/content/repositories/snapshots' // SNAPSHOT Repository (if needed)
}
jcenter()
mavenCentral()
}
apply plugin: 'java' // standard Java tasks
apply plugin: 'war' // standard Web Archive plugin
apply plugin: 'com.google.cloud.tools.appengine' // App Engine tasks
dependencies {
providedCompile group: 'javax.servlet', name: 'servlet-api', version:'2.5'
compile 'com.google.appengine:appengine:+'
// Add your dependencies here.
}
appengine { // App Engine tasks configuration
run { // local (dev_appserver) configuration (standard environments only)
port = 8080 // default
}
deploy { // deploy configuration
stopPreviousVersion = true // default - stop the current version
promote = true // default - & make this the current version
}
}
group = 'com.example.appengine' // Generated output GroupId
version = '1.0-SNAPSHOT' // Version in generated output
sourceCompatibility = 1.7 // App Engine Standard uses Java 7
targetCompatibility = 1.7 // App Engine Standard uses Java 7
However it doesn't work:
$ gradle appengineRun
FAILURE: Build failed with an exception.
* Where:
Build file '/path/to/myproject/build.gradle' line: 32
* What went wrong:
A problem occurred evaluating root project 'myproject'.
> Could not find method run() for arguments [build_c1i62diotjttavcmtjg1zqlbd$_run_closure3$_closure5#33f17289] on root project 'myproject' of type org.gradle.api.Project.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Shouldn't the dependencies be downloaded to make the custom appengine task configuration work?
Please have a look at the sources of the plugin. When the core plugin is applied it decides whether to apply a flexible or standard appengine plugin. Since there's probably no src/main/webapp/WEB-INF/appengine-web.xml flexible plugin is applied which does not create the extension that fails (FYI, this extension is created here). To fix the problem run:
mkdir -p src/main/webapp/WEB-INF
and then:
touch src/main/webapp/WEB-INF/appengine-web.xml
in console where build.gradle is located. This will solve the problem. Poor documentation :/

Task 'jacoocoTestReport' not found in root project

I'm trying to find out the line coverage of the JUnit tests in my java program by using gradle and jacoco but the following command causes a failure.
gradle test jacoocoTestReport
The command prints:
FAILURE: Build failed with an exception.
* What went wrong:
Task 'jacoocoTestReport' not found in root project 'ProjectName'. Some candidates are: 'jacocoTestReport'.
* Try:
Run gradle tasks to get a list of available tasks. Run with
--stacktrace option to get the stack trace. Run with
--info
or
--debug
option to get more log output.
BUILD FAILED
Total time: 3.389 secs
The build.gradle of my gradle project:
apply plugin: "jacoco"
apply plugin: 'java'
apply plugin: 'application'
repositories {
jcenter()
}
dependencies {
compile 'com.google.guava:guava:20.0'
testCompile 'junit:junit:4.12'
}
mainClassName = 'example.Main'
run {
standardInput = System.in
}
jacocoTestReport {
reports {
xml.enabled = true
html.enabled = true
}
}
You have a typo: use
jacocoTestReport
instead of
jacoocoTestReport
(two o's).
Use
gradle tasks
to check what tasks are defined.
You've run an invalid task (double o):
gradle test jacoocoTestReport
instead of:
gradle test jacocoTestReport

Running jacocoReport

I'm using Gradle 1.7 and Jacoco plugin. My project uses Java and Scala plugins.
When I run gradlew -i clean jacocoTestReport
Report is not created and I see in the log
:bl:jacocoTestReport (Thread[Daemon Thread 13,5,main] - start
:bl:jacocoTestReport
Skipping task ':bl:jacocoTestReport' as task onlyIf is false.
:bl:jacocoTestReport SKIPPED
:bl:jacocoTestReport (Thread[Daemon Thread 13,5,main]) - complete
What does it mean? Why report is not created?
The task will only run if coverage data is available. You can make sure of that by also running the test task.
Add the following at a top level to your build.gradle:
test {
finalizedBy jacocoTestReport
}
This means that at the end of the test task the jacocoTestReport task should be run.
You will receive your coverage analysis after run the tests.
None of the above worked for me. What worked for me was the following
Add to the top of my build.gradle:
apply plugin: 'jacoco' // code coverage reports
Add the following as a 'task':
// Generate code coverage reports ... run with jacoco
jacocoTestReport{
additionalSourceDirs = files(sourceSets.main.allJava.srcDirs)
reports {
xml.enabled false
csv.enabled false
html.destination "${buildDir}/reports/jacoco/html"
}
executionData = files('build/jacoco/test.exec')
}
Add the following to your gradle test task:
finalizedBy jacocoTestReport
Then I issued the following command:
gradle run test jacoco
For me the issue was that the executionData.setFrom(executionSource) file path was wrong.
For Spring 2.5 Users, who got stuck with it for hours -just like myself.
I was not having the exec file generated.
And because of that ,
I found that the jacocoTestReport was simply "skipped".
I got it fixed by adding :
apply plugin: 'jacoco'
test {
useJUnitPlatform()
finalizedBy jacocoTestReport // report is always generated after tests run
}
jacocoTestReport {
...
...
...
...
}
That's because I'm using Junit5 with spring boot 2.X
And as of today Junit5 is not by default in the test task,
Hope this helps.

Categories

Resources