How to start an interactive java app with gradle - java

I want to write a gradle task that runs me this small application:
import java.lang.IllegalArgumentException
class TestApp{
companion object {
#JvmStatic
fun main(args:Array<String>){
val a = try{
args[0].toInt()
}catch (e:Exception) {throw argException}
val b = try{
args[1].toInt()
}catch (e:Exception) {throw argException}
print("$a + $b = ")
val answer = readLine()!!.toInt()
println(if(a+b == answer)"CORRECT" else "WRONG!")
}
private val argException:IllegalArgumentException by lazy { IllegalArgumentException("expecting two integers as args") }
}
}
If I run the application with, say, Intellij, the app will pause at the readline() and expect user input.
However, if I add a gradle task for it
task runTestApp(type:JavaExec){
main = "${javaMainTestApp}"
classpath = sourceSets.main.runtimeClasspath
}
and run, say,
gradle runTestApp --args="2 4"
Then I get
2 + 4 = Exception in thread "main" kotlin.KotlinNullPointerException
at [...].app.TestApp$Companion.main(TestApp.kt:19)
at [...].app.TestApp.main(TestApp.kt)
Why is that? And more importantly, how do I get the execution to wait for user input?
UPDATE
Thanks #tim_yates:
adding standardInput = System.in makes the app accept user input
but results in an output like:
3 + 5 =
<<==========---> 80% EXECUTING [20s]
> :runTestApp
8
where 8 is the user input.
consequently, when the app finishes, the output reads
3 + 5 =
<<======CORRECT> 80% EXECUTING [22s]

Maybe you could use the application plugin and do a gradle run. Or you could use the distribution plugin and run the script.

Related

Automatically handling / ignoring NameError in Jython

I have a setup where I execute jython scripts from a Java application. The java application feed the jython script with variables, coming from the command line, so that a user can write the following code in it's jython script:
print("Hello, %s" % foobar)
And will call the java program with this:
$ java -jar myengine.jar script.py --foobar=baz
Hello, baz
My java application parse the command-line, and create a variable of that name with the given value to give to the jython scripting environment to consume. All is well so far.
My issue is that when the user does not provide the foobar command-line parameter, I'd like to be able to easily provide a fallback in my script. For now, the user needs to write that sort of code to handle the situation where the foobar parameter is missing from the command-line:
try: foobar
except NameError: foobar = "some default value"
But this is cumbersome, especially if the number of parameters is growing. Is there a way to handle that better from the script user point of view?
I was thinking of catching the jython NameError in the Java code, initializing the variable causing the exception to a default value if the variable causing the exception "looks like" a parameter (adding a naming convention is OK), and restarting where the exception occurred. Alternatively, I can require the script user to write code such as this:
parameter(foobar, "some default value")
Or something equivalent.
Well, this is one ugly workaround I found so far. Be careful, as this will call the script in loop many times, and is O(n^2).
private void callScriptLoop(String scriptfile) {
PythonInterpreter pi = new PythonInterpreter();
pi.set("env", someEnv);
int nloop = 0;
boolean shouldRestart;
do {
shouldRestart = false;
try {
pi.execfile(scriptfile);
} catch (Throwable e) {
if (e instanceof PyException) {
PyException pe = (PyException) e;
String typ = pe.type.toString();
String val = pe.value.toString();
Matcher m = Pattern.compile("^name '(.*)' is not defined")
.matcher(val);
if (typ.equals("<type 'exceptions.NameError'>")
&& m.find()) {
String varname = m.group(1);
pi.set(varname, Py.None);
System.out.println(
"Initializing missing parameter '"
+ varname + "' to default value (None).");
shouldRestart = true;
nloop++;
if (nloop > 100)
throw new RuntimeException(
"NameError handler infinite loop detected: bailing-out.");
}
}
if (!shouldRestart)
throw e;
}
} while (shouldRestart);
}

How to see the list of JARs that are loaded with my Scala Application

I need to do a security scan for my application. I have wrote this code to download all the dependent JARs
barvaz := {
buildStandalone.value
// Define the paths to the ".ivy2" in the current-working-directory (localIvy) and in the
user's home
val localIvy = (baseDirectory in publishLocal).value / ".ivy2"
val projectBoot = (baseDirectory in publishLocal).value / "project/boot"
// Package everything in target/standalone.zip so it could easily be copied around
val ivy2Files = (localIvy ** "*.jar").get.map(_.getPath.replaceAll(".*\\.ivy2", ".ivy2"))
val projectFiles = (projectBoot ** "*.jar").get.map(_.getPath.replaceAll(".*boot", "project/boot"))
val jarNames = (ivy2Files ++ projectFiles).map(_.replaceAll("\\\\", "/")) //Seq("sbt-launch.jar") ++
Packaging.downloadLibSourcesAndBins((resourceDirectory in Compile).value / "barvaz", jarNames)
val downloadedJars = ((target.value / "barvaz") ** "*.jar").get.map(f => f -> f.getPath.replaceFirst(".*barvaz", ""))
IO.zip(downloadedJars, new File(s"target/barvaz-${version.value}.zip"))
"Done"
}
however I have now duplicates of JARs from different versions , for example jettey from version 4.0.0 and 4.0.1 and of course some testing JARs
How can I inspect which JARs are actually loaded?
You can try show fullClasspath in sbt.
Edit:
If you want a pretty text output (perhaps to feed into some other programs), you can try consoleProject and then in the scala repl, evaluate: println(fullClasspath.in(Compile).eval.map(_.data).mkString("\n")).

