I am writing a console application with Java and gradle. I am using the application plugin and have the required fields correctly configured in build.gradle.
In my main class I have BufferedReader linked with System.in. Here's the problem: When I run gradle run in project directory, the reader does not wait for my console input. BufferedReader#readLine instead returns null on the very first call. This behavior is not desirable for what am I doing.
What is the solution? Is there a separate console application plugin for gradle or do I need to tweak application plugin somehow to suit my needs?
By default, the system.in of your Gradle build is not wired up with the system.in of the run (JavaExec) task. You can do the following:
build.gradle (Groovy syntax):
run {
standardInput = System.in
}
build.gradle.kts (Kotlin DSL syntax):
tasks.named<JavaExec>("run") {
standardInput = System.`in`
}
As stated above, add
run {
standardInput = System.in
}
And run:
gradle console:run -q --console=plain
where:
-q runs task in "quiet" mode (to avoid having > Building > :run)
--console=plain drops execution status: <=-> 80% EXECUTING [TIME]
Source: https://docs.gradle.org/current/userguide/gradle_command_line.html
For build.gradle.kts:
tasks.getByName<JavaExec>("run") {
standardInput = System.`in`
}
Chances are, the problem lies in your java code. All the application plugin does is compile the java code, and run the main class that you specify. Can you post the code in your main class that you specified for the application plugin (mainClassName) ?
Related
I'm currently building a Android application, and I would like to do some processing after the apk is built.
I've already succeeded to launch a gradle task after the build:
tasks.whenTaskAdded {
task ->
if(task.name == 'assembleRelease'){
task.finalizedBy postApkProcess
}
}
task postApkProcess{
doLast {
println 'OK'
}
}
But I struggle to launch a method inside that task. What I would like to do is to call something like new MyClass().postBuild() inside the class (or if it is not possible, run the main method of a Java class), but I don't find a way to do it.
I've tried to build a task task postProcess(type: JavaExec), but the line apply plugin: 'java'conflicts with the Android plugin.
Is there a way to do it ?
You could use commandLine to run the main method in MyClass which could call postBuild:
commandLine 'java' '<pathToSrc>/<mypackage>.MyClass'
Be careful to set the package name and source location properly. The path should point to the location (minus package directory tree) of the MyClass.class file, not MyClass.java. If your class is not compiled or it changes often, you could call javac to compile it each time before you run it (optionally using a shell script / batch file) to bundle both commands and simplify the gradle call and help you test the setup directly.
If your class uses code from libraries ensure you add them to the classpath:
'-classpath' 'mylib1.jar:mylib2.jar'
If you use java in the build process you might also have a look at scar
I have this simple Java program:
package me.fornever.javaterminal;
public class Main {
public static void main(String[] args) {
System.out.println("Console: " + System.console());
}
}
And this simple build.gradle:
apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'me.fornever.javaterminal.Main'
When I'm executing it using gradle --no-daemon run, I get the following output:
Console: null
If I execute it from the terminal through gradle jar; java -cp '.\build\libs\java-terminal.jar' me.fornever.javaterminal.Main, I get the following:
Console: java.io.Console#3d4eac69
I am aware that System.console() may return null when the parent process uses stdout redirection. Is there some Gradle option to disable the redirection and make the console fully available for my program?
I am developing a terminal library for Java, so I want to run my tests and executables without Gradle intervention in stdin/stdout/stderr.
Please note that System.console() being null is not the only issue but the most obvious one. In reality I want to access WinAPI WriteConsoleW function from the program executed by gradle run, and I'm unable to use this function due to the same reasons System.console() being null. So I really need to disable output redirection in Gradle if this option is available.
Also please note that the question is different from Gradle build null console object because that question asks how to use System.console() inside of a Gradle script and not in the Java program invoked by gradle run; I believe they're working differently in that matter, because neither of the answers are working or applicable to my case.
In order for java.io.Console to be available, the child processes' stdin and stdout have to point to a Linux/macOS/Unix terminal or a Windows console. The easiest way to arrange that is to inherit the stdin and stdout from a parent process already set up that way. However, there is a known limitation of Gradle (GRADLE-3292) that the JavaExec task type does not support making the child process inherit the input/output streams of the parent process.
If the Gradle JavaExec task type was enhanced to support stdin/stdout inheritance, then this could be made to work for gradle --no-daemon run.
Getting it to work with the Gradle daemon would be far more complex, and likely involve platform-specific code to manipulate pseudoterminals or call the Windows console API.
I have a Java TestNG project set up with gradle running test suites. Currently, most of the tests are pulling certain parameters out of a constants.properties file. How would I modify these on the command line when running the gradle task? Will gradle -DapplicationKey=0000 replace the line applicationKey=1234 in my constants.properties file?
Edit:
To be a bit more clear about the situation and the question, my constants.properties file contains around 400 to 500 properties that are already defined. I would like to avoid rewriting those properties in gradle completely. I just want to override those properties from the command line when Jenkins runs the same commands as part of that build job.
You want to pass system properties to the JVM used to run tests. Here is a way to configure all tasks of type Test:
tasks.withType(Test) {
systemProperty 'applicationKey', System.getProperty('applicationKey', '1234')
}
or just one task
test {
useTestNG()
systemProperties = [
applicationKey: System.getProperty('applicationKey', '1234')
]
}
You can also copy all system properties from the Gradle environment to the child virtual machine with systemProperties = System.getProperties()
I've installed the Gradle-support plugin in Netbeans and I can build and run the project just fine. When I try to run in debug mode, I get the following output:
Executing: gradle debug
:debug
Cannot execute debug because the property "mainClass" is not defined or empty.
BUILD SUCCESSFUL
Total time: 0.222 secs
I'm using:
Oracle Java 1.8
Gradle 1.12
Netbeans 8.0
Gradle-Support 1.3.0
LinuxMint 16
Why can't I run my debugger?
Add something like
if (!hasProperty('mainClass')) {
ext.mainClass = 'com.foo.acme.Main'
}
to your build.gradle. It will tell Gradle plugin what class to use when starting your application. Perhaps that should be customizable in the UI but I cannot see it now.
Another solution to this problem is to create a new debug task. Similar to the gradle run task you can just add the following task to your build.gradle file:
task debug(dependsOn: classes, type: JavaExec) {
main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = project.assetsDir
ignoreExitValue = true
debug = true
}
In addition to Radim's answer the way to customize the mainClass parameter in the Netbeans UI.
In the properties of a Netbeans gradle project go to "Built-In Tasks/Debug", unclick the "Inherit" and add "-PmainClass=aaa.bbb.ccc" to the arguments.
I guess this should also be done for the run task.
It's the same idea like run/debug single file which already take the selected file as parameter mainClass.
I had a similar problem and was able to fix it setting Options / Miscellaneous / Gradle / Task Execution / Automatic tasks to "NetBeans should not add tasks automatically".
I get into trouble while I try to run my JUnit test through Gradle test task. While I run the test in eclipse directly with Run As -> JUnit test, everything is ok, the test succeeds. But through test task, test always fails. Probably some trouble with the encoding of my resource txt file. So I would like to enable debug while I am launching the test with Gradle
in build.gradle, my test task now looks like:
test {
tasks.withType(Compile) {
options.encoding = 'UTF-8'
}
}
So what should I do to enable debug? I run Gradle tasks from Gradle panel in Eclipse, not from the console. Thanks!
To debug tests the following argument should be used: --debug-jvm
For example: gradle test --debug-jvm
Gradle will suspend execution right before running tests and wait for debugger connection on port 5005.
For executing only specific tests see Simple name pattern
For additional options see Debugging when running tests.
As explained under 23.12. Test in the Gradle User Guide, executing gradle test -Dtest.single=MyTestClass -Dtest.debug will suspend the test JVM upon start, and allows to connect an external debugger (such as the Eclipse debugger) on port 5005.
Putting this here as --debug-jvm did not work for me, I was able to do this by setting:
org.gradle.daemon=true
org.gradle.jvmargs=... -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=10999
in
~/.gradle/gradle.properties
But when I connect with eclipse debugger for the project none of the breakpoints I've set compile/trigger... I am connected via the debugger, I can see action in the Debug view, whenever I run gradle test from command line, like new threads starting/stopping, but can't get breakpoints to trigger, trying to resolve this now...
Fyi to stop deamon run gradle --stop
Other solution
Leaving above as reference, this worked for triggering break points in tests, I turned off deamon as I could not get it to work properly:
Using directions from this article: http://blogs.steeplesoft.com/posts/2013/gradle-tip-attaching-a-debugger.html
test {
if (System.getProperty('DEBUG', 'false') == 'true') {
jvmArgs '-Xdebug',
'-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=10999'
}
}
Executed via gradle test -DDEBUG=true
Solution when using the JUnit Platform Gradle plugin
The solution above won't work when using org.junit.platform.gradle.plugin.
Instead it should be replaced by:
junitPlatformTest {
if (System.getProperty('DEBUG', 'false') == 'true') {
jvmArgs '-Xdebug',
'-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=10999'
}
}
I'm on 4.6 (gradle) and I'm able to debug my tests when I have this in my build.gradle file:
test {
debug true
}
Link - https://docs.gradle.org/4.6/userguide/userguide_single.html#sec:java_test