Java Command Process Chain Generator - java

I have build a Java command line application which consists of several moduls. So when you start the application via the command line, you have to pass one parameter and its options like this for example:
cmd-> java -jar application -startModul1 option1 folderPath
OR
cmd-> java -jar application -startModul5 500 folderPath 1222
Currently I have to start each modul by starting the application and passing the requested parameter+options. For now thats finde but later, when I have lets say 20 modules, I want to generate a proccess chain with several moduls started one after the other.
For example at the end I could start both modules from the example above with just one command.
cmd-> java -jar application -startAllModules option1 500 folderPath 1222
Is there a framework, where I can generate such a proccess chain with existing command line modules? This should not be NOTHING programatically because I want to have some sort of xml-file or whatever, where I just configure a process chain and where I can select the modules and its parameters that should be run with one command.

Have you thought of turning your program into an interpreter?

I think that parsing your command line, understanding what simple commands it must execute (from the xml you want to use) and launching them is enough.
How to launch them?
Process p = Runtime.exec(String[] cmdarray)
where cmdarray will have each of the words of the command:
{"java", "-jar", "application", "-startModul1", "option1", "folderPath"}
and
p.waitFor();
if you want this thread to wait until launched command ends.
Update: non concurrent
The later was in case you want to run several independent processes in parallel. One for command you need.
In case you only need to execute them one after the another there's a more simply way. When the main realizes it must execute multi modules, it calls itself with the appropiate arguments.
public static void main(String[] args) throws Exception {
// parse params
if (it's a multi module command line) {
for (each module you have to execute) {
main(new String[] {"-startModule1", ..., ...}); // call myself with different args
}
}
else {
// execute what you've been asked for
}
}

Related

Why doesn't cd command work using Java JSch?

I'm just learning Java and Jsch, and I can get it to run other commands but not cd. The error code returned by the SSHManager sendCommand function is not null, but some unreadable string that is different every time (maybe that means it is null not that familiar with inner workings of Java).
Any idea why not? Similar question here JSch - Why doesn't CD work? but unanswered.
I won't copy and paste the whole SSHManager class here - useful answer with complete code here that I'm trying to follow. Run a command over SSH with JSch
Sample code below:
import SSH.SSHManager;
public class src
{
int ERROR = 0;
public static void main(String[] args)
{
String username = "debian";
String password = "temppwd";
String ipadd = "192.168.7.2";
SSHManager ssh = new SSHManager(username, password, ipadd, "");
ssh.connect();
String out = "";
//this doesn't work, printing output as bytes to show how weird it is
out = ssh.sendCommand("cd Desktop");
System.out.println(out.getBytes());
//some other test commands
out = ssh.sendCommand("mkdir test");
System.out.println(out);
out = ssh.sendCommand("ls");
System.out.println(out);
ssh.sendCommand("logout");
}
}
Output from the Eclipse Console (bin and Desktop are already there in root directory):
[B#b065c63
bin
Desktop
test
Each command executed over SSH "exec" channel (what is behind SSHManager.sendCommand) is executed in its own shell. So the commands have no effect on each other.
To execute multiple commands in the same shell, just use an appropriate syntax of your server shell. Most *nix shells use semicolon or double-ampersand (with a different semantics).
In your case, the double-ampersand would be more appropriate.
cd Desktop && mkdir test && ls
See also Multiple commands using JSch.
Though, if your want to read commands output, you will have problem distinguishing, where output of one commands ends and output of the following commands starts. Let alone if you wanted to check command exit code.
Then it's better to execute each command in its own "exec" channel in a way that does not require a context. In your case that means using full paths:
mkdir Desktop/test
ls Desktop
See also How to perform multiple operations with JSch.
Also as you were going to use file manipulation only, you actually should not execute shell commands at all. Use the standard SSH API for file manipulation, the SFTP.
The question has kind of an answer, in the comments. Every command in sendCommand uses it's own 'pipe', so it disconnects and starts over in each one.
A quick solution would be to send multiple commands in one one sendCommand, such as:
out = ssh.sendCommand("cd Desktop; mkdir test; ls; logout");
But the correct way is to use a session, such as https://stackoverflow.com/a/9269234/290036
I answered a similar question Using java jcabi SSH client (or other) to execute several commands in shell
My open-source API Maverick Synergy has a high-level API to execute multiple commands within a shell. Its currently designed for and works well with bash-type shells.

Starting a Java application at startup

I have a Java application.
The application has a setting that decides whether or not the application starts at startup.
Currently, I have it this by placing/removing a shortcut in the StartUp items folder.
However, I am wondering if there is a better way to handle this behaviour.
EDIT
Yes, it's Windows. Sorry for not clearing that before.
The application has an UI where the user may trigger actions, also the application runs a few tasks in the background periodically while running.
#Peter, how could I change the registry with code from within the application? Is that approach compatible with all versions of Windows?
Below is a small example snippet of how it can be done from inside your application
static final String REG_ADD_CMD = "cmd /c reg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\" /v \"{0}\" /d \"{1}\" /t REG_EXPAND_SZ";
private void exec(String[] args) throws Exception
{
if (args.length != 2)
throw new IllegalArgumentException("\n\nUsage: java SetEnv {key} {value}\n\n");
String key = args[0];
String value = args[1];
String cmdLine = MessageFormat.format(REG_ADD_CMD, new Object[] { key, value });
Runtime.getRuntime().exec(cmdLine);
}
I'm pretty sure this will work with all versions of Windows since they all use the same Startup\Run registry entry.
Hope that helps! :)
Credit
On Windows I have used open source Java Service Wrapper to make our application as window service which you can setup automatic at startup.
What you need to do is to download latest wrapper.exe and create wrapper.config file put all the configuration like Main class any VM arument other parameters in defined standards and create a window service by this exe
Use the Registry to start your program at the startup and then it will be shown in the list provided by msconfig commnd through Run.
Use this registry path
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

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".

