Gradle console() is null with daemon disabled - java

I'm using Gradle 2.13 with Java 1.8.0_121.
One of our Gradle tasks relies on user input.
def user = System.console().readLine('Please enter new user username: ')
However I get the following error: > Cannot invoke method readLine() on null object
So console() must be null... okay. I found this related issue suggesting to disable the daemon.
I did that and ran it with ./gradlew configureTask --no-daemon but got the same result... same error. I'm pretty sure it's not using the daemon as I get the following message: To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/2.13/userguide/gradle_daemon.html.
So if the Gradle daemon is not causing this issue, what else could be? Does anyone more experienced with Gradle know?

Gradle says it needs to run the build in a subprocess because of something in your build settings:
To honour the JVM settings for this build a new JVM will be forked.
And I guess Gradle creates that subprocess in a way that allows it to grab the output (which is the default with the APIs Java offers to spawn subprocesses). As a result, the subprocess does not have access to I/O of your terminal, and System.console() is null within that process: it is not attached to the system console.
It got me curious so I came up with a script that demonstrates the issue (using Groovy for its conciseness, it's the same thing as Java here):
import java.io.Console
println "Console for main JVM: " + System.console()
Process p1 = new ProcessBuilder("groovy", "-e", "print System.console()")
.redirectErrorStream(true)
.start()
p1.waitFor()
println "Console for child JVM: " + p1.text
Process p2 = new ProcessBuilder("groovy", "-e", "println 'Console for child JVM with inherited IO: ' + System.console()")
.redirectErrorStream(true)
.inheritIO() // <- this changes everything, as now p2 is attached to system console
.start()
p2.waitFor()
// No need to (actually cannot) get output of p2, as I/O is inherited by p2 it gets printed to terminal directly
Result:
Console for main JVM: java.io.Console#64cd705f
Console for child JVM: null
Console for child JVM with inherited IO: java.io.Console#3c130745
So Gradle is probably building the subprocess like p1 in my example. And I guess it needs to, because it needs to inspect the output (and not let it go directly to system output).
I think your only solutions are:
find a way to get Gradle do the build in the main JVM, without forking. Not a Gradle expert so I don't know how but the message seems to imply it's possible.
find another way to get user input. Maybe a Swing dialog? (not very elegant but hey, a build that takes user input is not very elegant in the first place, so the way it is collected does not matter much at this point)

Related

Pass System Property to Application using Gradle and Netbeans

To run my application from the command line, I run:
java -Dconfig.file=./config/devApp.config -jar ./build/libs/myJar.jar
and inside my code, I have:
String configPath = System.getProperty("config.file");
Which gets the property just fine. However, when I try to debug using the built in debug Netbeans task, the property is null. The output of my run is:
Executing: gradle debug
Arguments: [-Dconfig.file=./config/devApp.config, -PmainClass=com.comp.entrypoints.Runner, -c, /home/me/Documents/projects/proj/settings.gradle]
JVM Arguments: [-Dconfig.file=./config/devApp.config]
Which is coming from:
I set it in both the arguments and JVM arguemtns to see if either would set it. Regardless of what I do, it is null. Can someone help me figure out how to set the system property so my app can get it?
You are setting the property on the Gradle JVM which has almost nothing to do with the JVM your application runs in. If you want to use Gradle to start your app for debugging, you have to tweak your Gradle build file to set or forward the system property to the debug task.
Assuming the debug task is of type JavaExec this would be something like
systemProperty 'config.file', System.properties.'config.file'
in the configuration of your debug task to forward what you set up in the "JVM Arguments" field in Netbeans.
It seems that the "Arguments (each line is an argument):" and "JVM Arguments (each line is an argument):" fields provide values to the Gradle task itself. How I managed to pass properties over to the application was to append them to the jvmLineArgs argument (see image).
My application is now receiving the profiles property.
Thanks to #Vampire for the "guess work", lol!

Starting Mule for remote debugging without modifying wrapper.conf

I'm stuck on Mule version 3.4.0 due to requirements at work. I'm writing a service script to manage the service lifecycle of Mule and would really like to be able to have it hang and wait for a debugger to connect based on whether a certain option is present in the parameters.
I'm comfortable with Bash and implementing this, but I'm having an extremely hard time trying to get Mule to pass along the
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=9989
to the underlying Java process, as it uses its own (stupid) wrapper to address Java.
I'm trying to modify the bin/mule script to have a mode called debug which will pass the above debugger options to the JVM when invoked with:
bin/mule debug
My current work can be found here on PasteBin, and here is the relevant part near line 511:
debug() {
echo "Debugging $APP_LONG_NAME..."
getpid
if [ "X$pid" = "X" ]
then
# The string passed to eval must handle spaces in paths correctly.
COMMAND_LINE="$CMDNICE \"$WRAPPER_CMD\" \"$WRAPPER_CONF\" wrapper.syslog.ident=$APP_NAME wrapper.pidfile=\"$PIDFILE\" $ANCHORPROP $LOCKPROP"
######################################################################
# Customized for Mule
######################################################################
echo "command line: $COMMAND_LINE"
echo "mule opts: $MULE_OPTS"
echo "JPDA_OPTS: $JPDA_OPTS"
eval $COMMAND_LINE $JPDA_OPTS $MULE_OPTS
######################################################################
else
echo "$APP_LONG_NAME is already running."
exit 1
fi
}
I cannot upgrade to a newer version of Mule. I need to find a way to modify this script to simply wait for a debugger when invoked with bin/mule debug. I've modified it enough to get into this debug function I've defined which is basically a copy of their own console function for starting in console mode. I can't seem to figure out how to get my debug opts passed to the JVM. Any ideas?
The parameter -debug, following documentation, was present in 3.4.x:
./mule -debug
Give it a try.

Run jar from within a Java application

I am trying to build a simple auto updater for my application. I am currently checking the local application version against my remote version. If there is a newer version I want to start my updater.jar - which basically downloads and replaces the old application.
My problem is that I cannot seem to get the updater.jar to start if there is a new version.
The code I am currently using is:
Runtime runtime = Runtime.getRuntime();
try {
Process proc = runtime.exec("java -jar updater.jar");
} catch (IOException ex) {
Logger.getLogger(Splash.class.getName()).log(Level.SEVERE, null, ex);
}
System.exit(0);
The application exits but updater.jar is never launched..
Any ideas?
Your child process is likely exiting when your parent process exits.
When you launch a process you should usually:
consume stdout/stderr from the child process. If you don't do this your child process can block waiting for its output to be consumed. You should consume in separate threads. See this answer for more details
use Process.waitFor() to capture the exit code from the child process
It looks to me like you want to spawn the updater, let it perform a download and then exit your parent process. Anything more complex would likely be platform dependent (e.g. spawning a background process and disowning it)
Maybe the path to updater.jar should be specified in the java -jar command.
You better use the URLClassLoader since jre1.2
see How to load a jar file at runtime

Can't run JDI trace example: Error: Could not find or load main class

I run in command line the following program as an example app:
java -cp "D:\projects\PDFJavaFX\lib\PDFRenderer-0.9.1.jar"
com/sun/pdfview/PDFViewer
Then I run in command line the JDI trace example:
java -cp "C:\Program
Files\Java\jdk1.7.0_13\lib\tools.jar;D:\projects\JDI_Trace\jar\trace.jar;D:\projects\PDFJavaFX\lib\PDFRenderer-0.9.1.jar"
com/sun/tools/example/trace/Trace com/sun/pdfview/PDFViewer
I get this error:
Error: Could not find or load main class com.sun.pdfview.PDFViewer
-- VM Started --
-- The application exited --
The example app runs correctly, and it is included in the classpath.
What's the cause of this?
What am I missing?
Thanks
Edit: It looks like it is classpath related.
I did get this to work (well, it popped up the GUI but then crashed pretty quickly). I used the classpath environment variable instead of -cp:
C:\cos126\dev\debug>set CLASSPATH=%CLASSPATH%;c:\tmp\PDFRenderer-0.9.1.jar;c:\tmp\debug
So, not pretty, but then it did work. So it looks like the newly created VM doesn't automatically inherit -cp. I am optimistic, but not sure, that there might be an option you can change when starting the new VM to do this for you. To see the "documentation" for the VM launching options, you can add some code like
for (Map.Entry<String, Connector.Argument> arg : arguments.entrySet()) {
System.out.println(arg.getValue().name()+" "+arg.getValue().description());
}
to Trace.java. When I do this, it prints out
home Home directory of the SDK or runtime environment used to launch the application
options Launched VM options
main Main class and arguments, or if -jar is an option, the main jar file and arguments
suspend All threads will be suspended before execution of main
quote Character used to combine space-delimited text into a single command line argument
vmexec Name of the Java VM launcher
so maybe one of those is useful? Good luck!
By the way, this is what I used JDI for:
http://cscircles.cemc.uwaterloo.ca/java-visualize/
I am in the process of making the source shareable, if you want to see it (although I'm not 100% sure it will be of use).
Your command :
java -cp "C:\Program Files\Java\jdk1.7.0_13\lib\tools.jar;
D:\projects\JDI_Trace\jar\trace.jar;
D:\projects\PDFJavaFX\lib\PDFRenderer-0.9.1.jar"
com/sun/tools/example/trace/Trace com/sun/pdfview/PDFViewer
Explanation :
The new VM which is created by the Trace has different class path. main class PDFViewer is in the PDFRenderer**.jar,but the new VM didn't know the jar, so it can't find the main class. I also met this problem when I used Eclipse. And by changing the working directory, I can run it successfully.
In fact, the Trace class uses JDI to launch the new VM, but it only set the main option and discard the vm options. The code below is quoted from the Thrace class source file, and I add some lines to print the options.
Map<String, Connector.Argument> connectorArguments(LaunchingConnector connector, String mainArgs) {
Map<String, Connector.Argument> arguments = connector.defaultArguments();
Connector.Argument mainArg =
(Connector.Argument)arguments.get("main");
//added by me: begin
java.util.Set<String> argsString = arguments.keySet();
System.out.println("connector args size is :" + argsString.size());
for (String arg : argsString) {
System.out.println(arg + "=="+ arguments.get(arg).description()+"=="+arguments.get(arg).value()) ;
//added by me: end
}
if (mainArg == null) {
throw new Error("Bad launching connector");
}
mainArg.setValue(mainArgs);
The output of the arguments size is 6, and they are "home, options, main, suspend, quote and vmexec". If we want to configure the new VM options, we can set the "options" by setValue method like setting "main".

Java virtual machine launch issue

HI All,
I got an issue, all of a sudden Java stopped working completely. I start getting error like "Could not create the virtual machine". There is no issue with the memory (it has 3GB RAM) and was working fine for over a 6 months in this system without any issue.
Here are some peculiar behaviors -
When I start eclipse I see Java virtual machine dialog box with error messages like
"Could not find main class org.eclipse......support.legacysystemproperties"
Eclipse is able to start(with above error), but while running the program, I get error like "Could not create Java Virtual Machine" in a dialog box and after I click OK on that dialog box, I see error like "unrecognized option -dfile.encoding=cp1252
I used text editor, wrote a class Test.java (without any package), compiled it (Edit #1:javac Test.java). But when I execute the program (Edit #1:java Test), I get the following error -
Exception in thread "main" java.lang.NoClassDefFoundError: test (wrong name: Test).
Edit #1:
Note : The compiled file, Test.class is successfully created in the directory. I did recheck the path and classpath environment variables. All seem to be correct.
Please note that there seems to be some issues with cases which affected the Java.
I did uninstall Java (all versions), re-installed, but nothing helped. Also, I did run CCleaner to clean registry, Malwarebytes' Anti-Malware, but none helped so far.
Appreciate if someone could help me to resolve the issue.
I did googled for this and found that some have experienced similar issues, but none of them have found solution yet other than some suggestion that re-installation of Windows OS itself, which I want to avoid it. I did system restore, but that failed for some other
reason.
Please note that am using Java for over 10 years. This is first time am having such issue. This is something to do with Windows Registry or some other system configuration, but I am not able to find out the exact problem.
Anyways awaiting some good suggestion.
EDIT: Okay, so it looks like the Java executable is getting the command line arguments lower-cased.
Step 1: Verify
You can double-check whether this affects all command line arguments by creating a class with a lower-case name which just dumps its arguments:
public class test {
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
Compile and run this with a variety of inputs.
Step 2: Check scope
Assuming step 1 confirms the problem, if you've got .NET installed you can see whether it affects that as well. Create a file Test.cs:
using System;
class Test
{
static void Main(string[] args)
{
foreach (string arg in args)
{
Console.WriteLine(arg);
}
}
}
Compile this with "csc Test.cs" having found csc in the .NET framework directory (e.g. in c:\Windows\Microsoft.NET\Framework\v4.0.30319 for .NET 4).
Run it like this:
Test foo BAR Baz
and see what happens
Step 3: If step 2 showed that the issue is limited to java.exe:
Check your path, and work out where you're actually running java.exe from
Try explicitly running java.exe from your JRE or JDK directory

Categories

Resources