Debugging simple Gradle Java App in Intellij - debugging

I'm trying to debug a simple gradle Java app in IntelliJ and I'm having the hardest time. I can run my tasks from the JetGradle plugin just fine, but when I right click the task and try to debug it, I get a message in the console that says it's connected, and then it says the equivalent disconnected:
Disconnected from the target VM, address: '127.0.0.1:59303', transport: 'socket'
Not really sure how to proceed from here. I've tried looking online etc and haven't really found much except people talking about how JetGradle plugin isn't very good.
Here is my build.gradle if it matters.
apply plugin: 'java'
apply plugin: 'idea'
task(parse, dependsOn: 'classes', type: JavaExec) {
main = 'com.test.creator.Main'
classpath = sourceSets.main.runtimeClasspath
}
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
compile 'org.xerial:sqlite-jdbc:3.7.2'
compile 'net.sourceforge.jexcelapi:jxl:2.6.12'
}
Any help or direction would be appreciated.
A few additional things to note:
I'm using the gradle Daemon as it dramatically decreased my build time with certain projects, so I'd prefer to keep that on.
I'm using the Gradle Wrapper.
I'm running IntelliJ 12.1.6

I'm not sure if right-clicking the Gradle task and hitting Debug is the right solution (you might be debugging Gradle here, rather than your application). The easiest solution is to just run/debug the com.test.creator.Main class directly (from IntelliJ).
PS: Gradle support is much better in IntelliJ 13 (EAP).

Related

How to run remote debug on local kotlinc

I want to compile some sample kotlin project using local compiler. I clone jetbrains/kotlin project from githib and build it. And now i have local compiler in /dist folder. How i need to configure gradle in sample project to use this local compiler in it and have an ability for remote debugging?
The simplest way is to build the whole toolchain and use it in your test projects.
To do that, run the install Gradle task in the Kotlin project:
./gradlew install
This will publish all of the project's Maven modules to the Maven local repository (~/.m2/repository by default) with the default snapshot version, which is 1.3-SNAPSHOT at the moment.
Then, in your test Gradle project:
If you apply the Gradle plugin using a buildscript block and an apply statement, add the mavenLocal() repository to buildscript { repositories { ... } } and use the snapshot version of the Gradle plugin:
buildscript {
repositories {
mavenLocal()
jcenter()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3-SNAPSHOT")
}
}
If the plugins are applied using the plugins { ... } block, modify the settings.gradle script and add the following:
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
and again, use the 1.3-SNAPSHOT version of the Gradle plugin:
plugins {
id("org.jetbrains.kotlin.jvm").version("1.3-SNAPSHOT")
}
In order to be able to debug the compiler, you need to run its process with a debugging agent waiting for a connection. Normally, the compiler is run in a daemon process that is harder to connect to. It's much simpler to run the compiler inside the Gradle process. To do that, you need to set a system property kotlin.compiler.execution.strategy to in-process in the Gradle process (note: this should be not a Gradle project property but a Java system property which can be passed by -Dkey=value or set using System.setProperty(...).
Then run a Gradle build with a command line -Dorg.gradle.debug=true to make Gradle wait for a remote debugger. I would advise for running the test project build from the terminal, not the IDE.
This will look like:
./gradlew compileKotlin -Dorg.gradle.debug=true -Dkotlin.compiler.execution.strategy=in-process
Starting a Gradle Daemon, 1 busy Daemon could not be reused, use --status for details
> Starting Daemon
(at this point, the build seems to hang, but it just waits for the debugger, so proceed below)
In the IDE where you work with the Kotlin project, put some breakpoints in the compiler code and attach the remote debugger to the Gradle process.
Note that, with the Kotlin compiler running inside the Gradle process, the latter may run out of memory sooner. Make sure the Gradle process gets enough heap space.

Spring Boot + Spring-Loaded (IntelliJ, Gradle)

