1

I have a Windows batch file to run my Java app, so this looks like:

RunJavaPgm.bat

java -classpath lib\* com.blah.MyClass %*

So this works perfectly well, I can pass through any number of parameters to my main method by doing something like

RunJavaPgm Param1 Param2

Now the problem I've hit is that I need to define some system properties, but if I try to do something like

RunJavaPgm Param1 Param2 -DMyProperty=MyValue

then it doesn't work - its passing that -D value to my main method. Putting " around it makes no difference. The reason being that, if you just type "java' on the command line, it tells you what the syntax is supposed to be:

java [-options] class [args]

So any -D parameters need to go before the classname, and any main method parameters need to go after the classname. Making the batch file intelligent enough to examine the value of every parameter passed to it and splitting them up in that way would seem very difficult to do, can anyone think of any clever alternatives?

Many thanks!

Related - batch file to run jar file with parameters

4
  • 1
    sorry, but i do not understand your problem.Why did you not specify the JVM Options before the main-class parameter? Commented Sep 1, 2014 at 14:53
  • 1
    Because its being ran from a batch file. I don't know when writing the batch file what JVM options the end user running this may want to specify. To the batch file that %* notation just means all the parameters passed into it, it doesn't know the difference between JVM and main method parameters. Commented Sep 1, 2014 at 15:09
  • @nigelg - new answer arrived.. Commented Sep 1, 2014 at 16:04
  • ok. i do understand now. but when the "user" is aware of -D JVM-Options,it should not be a problem to the user to append "-classpath lib* com.blah.MyClass". I don't think that someone will really benefit by using this Batch-File. Commented Sep 1, 2014 at 16:24

2 Answers 2

1

try this :

@echo off

setlocal EnableDelayedExpansion

set "jvm_args="
set "main_args="
set flag=0

for %%a in (%*) do (

    set arg=%%~a


    if !flag! EQU 0 if "!arg:~0,1!" NEQ "-" (
        set "main_args= !main_args! %%a"
        set flag=2
    )

    if "!arg:~0,1!" EQU "-" (
        set "jvm_args=!jvm_args! !arg!"
        set flag=1
    )

    if !flag! EQU 1 if "!arg:~0,1!" NEQ "-"  (
        set "jvm_args=!jvm_args!=!arg!"
        set flag=0
    )

)

::remove echo to run the java
echo java %jvm_args% com.blah.MyClass %main_args%

It checks i the argument starts with - and puts it (and the next one as the = is delimiter for batch) to jvm arguments and the rest to java arguments. It is not perfect solution (and is not heavy tested) , but might do the thing you want.

EDIT: attempt to handle quoted jvm parameters:

@echo off

setlocal EnableDelayedExpansion

set "jvm_args="
set "main_args="
set flag=0

for %%a in (%*) do (

    set "arg=%%~a"

    echo #!arg:~0,1!#

    if !flag! EQU 0 if "!arg:~0,1!" NEQ "-" (
        set "main_args= !main_args! %%a"
        set flag=2
    )

    if "!arg:~0,1!" EQU "-" (
        set "jvm_args=!jvm_args! !arg!"
        set flag=1
        echo !arg!|find "=" >nul 2>&1 && set flag=0

    )

    if !flag! EQU 1 if "!arg:~0,1!" NEQ "-"  (
        set "jvm_args=!jvm_args!=!arg!"
        set flag=0
    )

)

::remove echo to run the java
echo java %jvm_args% com.blah.MyClass %main_args%
Sign up to request clarification or add additional context in comments.

3 Comments

This is fabulous, thank you so much! As you say, handling = is a problem. As your code is it will handle RunJavaPgm -Dx=y Param1 but not RunJavaPgm "-Dx=y" Param1 because the flag then considers Param1 to be the value after the JVM param. It seems impossible to handle both -Dx=y and "-Dx=y" at the same time since the first = disappears before the batch file can see it. So I will just tell the users they must put -D params in double quotes, that's not a problem, and makes the script a little simpler since it doesn't have the flag values to worry about. So, great thank you!
@nigelg I think its possible to handle also quoted case with a bit more effort.If I succeed will add it to the answer...
@nigelg - I've added a variant where it handles quoted jvm parameters , though it could fail if there are spaces there (it will be a huge effort to make really robust) .Still should work in most of the cases.
1

... can anyone think of any clever alternatives?

There are no clever alternatives. If you want to allow the -D options to appear anywhere on the command line, then your Java application needs to be called by a wrapper script, batch file, or some other kind of launcher that knows how to rearrange the command options.

But I'd have thought that a user who can understand -D options can also be taught to put them in the right place.


(You could consider getting the main method to look for "misplaced" -D options, and adding the corresponding system properties. However, in a lot of cases, that will happen too late. Some properties will be used before your main method executes. This is not a solution, in general.)

3 Comments

Yeah I'd thought of that... its a Spring app, so in the first few lines, before it fires up the spring context, the main method could parse all the args to see if any begin with -D and use System.setProperty to set them, but that just seemed a nasty way to have to do it :(
And yes the users know about how to use the -D option correctly and would know where to put it, but I'm trying to save them the grief of having to type out "java -classpath lib/* -DSomeProperty=SomeValue com.very.long.package.name.VeryLongClassName Param1 Param2" so instead they can just type "RunJavaPgm -DSomeProperty=SomeValue Param1 Param2"
@nigelg - Well, if this is just and idea, I suggest that you give up on it. If it is a hard requirement ... well bite the bullet and write a smart batch file (good luck with that!) or code up a launcher in a language that is easier to use; e.g. Perl or Python.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.