2

I have this program that I am writing that has this method that is supposed to execute a program but does not do anything. The method in question is as follows:

public void findCC_Data(List<String> l7) {

         StringBuffer output = new StringBuffer();

         Process p;
         try {
            for(String sql_file: l7) {
                String command = "cleartool describe " + sql_file;
                p = Runtime.getRuntime().exec(command);
                System.out.println("Executing: " + command);
                p.waitFor();
                BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    output.append(line + "\n");
                }
                if (reader.readLine() == null) {
                    System.out.println("'reader.readLine()' is equal to null");
                }


            }

        } catch(Exception e) {
            e.printStackTrace();
        }

        System.out.println(output.toString());



     }

Does anyone know why the command does not do anything and the reader.readLine() method always returns null?

I am following a tutorial but using the cleartool program instead of the ping program basically. The tutorial is at this URL:https://www.mkyong.com/java/how-to-execute-shell-command-from-java/

Solution I had the System.out.println(output.toString()) print statement outside of the for loop instead of inside it. Now when I move the SOP statement inside the loop it prints a million plus lines of information on ClearCase version control stuff. To fix put the SOP with the output.toString() inside the loop in the broken code above.

user3808269
  • 1,321
  • 3
  • 21
  • 40
  • What version of ClearCase are you running? On which OS on the client side? On the server side? Are you running your Java program in a dynamic view? – VonC Aug 22 '16 at 17:44
  • p is null. I think you want assign return type of Runtime.getRuntime().exec(command) to p. – omkar sirra Aug 22 '16 at 17:44
  • @omkarsirra Thank-you for pointing that out. I forgot to add that assignment back in the code but did just now. Either way nothing is returned... I removed the assignment to 'p' because it was not doing anything but went ahead and added it back so somone could possibly help debug it. I got this idiom from here: https://www.mkyong.com/java/how-to-execute-shell-command-from-java/ – user3808269 Aug 22 '16 at 17:48
  • @VonC I am not sure about the version of ClearCase. I am running Windows on the client side and I do not know the OS ClearCase is running on for the server. – user3808269 Aug 22 '16 at 17:50
  • @user3870315 `cleartool -ver` or `cleartool -verall` should tell you about the version. But are you in a dynamic view? – VonC Aug 22 '16 at 17:51
  • Yes I run the command from a dynamic view. The version is basically 8 dot something. – user3808269 Aug 22 '16 at 18:02
  • By the way, it's generally not a good idea to read a process's output after waiting for it to terminate. Once the process has terminated, its output is kept in a limited-size buffer owned by the Java Process object. If the process produces a lot of output, you'll encounter problems. – Klitos Kyriacou Aug 22 '16 at 18:51
  • @KlitosKyriacou So I should not call the `waitFor()` method on the Process reference? – user3808269 Aug 22 '16 at 18:56
  • You should call waitFor() to make sure the subprocess exits. As your case is simple, you could just move the waitFor() to after the read loop. For larger applications, people use other techniques, such as reading the process output in another thread. – Klitos Kyriacou Aug 22 '16 at 18:59
  • After removing the `waitFor()` method and re-compiling the program does not work and null is still returned by `reader.readLine()`. I could try moving this method, `waitFor()` to after the "read loop". – user3808269 Aug 22 '16 at 19:02
  • I didn't say that moving the waitFor() call would solve your problem. It was just a "by the way". Your problem is caused by something else. – Klitos Kyriacou Aug 22 '16 at 22:04
  • Why don't you call getErrorStream() and check the status code returned from the process when you call waitFor()? – Klitos Kyriacou Aug 22 '16 at 22:12
  • That is a good idea. It helped me look at my entire algorithm also which helped me see the larger picture and fix the problem. :) – user3808269 Aug 22 '16 at 23:23

2 Answers2

2

One possibility for a program in (java, python, bash, ...) to do nothing with ClearCase command is if said cleartool command is run within a dynamic view which has been set (cleartool setview).

As I explained before, the cleartool setview command opens a subshell in which commands are supposed to be run, which is not the case here (the java program runs in the main shell)

The other possible cause is that you are reading stdout, not stderr, and somehow this commands returns an error (maybe its execution path is not correct).