I'd like to use hot swap with my Spring Boot project. Somehow I am not able to make it working by running it in my IDE (IntelliJ), despite of having this topic covered by documentation. I simply run the class with my main method with VM attributes:
-javaagent:/path/to/jar/springloaded.jar -noverify
My question is, how do I make it work? :-)
Further question is how to use spring loaded with Gradle and IntelliJ. I find it quite inconvenient to force the developer to download the JAR manually, place it somewhere and point to it with a JVM parameter. Is there any better way (should I configure my own task which does the job and run it from my IDE as a Gradle task)?
You need to configure the project as stated in the documentation:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-reload-springloaded-gradle-and-intellij-idea
After that, you must configure your IDE to output the compiled classes in build/classes/main (with Idea plugin, you can configure the outputDir as specified in the above link, and then invoke gradle idea to have it done).
Then, if you launch the task (run / bootRun) or run the main class from the IDE's using the debug mode, hot code reloading should work when a class is compiled.
The gotcha here is that IntelliJ, unlike Eclipse, doesn't automatically compile a class when it is saved (even if you configure the compiler to "Build on save", it won't do it when is Running/Debugging). This is apparently a design decission made by IntelliJ - as stated here Intellij IDEA Java classes not auto compiling on save (CrazyCoder answer) .
It would be ideal if spring boot provided a configuration option to monitor your source code files and recompile them when they change - that is what Grails does. But I think such a think does not exist yet, and maybe is not even possible to combine that with gradle, which is the responsible of managing the classpath and that kind of things.
So there are two options as far as I can tell:
You remember to compile everything you edit (adding an easier Compile shortcut as suggested in the previous StackOverflow link might help).
You put some filesystem monitor (inotify-tools for Linux, launchd for Mac OS X are examples) that invokes gradle compileJava/compileGroovy when a change is detected in any source code file.
First is tedious, second is slow :) . Actually there's another option: you change your IDE :-D (or install the EclipseMode IntelliJ plugin).
If one wants to be able to run the application solely from IntelliJ (using Right Click -> Debug on the main method) and not involve Spring Boot's Gradle tasks at all, you simply need to do the following:
Configure the run configuration in IntelliJ to use the SpringLoaded agent. This is easy to do and an example is shown in the following screenshot:
Notice how I have added a VM Option: -javaagent:/path/to/springloaded-${version}.jar -noverify (which you can download here)
Debug using Right Click -> Debug like the following screenshot:
Everytime you make a change and want to reload it, just compile the project. The default shortcut is Cntrl+F9, but you can also access it from the menu Build -> Make Project
I managed to do this with IDEA in a Maven project, it should work with the Gradle version as well I guess, my procedure was the following.
Settings -> Compiler -> Make project automatically (only works while not running/debugging !)
Start the project with the sprint-boot-plugin outside of the IDE (a trick because of the above sentence).
The Maven plugins setup looks like the following:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Now change some code and reload the page.
I'm running SpringBoot and Gradle in IntelliJ Idea. Auto-reloading is working 100%
Static Content is autoreloading (instantly)
Thymeleaf is autoreloading (instantly)
Controllers / Java Files require me to hit the "build" button (takes a few seconds), but does not require a restart - it's just to compile the files, so Spring Loaded can pick them up.
Step 1: Get SpringLoaded going
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:1.2.1.RELEASE"
classpath 'org.springframework:springloaded:1.2.1.RELEASE'
}
}
apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'idea'
apply plugin: 'spring-boot'
repositories {
jcenter()
mavenLocal()
mavenCentral()
}
mainClassName = 'com.noxgroup.nitro.NitroApp'
idea {
module {
inheritOutputDirs = false
outputDir = file("$buildDir/classes/main/")
}
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE")
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
}
jar {
baseName = 'org.noxgroup-nitro'
version = '0.1.0'
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
Step 2: Create an Application.properties
And add the following:
spring.thymeleaf.cache=false
Step 3: Run the bootRun task
(Not just the standard run task - this adds SpringLoaded functionality)
Step 4: Compile your Java
Make your Java files by hitting "Make Project" or pressing "Ctrl/Command + F9
In later versions of gradle you can start a command window and run
gradle -t classes
This will start a process that look for changes to source code and recompile them.
In another run.
gradle bootRun
Any changes to java or groovy src will automatically be recomplied. While not intellij specific, your good to go with intellij. You could even make do with you favorite text editor (e.g. submlime, atom ).
credits/link

How to use JMH with gradle?

I want to use JMH, an OpenJDK microbenchmark tool, with gradle. However, Im getting the NPE on compilation. On the other hand, JMH works when using from maven.
I am not posting any build.gradle as it is basic - apply java plugin and add dependency on JHM tool (org.openjdk.jmh:jmh-core:0.2).
I have tried whats written here without success.
What else I have to do? I think something with setting the agent, but I still didnt figure it out.
Exception:
:compileJava
java.lang.NullPointerException
at org.openjdk.jmh.processor.internal.GenerateMicroBenchmarkProcessor.validMethodSignature(GenerateMicroBenchmarkProcessor.java:502)
Just finished my "masterpiece". No uber-jars, no plugins, code base separated from main & test, benchmarks compilation hooked to main, but does not run automatically in the mainstream lifecycle. Simple, explicit, and hackable, vanilla gradle.
I run it directly from IntelliJ, to run on a box you probably will need the uber-jar back :-)
Before doing it I have spent a fair amount of time trying to get that plugin work, but it's way too clunky for my taste.
Step-by-step breakdown below.
Define a new sourceSet called jmh with classpath hooked to that of the main sourceSet
sourceSets {
jmh {
java.srcDirs = ['src/jmh/java']
scala.srcDirs = ['src/jmh/scala']
resources.srcDirs = ['src/jmh/resources']
compileClasspath += sourceSets.main.runtimeClasspath
}
}
Define dependencies for it (at minimum JMH and its annotation processor).
dependencies {
...
jmhImplementation 'org.openjdk.jmh:jmh-core:1.35'
jmhImplementation 'org.openjdk.jmh:jmh-generator-annprocess:1.35'
}
Define a task jmh of type JavaExec
task jmh(type: JavaExec, dependsOn: jmhClasses) {
main = 'org.openjdk.jmh.Main'
classpath = sourceSets.jmh.compileClasspath + sourceSets.jmh.runtimeClasspath
}
Hook jmhClasses task to run after classes to make sure benchmarks are compiled with the rest of the code
classes.finalizedBy(jmhClasses)
Currently you can just use dedicated plugin jmh-gradle-plugin
It requires minimal configuration and allows you to run JMH benchmarks as well as build benchmarks artifact
My bad, I was trying to benchmark a method that has an argument - of course JMH will not know what to pass :) Once when I created a void method with no arguments, everything worked.
My build.gradle:
defaultTasks 'build'
apply plugin: 'java'
apply plugin: 'shadow'
buildscript {
repositories {
mavenCentral()
maven {
name 'Shadow'
url 'http://dl.bintray.com/content/johnrengelman/gradle-plugins'
}
}
dependencies {
classpath 'org.gradle.plugins:shadow:0.7.4'
}
}
jar {
manifest {
attributes 'Main-Class': 'org.openjdk.jmh.Main'
}
}
repositories {
mavenCentral()
}
build.doLast {
tasks.shadow.execute()
}
shadow {
outputFile = new File('build/libs/microbenchmarks.jar')
}
ext {
lib = [
... other dependencies...
jmh: 'org.openjdk.jmh:jmh-core:0.2'
]
}
dependencies {
compile lib... other dependencies...
compile lib.jmh
}
sourceCompatibility = 1.7
Build tests and jar:
gw clean build
and then run them with:
java -jar build/libs/microbenchmarks.jar ".*" -wi 2 -i 10 -f 2 -t 16
UPDATE
From recent versions of JMH, you would also need to add dependency to:
org.openjdk.jmh:jmh-generator-annprocess:0.5.4
and you can use shadow 0.8.
I made a very small example project to clone and modify as you like. It's a full working example:
https://gitlab.com/barfuin/jmh-gradle-example
It requires no shadow Jars and no plugins, while still running the benchmark in a dedicated JVM. The project also includes some extra Gradle tasks for printing the classpath, the JMH options, etc., stuff that may help to understand what's going on.
If you're an IntelliJ user, perhaps the easiest way to make it work, without all that workarounds, is to use the IDE plugin:
https://github.com/artyushov/idea-jmh-plugin
Add the dependencies
Create your benchmark
be happy :)

