I'm new with JCommander and I'm trying to use it in my JAVA Command Line Application.
Fisrt thing I did is I've created my CommandLineArguments class.
Now, I'm trying to print options given with arguments in command line. But I think I'm missing something.
Here is my main class :
public static void main(String[] args) {
String[] argv={"-h","host"};
CommandLineArguments arguments=new CommandLineArguments();
JCommander commands= new JCommander(arguments);
try {
commands.parse(argv);
System.out.println(commands.getParsedCommand());
} catch (Exception e) {
System.out.println(e.getMessage());
commands.usage();
}
}
Once I run this class, I got : null as output. Seems like getParsedCommand() is not used as it should.
Can someone tell me how to use JCOmmmander methods correctly so I can see options given with arguments?
What I'm trying to do here is, once the user runs java -jar myApp.jar -port portNumber -h hostname -d database -c collection I wanna be able to get portNumber hostname database and collection value so I can establish a connexion and send queries.
Hope I was clear enough.
Ismail
You need to make a distinction between commands and parameters. In the example you give, you only need parameters.
The first chapter of the JCommander documentation provides a clear enough example of how to handle parameters. If your CommandLineArguments class is annotated as in the example, the parameter values should be correctly set in that class after calling parse(argv).
Commands are explained in a later chapter dealing with more complex command-line syntaxes.
Related
I hope someone can help me with this one... It's kind of a rookie question, but unfortunately I'm kind of stuck right here.
Currently I'm starting my java application like (cmd):
Now this is the calling part after all the classpath stuff.
%JAVA_HOME%bin\java.exe -cp %CLASSPATH%;%SCRIPTROOT%jar* -XX:MaxPermSize=1024M view.Main C:\temp\MyDatabase c:\temp\MyFile.xml
First arg:
C:\temp\MyDatabase
Second arg:
C:\temp\MyFile.xml
public static void init(String[] args){
try {
mydatabase = args[0];
} catch (Exception ex) {
}
try {
myfile = args[1];
} catch (Exception ex) {
}
}
Now in this case the order of the arguments is relevant.
With only two arguments this might be just fine, but what am I supposed to do, if I have like 10 arguments and some of them were optional? That would be a problem, right?
What if I do something like this:
%JAVA_HOME%bin\java.exe -cp %CLASSPATH%;%SCRIPTROOT%jar* -XX:MaxPermSize=1024M view.Main database:/C:\temp\MyDatabase myfile:/c:\temp\MyFile.xml
Now within my code the order would not matter anymore, because I have like a "key-value pair" of arguments and the key identifies the actual "use" of value. This works, but it don't feels right.
Is there a better way of doing this?
Maybe like java.exe does it with -cp? If yes, how can I implement this?
Thank you.
You need java.util.Properties.
Pass them to java process adding -D:
java -jar my-app.jar -Dfile=C:\temp\MyFile.xml -Ddatabase=C:\temp\MyDatabase
Order now does not matter. Get you args inside with System.getProperties() static method, it also has its satellites System.getPropery(String key) and System.getPropery(String key, Object default).
For advanced options take a look at Apache Commons CLI and libs like such.
I am trying to figure out how to pass parameter and command to the command prompt via Java.
I am trying to create a program which gel serveral command prompt application together.
I have tried using
Process p = Runtime.getRuntime().exec()
but i can only execute one command at a time how do i pass parameters ?
Thanks.
Please read the source code of Runtime.Class.
There are several optional functions could be used like
public Process exec(String cmdarray[]) throws IOException {
return exec(cmdarray, null, null);
}
You could put commands in an array as the parameter of the function.
Hope it would be helpful for you.
I am wondering if there's a way to create a jar that includes some command line arguments in it, the arguments that are usually passed in the command line when one tries to start up the jar (these parameters are then passed on to the main function). Basically instead of starting my app with
java -jar myapp.jar "arg1" "arg2", I want to start my app with
java -jar myapp.jar
and have "arg1" and "arg2" passed to the main function.
The reason behind this is that I want to deploy this to different environments, and I want my jar to contain different parameters according to the environment it's being deployed at.
Maybe there's another way to achieve similar results ??
Cheers.
PS: Looking for a maven solution.
Edit: I'll add a complete example to make this a bit more clear:
Let's say I have 2 environments: "Production" and "Test". I want to run the jar in the same way no matter in what environment I deploy it. So I always want to run it with:
java -jar myapp.jar
But! In order for my 2 environments to run ok, I need the Production environment jar to start it's main method with an argument "prod" and I need the Test environment jar to start it's main method with an argument "test".
If I correctly understood your problem, in your main() you could define a simple logic to handle the case where you do not specify any input parameter; the logic could retrieve the desired values according to the correct platform/env.
As an example:
public class Test01
{
public static void main(String... aaa)
{
// Check input
if(aaa.length == 0) {
/* Insert logic to retrieve the value you want, depending on the platform/environment.
* A trivial example could be: */
aaa = new String[2];
aaa[0] = "First value";
aaa[1] = "Second value";
}
// Processing, e.g. print the 2 input values
System.out.println(aaa[0] + ", " + aaa[1]);
}
}
Fyi, I created a runnable jar using eclipse, and start the application by either
java -jar Test01.jar
or
java -jar Test01.jar arg1 arg2
Hope this helps!
One solution is to change main(String[] args) to get values from env var if they are not present in the passed arguments.
String user;
String password;
if(args.length < 2)
{
user = System.getenv("appUser");
password = System.getenv("appPassword");
} else {
user = args[0];
password = args[1];
}
You can also create another class with a main function that will call the real one.
public class CallerMyApp{
public void main(String[] args) {
String[] realArgs = {System.getenv("appUser"), System.getenv("appPassword")};
MyApp.main(realArgs);
}
}
Then to execute its something like
java -cp myapp.jar CallerMyApp
I would like to know if it is possible to get from code the command used to launch a java program.
E.g. if I launch a java program with:
java -cp lib1:lib2:... -jar mylib.jar com.foo.Bar
I would like to get the exact string (jvm parameters included).
Is it possible?
Comment on the bounty and the question
Thank you all for your responses. Unfortunately, I did not get the answer I was initally looking for. I was hoping there was some portable solution to get the complete java command from within the program itself (including classpath etc.). As it seems there are no portable solution and since I am using Linux I am using the responses of agodinhost and Luigi R. Viggiano to solve my problem. However I give the bounty to rahulroc for the most complete (portable) response. For the rest an upvote for all :)
The below mentioned code should show all JVM parameters, arguments passed to the main method as well as the main class name.
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;
public static void main(String[] args) {
RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
List<String> jvmArgs = bean.getInputArguments();
for (int i = 0; i < jvmArgs.size(); i++) {
System.out.println( jvmArgs.get( i ) );
}
System.out.println(" -classpath " + System.getProperty("java.class.path"));
// print the non-JVM command line arguments
// print name of the main class with its arguments, like org.ClassName param1 param2
System.out.println(" " + System.getProperty("sun.java.command"));
}
javadoc for getInputArguments
Returns the input arguments passed to the Java virtual machine which
does not include the arguments to the main method. This method returns
an empty list if there is no input argument to the Java virtual
machine.
Some Java virtual machine implementations may take input arguments
from multiple different sources: for examples, arguments passed from
the application that launches the Java virtual machine such as the
'java' command, environment variables, configuration files, etc.
Typically, not all command-line options to the 'java' command are
passed to the Java virtual machine. Thus, the returned input arguments
may not include all command-line options.
You can also take a look at : jps
It's a Java program that is able to get the full command line for all
Java processes, including full class name of main class and JVM
options.
You can find a good summary of various JVM tools, including
Java Application Launcher links to :
ManagementFactory.getRuntimeMXBean() - Returns the managed bean for the runtime system of the Java virtual machine.
getInputArguments() javadoc
determine if JVM is running in debug mode
You can use this to retrieve the VM parameters :
public static void main(String args[]) {
List<String> inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
System.out.println("input arguments = " + inputArguments);
}
However it won't give you all the command line (only gives the JVM arguments, no main class nor parameters). Sample output:
input arguments = [-Dfile.encoding=UTF-8, -XX:-UseTLAB, -Xms2000m, -Xmx2000m, -XX:+PrintCompilation, -XX:+PrintGC]
It only works on Sun Oracle JVM: System.getProperty("sun.java.command")
Additionally, you can have a look at JavaSysMon, it can report command line of active processes. To check which is the current JVM Process check here: How can a Java program get its own process ID?
in a linux machine would be easier to run:
ps -ef | grep java
this command will list all java programs running with it's used parameters.
Not sure about what can be used in a windows environment.
In the task manager on Win2003 you can enable the display of a column that displays the command like it does on linux. Or, you can do it from the command line like so:
wmic.exe PROCESS where "name like '%java%'" get Processid,Caption,Commandline
I know that I can get the command-line arguments in the "main" method, but I need to be able to get them indirectly.
Thanks for your help.
Following expression is exactly what you want:
System.getProperty("sun.java.command")
You can list the threads, find the main thread, and crawl down the stack trace until you find the call to main, and pull out the args.
update a comment points out that this won't work all by itself, and I think the comment is correct. I misremembered the capabilities of stack introspection or mentally mixed in JVMTI.
So, here's plan B. Connect to yourself with JMX. The VM Summary MBean has the args.
Connection name:
pid: 77090 com.basistech.jdd.JDDLauncher -config src/main/config/benson-laptop-config.xml
All this having been said, what you should do is call System.getProperty and live with the need to use -D to pass parameters from the outside world down into your cave.
You could write a wrapper to take the cli and re-format it to use -DPROP=VAL
int main(int argc, char*argv[])
{
std::vector<std::string> in (argv+1,argv+argc), out();
out.push_back("java.exe");
out.push_back("-cp");
out.push_back("my-jar.jar");
out.push_back("main.class")
for( auto it = in.begin(); it!=in.end(); ++in)
{
//process CLI args. turn "-abc","BLAH" into "-Darg.a=true","-Darg.b=true","-Darg.c=BLAH" and push to out
//Do additional processing. Maybe evn use get_opt() or Boost.ProgramOptions
}
//use exec or CreateProcess to launch java with the proper args
//or even use something like WinRun4J's methods to load the jvm.dll
//Then your program shows up as "MyExe.exe" instead of "java.exe"
//Use System.getProperty("arg.a","false") to get the value of a
}
Of course, you could always just tell you users to invoke a bash/batch script with the proper -DA=true type arguments