Run cmd-line in java fails

I am facing the following problem:
I am writing a java-application in Eclipse. Inside my application I want to start a cmd command:
C:/Users/User1/Content-Integration Testing Framework/JDBC Connector/bin/connect -h
The command 'connect -h' is a an enterprise internal application which works fine.
If I would use a comand line a would have to chance my current directory like that:
cd C:/Users/User1/Content-Integration Testing Framework/JDBC Connector/bin/
and afterwards I would just type connect -h
This works great. But I am not really shure how to execute this command within a java application.
Here they tell me how to run a cmd inside a java application:
How to use "cd" command using Java runtime?
But if I do that:
Runtime.getRuntime().exec("'C:/Users/User1/Content-Integration Testing Framework/JDBC Connector/bin/connect' -h");
Eclipse tells me:
java.io.IOException: Cannot run program "'C:/Users/User1/Content-Integration": CreateProcess error=2, Das System kann die angegebene Datei nicht finden
at java.lang.ProcessBuilder.start(Unknown Source)
It cuts my command at "Content-Integration".
can someone help me please?
You should use the version of exec() that takes multiple args via a String array.
Runtime.exec(String s) will split your string using a tokenizer (this is why quoting the string won't work, and why you see the behaviour you do). If you resolve the executable and arguments yourself, and pass each as an array element in the above e.g.
String[] args = new String[]{"executable", "arg1", "arg2"};
Runtime.getRuntime().exec(args); // don't forget to collect stdout/err etc.
then you will bypass Runtime.exec(String s)'s splitting behaviour.
Have you tried:
Runtime.getRuntime().exec("\"C:/Users/User1/Content-Integration Testing Framework/JDBC Connector/bin/connect\" -h");
This happens because your path contains spaces. Make sure to wrap it in "" and it will work.
Runtime.getRuntime().exec("\"C:/Users/User1/Content-Integration Testing Framework/JDBC Connector/bin/connect\" -h");

Executing python compiled script (.pyc) in Java

I have a python compiled script (script.pyc , I haven't the .py file)that work well from my windows command prompt, and I want to execute it from my Java's application.
I tried to use runtime() method :
Runtime runtime = Runtime.getRuntime();
runtime.exec(new String[] {"C:\\toto\\tools\\script.pyc" ,"arg","arg2" });
but I get an error :
Exception in thread "main" java.io.IOException: Cannot run program "C:\Nuance\VoCon Hybrid\SDK_v4_3\tools\clctodict.pyc": CreateProcess error=193, %1 n?est pas une application Win32 valid
The script work well in my terminal ("arg" is a txt file, "arg2" is the output name, and the script does its job without any problem).
I also try to launch my script with getDesktop() :
File fie = new File("C:\\toto\\tools\\script.pyc" ,"arg","arg2");
Desktop.getDesktop().open(fie);
There is no problem, but I can't add argument, so I can just see a terminal windows opening during a few second before disappearing instantly.
I have also tried to use JPython, without success too (maybe we can't use methode "execfile" on a .pyc????)
You can do something like
Process p = Runtime.getRuntime().exec(new String[]{"python.exe" ... other args)
Then you can invoke p.waitFor() to wait for the end of the process and p.exitValue() to test if the program exited successfully.
You can also get the output stream via p.getOutputStream() to retrieve the text printed by your python script
Please refer to the class documentation for further information : http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html
Just like you need a jvm to run a .class, you need a python interpreter to run a .pyc.
Try something like:
runtime.exec(new String[] {"c:\\Python26\\bin\\python.exe", "C:\\toto\\tools\\script.pyc" ,"arg","arg2" });

Categories

Resources