Debug Gradle plugins with IntelliJ

Problem
I want to use the interactive debugger with IntelliJ. Unfortunately, I can't convince IntelliJ to load and compile the plugin. However, I can do gradle clean build and the plugin builds and runs its tests as expected.
Specifically, I'm trying to debug local changes to gradle-js-plugin and IntelliJ says it can't find com.google.javascript.jscomp.CompilerOptions as well as spock.lang.Specification. (I'm thinking maybe it's something about the way they are loaded, but that's a guess.)
Things I've tried
NOTE: I didn't revert any processes between steps.
0. My First Guess
I noticed a howto on docs.codehaus.org. IntelliJ couldn't find org.gradle.launcher.GradleMain, so I've adapted it to use GradleLauncher with the following:
import org.gradle.GradleLauncher
class GradleScriptRunner {
public static void main(String[] args) {
GradleLauncher.newInstance(
"-p",
"/path/to/gradle-js-plugin/src/test/resources/build.gradle",
"clean assemble"
)
}
}
Per GradleLauncher's documentation.
Outcome: IntelliJ won't compile the project.
1. Per Peter Niederwieser's answer Fix idea project & debug via plugin
Steps
~# cd /path/to/gradle-js-plugin && gradle cleanIdea idea
Opened the newly created project and attempted to debug using the ScriptRunner from step 0.
Outcome: Project compiles (yay!), but I can only hit breakpoints in GradleScriptRunner.groovy.
2. Per Peter Niederwieser's answer run gradle CLI w/ special options
1 & 2. Merged for clarity:
~# export GRADLE_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
~# gradle clean assemble
Listening for transport dt_socket at address: 5005
Configure IntelliJ to connect to this port and start debugging (see image):
For this step I tried the following .gradle file configurations:
1. Use only build.gradle
--build.gradle--
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'maven'
apply plugin: 'js'
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile findProject "/path/to/gradle-js-plugin"
}
}
repositories {
mavenLocal()
mavenCentral()
}
Outcome:
FAILURE: Build failed with an exception.
* Where:
Build file '/path/to/gradle-js-plugin/src/test/resources/build.gradle' line: 13
* What went wrong:
A problem occurred evaluating root project 'resources'.
> No such property: findProject for class: org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 8 mins 50.498 secs
2. Use both build.gradle and settings.gradle
--settings.gradle--
include "/path/to/gradle-js-plugin"
--build.gradle--
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'maven'
apply plugin: 'js'
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
}
repositories {
mavenLocal()
mavenCentral()
}
Outcome:
FAILURE: Build failed with an exception.
* Where:
Build file '/path/to/gradle-js-plugin/src/test/resources/build.gradle' line: 5
* What went wrong:
A problem occurred evaluating root project 'resources'.
> Plugin with id 'js' not found.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 13.553 secs
My Setup
Gradle
~# gradle -v
------------------------------------------------------------
Gradle 1.0
------------------------------------------------------------
Gradle build time: Tuesday, June 12, 2012 12:56:21 AM UTC
Groovy: 1.8.6
Ant: Apache Ant(TM) version 1.8.2 compiled on December 20 2010
Ivy: 2.2.0
JVM: 1.7.0_04 (Oracle Corporation 23.0-b21)
OS: Linux 3.2.0-2-amd64 amd64
Java
~# java -version
java version "1.7.0_04"
Java(TM) SE Runtime Environment (build 1.7.0_04-b20)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)
IntelliJ
IntelliJ IDEA Ultimate 117.499 w/ Bundled Gradle plugin
Hoping for
Any tips that'll get me into debug mode within the plugin.
I was able to debug gradle sources (including plugins) using -Dorg.gradle.debug=true (found on gradle forum):
Stop daemons if any:
./gradlew --stop
Run
./gradlew <task> --no-daemon -Dorg.gradle.debug=true
Connect remotely to gradle process (port 5005) - if using IntelliJ IDEA, see OP's image above
It should stop on breakpoints now.
BTW, I have created a separate IntelliJ IDEA project for gradle sources. Since I use gradle wrapper, I have grabbed the sources from
~/.gradle/wrapper/dists/gradle-1.11-all/7qd8qq8te5j4f5q9aaei3gh3lj/gradle-1.11/src
In IDEA I did File->Import Project, then selected the above path, then - "Create project from existing sources". Hit Next couple of times (made sure I didn't include any jars from lib/plugins directory, since IDEA would complain that most project files already exist).
I then created a remote debug configuration in that IDEA project and used it for debugging gradle.
First, it sounds like there is a problem with your IDEA Gradle project. If you run gradlew cleanIdea idea and then open the generated project from IDEA (rather than using the JetGradle plugin), all should be fine.
Second, if you still can't get the GradleMain/GradleLauncher (the former class does exist) approach to work, another approach is to debug the Gradle build as an external application. For that you need to add -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 to the GRADLE_OPTS environment variable, run the build from the command line, wait until it suspends, and then start a "Remote" run configuration (with corresponding settings) from IDEA. At that point the debugger should connect to the Gradle process and you should be up and running.
IntelliJ IDEA 12.1 provides ability to debug gradle tasks out of the box - right-click target task at the JetGradle tool window tasks list and choose 'debug'

how to tell gradle to download all the source jars

Ideally, we would like to add a task for downloading all the source jars for the first level and transitive dependencies of our project. Is there a way to do that?
If not, is there a command line option to supply like maven has to get all the sources downloaded onto our machines?
It seems like that should just be the default these days at least for first level dependencies as it gives you the javadoc in eclipse then which is very nice when doing the code completion stuff.
The eclipse task can be configured with downloadSources. Following is an example of that configuration
apply plugin: 'java'
apply plugin: 'eclipse'
eclipse {
classpath {
downloadSources=true
}
}
So run
gradle cleanEclipse eclipse
to have it download sources.
If you use Eclipse and want to navigate the source code of your dependencies there, then the Eclipse plugin does this for you.
Install the eclipse plugin by adding apply plugin: "eclipse" to your build.gradle file. Then run gradle eclipse to generate the Eclipse .project, .classpath and .settings files. The plugin will download all available sources automatically and add references them in the .classpath file (see the sourcepath attribute of the classpathentry element).
To import the project into Eclipse, choose File > Import... > Existing Projects into Workspace and select your project.
(I'm not sure whether the Idea plugin does the same for Idea users, but it may do).
Another catch not mentioned in other answers is when you are using mavenLocal() repository in your gradle.build file. If there are downloaded jar in that local maven repo but no downloaded sources or javadocs in that repo, then gradle will not even try to download javadocs or sources for you. Even with enabled eclipse.classpath.downloadJavadoc and eclipse.classpath.downloadSources.
The solution is to remove mavenLocal() from repositories or place it to bottom of the list. Or you can setup maven to download sources and javadocs and clean your maven local repository (~/.m2/repository).
A more detailed description of the problem is here.
Here is how to add the required configuration in Gradle using the IDEs' plugins:
For Eclipse:
apply plugin: 'java'
apply plugin: 'eclipse'
eclipse {
classpath {
downloadJavadoc = true
downloadSources = true
}
}
For IntelliJ
apply plugin: 'java'
apply plugin: 'idea'
idea {
module {
downloadJavadoc = true
downloadSources = true
}
}
To run these plugins:
gradle cleanEclipse eclipse
gradle cleanIdea idea
Piohen's comment above should be it's own answer (since it was the only solution that worked for me)
Right click your project, then select "Build Path" --> "Configure Build Path";
Select "Order and export"
Select "Web App Libraries", and click "Bottom" button, then the "Web App Libraries" will be on the bottom;
And to get this into the Gradle Eclipse plugin (so you don't need to do it manually every time):
Why is Eclipse not attaching 3rd party libs source files to a WTP-faceted Gradle project?
There is only one problem here. This only works if you are generating NEW projects. If you are working on mature projects that can't be re-generated using Gradle, the above suggestions will not work.
One thing I should add is that the version of Gradle/Builsdhip plugin strongly depends on the version of Java you use to start Eclipse. They must all be compatible. I had to switch my Eclipse (current version) from Java 11 back to Java 8 to fix Buildship (3.0.1) errors. We are, and have been, stuck on Gradle 4.2.1 for some time due to API changes in Gradle breaking our build. So to move to Java 11 we have to move to a new version of Gradle, Buildship, and Eclipse. Ugh! Oh yeah, this also fixed the issue mentioned in this thread. Source is now avalable again.

Resources