Topic
  • 11 replies
  • Latest Post - ‏2008-01-28T12:02:52Z by SystemAdmin
SystemAdmin
SystemAdmin
1525 Posts

Pinned topic Runnimg a script (command file) from an application

‏2007-12-23T18:08:19Z |
Hello,

from the console prompt you call a command procedure simply with
ij> run 'myscript.sql';

but how can this be done from within a program?
I tried with Runtime.getRuntime().exec(...)

 public class RuntimeTst{
static public void main(String args[])
{ String command;
command ="cmd /C C:/Programme/Java/jre1.6.0_03/bin/java -cp C:/Programme/JavaDB/lib/derbytools.jar -Djdbc.drivers=org.apache.derby.jdbc.EmbeddedDriver org.apache.derby.tools.ij 'MyScript.sql'";
try
{ Process p= Runtime.getRuntime().exec(command);
System.out.println(p.waitFor());
}
catch(IOException e)
{ System.out.println (e);
}
System.out.println ("Done.");
}
}
but this doesn't work. Unfortunaltely there are no error messages. It seems that I can pass parameters to the called java vm, but not to the programs initiated by java.

Thanks for any ideas
and merry christmas (if it is of any concern to you)

Jörg
Updated on 2008-01-28T12:02:52Z at 2008-01-28T12:02:52Z by SystemAdmin
  • Stan
    Stan
    267 Posts

    Re: Runnimg a script (command file) from an application

    ‏2007-12-26T17:37:53Z  
    I have not done this myself but recommend you test the command line you are executing in an interactive shell first to make sure it works. I expect you will find that you need to add derby.jar to the classpath in addition to derbytools.jar. Once the command line executes properly in an interactive shell then try executing it within your program. I don't know how the 'cmd' works used in such a manner nor where STDOUT is routed to. IJ writes messages to STDOUT and STDERR and these appear to be getting lost since you are not seeing any output.
  • SystemAdmin
    SystemAdmin
    1525 Posts

    Re: Runnimg a script (command file) from an application

    ‏2007-12-27T13:12:59Z  
    • Stan
    • ‏2007-12-26T17:37:53Z
    I have not done this myself but recommend you test the command line you are executing in an interactive shell first to make sure it works. I expect you will find that you need to add derby.jar to the classpath in addition to derbytools.jar. Once the command line executes properly in an interactive shell then try executing it within your program. I don't know how the 'cmd' works used in such a manner nor where STDOUT is routed to. IJ writes messages to STDOUT and STDERR and these appear to be getting lost since you are not seeing any output.
    Thank you, Stan, for helping me again. Indeed, derby.jar is necessary. So I changed my code to
     command ="cmd /C C:\\Programs\\Java\\jre1.6.0_03\\bin java "+
    "-cp C:\\Programs\\JavaDB\\lib\\derby.jar;"+
    "C:\\Programs\\JavaDB\\lib\\derbytools.jar "+
    "org.apache.derby.tools.ij "+
    "run 'MyScript.sql'";
    but to no avail. I become more and more convinced that passing parameters to a "secondary level" is not possible.
    Updated on 2007-12-27T13:12:59Z at 2007-12-27T13:12:59Z by SystemAdmin
  • SystemAdmin
    SystemAdmin
    1525 Posts

    Re: Runnimg a script (command file) from an application

    ‏2007-12-27T15:07:57Z  
    Thank you, Stan, for helping me again. Indeed, derby.jar is necessary. So I changed my code to
     command ="cmd /C C:\\Programs\\Java\\jre1.6.0_03\\bin java "+
    "-cp C:\\Programs\\JavaDB\\lib\\derby.jar;"+
    "C:\\Programs\\JavaDB\\lib\\derbytools.jar "+
    "org.apache.derby.tools.ij "+
    "run 'MyScript.sql'";
    but to no avail. I become more and more convinced that passing parameters to a "secondary level" is not possible.
    It is possible!
     command ="cmd /C /Programs/Java/jre1.6.0_03/bin/java "+
    "-cp /Programs/JavaDB/lib/derby.jar;"+
    "/Programs/JavaDB/lib/derbytools.jar "+
    "org.apache.derby.tools.ij";
    try {
    Process p= Runtime.getRuntime().exec(command);
    OutputStream os= p.getOutputStream();
    os.write("run 'MyScript.sql';".getBytes());
    os.write("exit;".getBytes());
    os.flush();
    os.close();
    System.out.println(p.waitFor());
    }
  • Stan
    Stan
    267 Posts

    Re: Runnimg a script (command file) from an application

    ‏2007-12-27T17:37:00Z  
    It is possible!
     command ="cmd /C /Programs/Java/jre1.6.0_03/bin/java "+
    "-cp /Programs/JavaDB/lib/derby.jar;"+
    "/Programs/JavaDB/lib/derbytools.jar "+
    "org.apache.derby.tools.ij";
    try {
    Process p= Runtime.getRuntime().exec(command);
    OutputStream os= p.getOutputStream();
    os.write("run 'MyScript.sql';".getBytes());
    os.write("exit;".getBytes());
    os.flush();
    os.close();
    System.out.println(p.waitFor());
    }
    Hi Joerg2 -

    That's great. And thanks for sharing the solution here for others to reference when they need to do this. The example got me to look at the PROCESS class and I see there are methods for accessing the output and the error streams (STDOUT and STDERR) as well. This warning leads me to believe you should be managing/clearing these stream buffers to avoid possible problems.

    "..All its standard io (i.e. stdin, stdout, stderr) operations will be redirected to the parent process through three streams (getOutputStream(), getInputStream(), getErrorStream()). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock."
  • SystemAdmin
    SystemAdmin
    1525 Posts

    Re: Runnimg a script (command file) from an application

    ‏2007-12-29T00:50:33Z  
    • Stan
    • ‏2007-12-27T17:37:00Z
    Hi Joerg2 -

    That's great. And thanks for sharing the solution here for others to reference when they need to do this. The example got me to look at the PROCESS class and I see there are methods for accessing the output and the error streams (STDOUT and STDERR) as well. This warning leads me to believe you should be managing/clearing these stream buffers to avoid possible problems.

    "..All its standard io (i.e. stdin, stdout, stderr) operations will be redirected to the parent process through three streams (getOutputStream(), getInputStream(), getErrorStream()). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock."
    Hello Stan,
    yes, you're right. I was just so glad that it worked at all, that I posted immediately.
    Now here comes what I hope to be a complete demo:
     /*
    Demonstrates how to pass input to a programme launched by Runtime.getRuntime().
    Here we call "ij" (the CLI to the java db) and pass the command line
    "run 'MyScript.sql'".

    See Michael C. Daconta's article on
    http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1
    */

    import java.io.*;
    import java.util.*;

    public class PassInput {
    static public void main(String args[]) {
    String command;
    command ="cmd /C /Programs/Java/jre1.6.0_03/bin/java "+
    "-cp /Programs/JavaDB/lib/derby.jar;"+
    "/Programs/JavaDB/lib/derbytools.jar "+
    "org.apache.derby.tools.ij";
    try {
    Process p= Runtime.getRuntime().exec(command);
    // Any error message?
    StreamGobbler errorGobbler= new StreamGobbler(p.getErrorStream(),"ERROR");

    // Any output?
    StreamGobbler outputGobbler=
    new StreamGobbler(p.getInputStream(), "OUTPUT");
    errorGobbler.start();
    outputGobbler.start();
    OutputStream os= p.getOutputStream();
    os.write("run 'MyScript.sql'".getBytes());
    os.write("exit".getBytes());
    os.flush();
    os.close();
    // By convention, 0 indicates normal termination.
    System.out.println(p.waitFor());
    }
    catch(InterruptedException e) {
    System.out.println (e);
    }
    catch(IOException e) {
    System.out.println (e);
    }
    }

    static class StreamGobbler extends Thread {
    InputStream is;
    String type;

    StreamGobbler(InputStream is, String type) {
    this.is = is;
    this.type = type;
    }

    public void run() {
    try {
    BufferedReader br= new BufferedReader(new InputStreamReader(is));
    String line=null;
    while ( (line=br.readLine()) != null)
    System.out.println(type + "> " + line);
    }
    catch (IOException ioe) {
    ioe.printStackTrace();
    }
    }
    }

    }
    All the best

    Jörg
  • SystemAdmin
    SystemAdmin
    1525 Posts

    Re: Runnimg a script (command file) from an application

    ‏2008-01-03T04:42:44Z  
    Why not invoke an Ant script from Java using Ant's API?

    • KRo
  • SystemAdmin
    SystemAdmin
    1525 Posts

    Re: Runnimg a script (command file) from an application

    ‏2008-01-07T16:19:35Z  
    Why not invoke an Ant script from Java using Ant's API?

    • KRo
    I haven't used ANT so far; the only thing I know about it is that it's a MAKE utility. But according to your proposal it seems that it's much more. Do you mean you can tell ANT to run any application with a partiucular input to that application?
  • SystemAdmin
    SystemAdmin
    1525 Posts

    Re: Runnimg a script (command file) from an application

    ‏2008-01-12T07:21:00Z  
    I haven't used ANT so far; the only thing I know about it is that it's a MAKE utility. But according to your proposal it seems that it's much more. Do you mean you can tell ANT to run any application with a partiucular input to that application?
    Yes, Ant is usually used as a a Make utility for Java.

    But, Ant provides an SDK / API that can be used to spawn an Ant XML script from a Java application (and the Ant XML script could contain a target that forks a cshrc or cmd file or forks a Java application...)

    You can either, as my example above shows, execute an already existing (canned) Ant XML script (from your Java application) or you can build up an Ant "project" and "target"s - in either case using the provided SDK / API (jars in Ant's distributed lib).

    Anyway, the nice thing about Ant is that it's a portable scripting language (which is nice when you develop on Windows and deliver to a Unix flavor).

    In addition, when spawning an Ant XML script from a Java application using Ant's SDK / API, you can capture the script's logging to a log file.

    Just as you can create a target in an Ant script to execute a Test Java application or to execute a cshrc or cmd script - you can do the same using Ant's SDK / API from a Java application.

    So, I passed arguments into the XML script by setting properties that the Ant script (expects) reads.

    • KRo
  • SystemAdmin
    SystemAdmin
    1525 Posts

    Re: Runnimg a script (command file) from an application

    ‏2008-01-12T07:36:57Z  
    Yes, Ant is usually used as a a Make utility for Java.

    But, Ant provides an SDK / API that can be used to spawn an Ant XML script from a Java application (and the Ant XML script could contain a target that forks a cshrc or cmd file or forks a Java application...)

    You can either, as my example above shows, execute an already existing (canned) Ant XML script (from your Java application) or you can build up an Ant "project" and "target"s - in either case using the provided SDK / API (jars in Ant's distributed lib).

    Anyway, the nice thing about Ant is that it's a portable scripting language (which is nice when you develop on Windows and deliver to a Unix flavor).

    In addition, when spawning an Ant XML script from a Java application using Ant's SDK / API, you can capture the script's logging to a log file.

    Just as you can create a target in an Ant script to execute a Test Java application or to execute a cshrc or cmd script - you can do the same using Ant's SDK / API from a Java application.

    So, I passed arguments into the XML script by setting properties that the Ant script (expects) reads.

    • KRo
    Oops - maybe the attached scripts help :) Sorry I forgot to include them.

    Anyway, the Java application executes the "demo" target in the Demo.xml Ant script.

    Which in turn executes the Demo.cmd windows script.

    http://I could have just as easily invoked the Derby ij executable from the Demo.xml script instead of invoking the Demo.cmd file.

    -KRo
  • SystemAdmin
    SystemAdmin
    1525 Posts

    Re: Runnimg a script (command file) from an application

    ‏2008-01-12T07:49:23Z  
    Oops - maybe the attached scripts help :) Sorry I forgot to include them.

    Anyway, the Java application executes the "demo" target in the Demo.xml Ant script.

    Which in turn executes the Demo.cmd windows script.

    http://I could have just as easily invoked the Derby ij executable from the Demo.xml script instead of invoking the Demo.cmd file.

    -KRo
    
    ... And an example Ant target that creates a Derby database...


    <!-- Build a database -->
    <target name="create-db"
    description="Builds the Invoice / Lineitem database.">

    <delete dir="${db.dir}/${dbname}"/>
    <mkdir dir="${db.dir}/${dbname}"/>

    <!-- Give the database some structure -->
    <java classname="org.apache.derby.tools.ij"
    classpathref="run.classpath"
    fork="Yes" jvm="${java.home}/bin/java">
    <jvmarg value="-Xms128m" />
    <jvmarg value="-Xmx128m" />
    <jvmarg value="-Dlog4j.config=log4j.xml" />
    <jvmarg value="-Dij.connection.${dbname}=${dburl}" />
    <jvmarg value="-Dij.driver=${dbdriver}" />
    <jvmarg value="-Dij.user=${dbuser}" />
    <jvmarg value="-Dij.password=${dbpasswd}" />

    <arg value="${sql.scripts}/create_database.sql" />
    </java>
    </target>


    where run.classpath is something like:

    <path id="run.classpath">
    <fileset dir="${java.lib}"> <include name=" */.jar"/> </fileset>
    <fileset dir="${log4j.lib}"> <include name=" */.jar"/> </fileset>
    <fileset dir="${mail.lib}"> <include name=" */.jar"/> </fileset>
    <fileset dir="${jaf.lib}"> <include name=" */.jar"/> </fileset>
    <fileset dir="${db.lib}"> <include name=" */.jar"/> </fileset>
    <pathelement location="${src.jar}"/>
    <pathelement location="${test.jar}"/>
    <pathelement path="${etc}"/>
    <pathelement path="${resources}"/>
    </path>

    You'll need to look at Ant's documentation after you've downloaded its distribution.

    <ul> <li>KRo</li> </ul>
  • SystemAdmin
    SystemAdmin
    1525 Posts

    Re: Runnimg a script (command file) from an application

    ‏2008-01-28T12:02:52Z  
    
    ... And an example Ant target that creates a Derby database...


    <!-- Build a database -->
    <target name="create-db"
    description="Builds the Invoice / Lineitem database.">

    <delete dir="${db.dir}/${dbname}"/>
    <mkdir dir="${db.dir}/${dbname}"/>

    <!-- Give the database some structure -->
    <java classname="org.apache.derby.tools.ij"
    classpathref="run.classpath"
    fork="Yes" jvm="${java.home}/bin/java">
    <jvmarg value="-Xms128m" />
    <jvmarg value="-Xmx128m" />
    <jvmarg value="-Dlog4j.config=log4j.xml" />
    <jvmarg value="-Dij.connection.${dbname}=${dburl}" />
    <jvmarg value="-Dij.driver=${dbdriver}" />
    <jvmarg value="-Dij.user=${dbuser}" />
    <jvmarg value="-Dij.password=${dbpasswd}" />

    <arg value="${sql.scripts}/create_database.sql" />
    </java>
    </target>


    where run.classpath is something like:

    <path id="run.classpath">
    <fileset dir="${java.lib}"> <include name=" */.jar"/> </fileset>
    <fileset dir="${log4j.lib}"> <include name=" */.jar"/> </fileset>
    <fileset dir="${mail.lib}"> <include name=" */.jar"/> </fileset>
    <fileset dir="${jaf.lib}"> <include name=" */.jar"/> </fileset>
    <fileset dir="${db.lib}"> <include name=" */.jar"/> </fileset>
    <pathelement location="${src.jar}"/>
    <pathelement location="${test.jar}"/>
    <pathelement path="${etc}"/>
    <pathelement path="${resources}"/>
    </path>

    You'll need to look at Ant's documentation after you've downloaded its distribution.

    <ul> <li>KRo</li> </ul>
    Hello KRo,

    thank you very much for all the code. I'm awfully busy at the time and still haven't tried to implement it. But I will do this as soon as I can.

    Thank's again

    Jörg