thought it would not matter anyway because a method I call before the one in question is supposed to change directories to the dynamic view. It appears it does not work as expected though because the result of the cleartool pwd command is just my desktop

Yes, each cleartool command operates in its own shell. You must set the right execution folder for each Java Process run("cleartool ...") commands, in order for those cleartool commands to start in the right folder.
See "execute file from defined directory with Runtime.getRuntime().exec", although the answer is a bit dated, and that might have changed with Java8.


As the OP noted, the output.toString() print statement was outside of the for loop instead of inside said loop.
You can see additional example in:

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • I tried setting the view like so, `//try to start a view into ClearCase Process r = Runtime.getRuntime().exec("cleartool startview dynamic_view_name");` but the program just shuts down here and the 'r' variable is null. – user3808269 Aug 22 '16 at 18:03
  • I just read more of your post that is hyperlinked from, "As I explained before". I could try using the `exec` option so that another program is called from there. 0_o – user3808269 Aug 22 '16 at 18:09
  • @user3870315 That should not apply to your case, as it is for dynamic view on Unix, not Windows. You need to make sure of your `cleartool pwd` and `cleartool pwv`: try those commands through Java and see if you get any result. – VonC Aug 22 '16 at 18:19
  • Ah, I am glad it does not apply because it was getting very complex in Java. :) I thought it would not matter anyway because a method I call before the one in question is supposed to change directories to the dynamic view. It appears it does not work as expected though because the result of the `cleartool pwd` command is just my desktop. :/ Thank-you for the help. Maybe we can get this to run correctly. – user3808269 Aug 22 '16 at 18:24
  • I tried issuing the `cleartool setview` command but I receive the error: `cleartool: Error: Unrecognized command: "setview"`. – user3808269 Aug 22 '16 at 18:54
  • @user3870315 The all point of my past answer if to warn users to never use cleartool setview. You don't need it here. You can execute a Java process in a specific folder though, so try that, and check if it works with cleartool pwd. – VonC Aug 22 '16 at 19:11
  • If I specify the directory to run the program in as the 3rd argument to the `exec()` method the program runs in the correct directory but the output is still `null` for `reader.readLine()`. :/ Thank-you for adding more to the answer though. I did not think to call exec like this before. – user3808269 Aug 22 '16 at 20:15
  • Output of what though? Cleartool describe? Or cleartool pwd? – VonC Aug 22 '16 at 20:17
  • But would a cleartool pwd confirm you are in the right path? – VonC Aug 22 '16 at 20:23
  • I ran the program with 'cleartool pwd' as the command for exec and it printed the same thing for null references but after every thing in the loop ran it printed the correct working directory for the same number of times as what was in the loop. I have no idea why the loop ran twice. Maybe some of this output was stuck in some buffer or something...So it printed the null output for the 297 sql files i have in my arraylist then after all that ran it printed out the correct working directory 297 times. – user3808269 Aug 22 '16 at 20:55
  • My problem must be that my view to ClearCase is a dynamic view. – user3808269 Aug 22 '16 at 21:19
  • Yes it must be started, and it's vob mounted – VonC Aug 22 '16 at 21:47
  • I think the view is started and mounted on one of my drives, X for example. Still the 'cleartool describe' command does not work. Frustrating... – user3808269 Aug 22 '16 at 21:59
  • 1
    @user3870315 do not use some shortcut. Always test at first in the full dynamic view path: M:\myview\myvob\... – VonC Aug 22 '16 at 22:00
  • It works if I specify the full path for a single file. I think it maybe a problem with escape characters on the files paths with single backslashes that are loaded from a file. – user3808269 Aug 22 '16 at 22:16
  • I figured it out!. I needed to put the `output.toString()` in the loop not outside of the loop. – user3808269 Aug 22 '16 at 22:45
  • @user3870315 Good job. I have included your comment in the answer for more visibility, and have added additional links to illustrate the stdout capture process. – VonC Aug 23 '16 at 06:32
0

Run your command inside a child shell using sh command and redirect the output to nohup, refer nohup and sh command.

once you have the command executed i.e. "nohup cleartool describe " + sql_file; you can get the error or details from nohup.out file and confirm if there is an issue in executing the command.

Amit Mahajan
  • 895
  • 6
  • 34