Passing parameters to gradle build script

I'm trying to execute a such command in the console:
./gradlew cucumber -Pthreads=80 -Ptags=#ALL_API_TESTS
in the build.gradle:
cucumber {
threads = "$threads"
glue = 'classpath:com.sixtleasing.cucumber.steps'
plugin = ['pretty']
tags = "$tags"
featurePath = 'src/main/resources/feature'
main = 'cucumber.api.cli.Main'
}
but it doesnt work :( How can I fix it?
Your original expression set threads to a String value, when it is clearly a numeric one, so you need to use something like:
int threadsNum = "$threads".toInteger()
cucumber {
threads = threadsNum
glue = 'classpath:com.sixtleasing.cucumber.steps'
plugin = ['pretty']
tags = "$tags"
featurePath = 'src/main/resources/feature'
main = 'cucumber.api.cli.Main'
}
Hope this helps.

How to gracefully end test client

I have a simple cumulocity test client. The code runs fine but the jvm does not stop when the code finishes.
Some threads are still running: MultiThreadedHttpConnectionManager.
How to gracefully shutdown the open connections allocated by:
InventoryApi inventory = platform.getInventoryApi() ?
_
...
platform = new PlatformImpl(App.C8Y_URL, new CumulocityCredentials(App.C8Y_USER, App.C8Y_PWD));
InventoryApi inventory = platform.getInventoryApi();
GId testId = new GId("123456");
ManagedObjectRepresentation testDevice = inventory.get(testId);
MeasurementApi mApi = platform.getMeasurementApi();
MeasurementRepresentation measurement = new MeasurementRepresentation();
measurement.setType("c8y_SampleRate");
measurement.setSource(testDevice);
DateTime time = new DateTime();
System.out.println("time " + time.toString());
measurement.setDateTime(time);
Map<String, Object> flowRateFragment = App.createFlowRateFragment(new BigDecimal(20.5));
measurement.set(flowRateFragment, "c8y_SampleRate");
MeasurementRepresentation measurementCreation = mApi.create(measurement);
...
To gracefully shutdown your Cumulocity client call platform.close().
NO you cannot exit after the code finished. Cumulocity agent is made to run continuously so, they won't stop the thread.
If you want out exit then you have use
System.exit(0); //Change the status code accordingly.

Listening on CTRL+C in Groovy Script

Is it possible to listen to CTRL+C when a groovy script is run from the command line ?
I have a script that creates some files. If interrupted I want to delete them from disk and then terminate.
Possible?
UPDATE 1:
Derived from #tim_yates answer:
def withInteruptionListener = { Closure cloj, Closure onInterrupt ->
def thread = { onInterrupt?.call() } as Thread
Runtime.runtime.addShutdownHook (thread)
cloj();
Runtime.runtime.removeShutdownHook (thread)
}
withInteruptionListener ({
println "Do this"
sleep(3000)
throw new java.lang.RuntimeException("Just to see that this is also taken care of")
}, {
println "Interupted! Clean up!"
})
The following should work:
CLEANUP_REQUIRED = true
Runtime.runtime.addShutdownHook {
println "Shutting down..."
if( CLEANUP_REQUIRED ) {
println "Cleaning up..."
}
}
(1..10).each {
sleep( 1000 )
}
CLEANUP_REQUIRED = false
As you can see, (as #DaveNewton points out), "Shutting down..." will be printed when the user presses CTRL-C, or the process finishes normally, so you'd need some method of detecting whether cleanup is required
Update
For the sake of curiosity, here is how you would do it using the unsupported sun.misc classes:
import sun.misc.Signal
import sun.misc.SignalHandler
def oldHandler
oldHandler = Signal.handle( new Signal("INT"), [ handle:{ sig ->
println "Caught SIGINT"
if( oldHandler ) oldHandler.handle( sig )
} ] as SignalHandler );
(1..10).each {
sleep( 1000 )
}
But obviously, those classes can't be recommended as they might disappear/change/move
I am not much into groovy script but i have a link that have some examples and says catching ctrl+c.....hope that helps http://pleac.sourceforge.net/pleac_groovy/processmanagementetc.html

Categories

Resources