0

I am running something like this

String[] reassignCmdArgs =
    { "--reassignment-json-file=" + jsonFile,
      "--zookeeper=" + zkConnect,
      "--throttle=" + (throttle <= 0 ? "1000000000" : throttle),
      "--execute" };
 ReassignPartitionsCommand.main(reassignCmdArgs);

The ReassignPartitionsCommand has some println statements and I would like to capture those here.

How can this be done?

EDIT: My current workaround is below. I'm looking for something that does not start another process

   String[] reassignCmdArgs =
          { "--reassignment-json-file=" + jsonFile,
            "--zookeeper=" + zkConnect,
            "--throttle=" + (throttle <= 0 ? "1000000000" : throttle),
            "--execute" };
      System.out.println("Calling ReassignPartitionsCommand with args: " +
                         Arrays.toString(reassignCmdArgs));
      StringBuilder result = new StringBuilder();
      try {
        ClassLoader cl = ClassLoader.getSystemClassLoader();

        URL[] urls = ((URLClassLoader) cl).getURLs();
        ProcessBuilder pb = new ProcessBuilder();
        pb.redirectErrorStream(true);
        String classPath = Arrays.asList(urls)
                                 .stream()
                                 .map(URL::getFile)
                                 .collect(Collectors.joining(";"));
        String[] args = new String[4 + reassignCmdArgs.length];
        args[0] = "java";
        args[1] = "-cp";
        args[2] = classPath;
        args[3] = ReassignPartitionsCommand.class.getName();
        for (int i = 4; i < 4 + reassignCmdArgs.length; i++) {
          args[i] = reassignCmdArgs[i - 4];
        }
        pb.command(args);
        System.out.println("Calling process with args: " + Arrays.toString(args));
        Process p = pb.start();
        p.waitFor();  // wait for process to finish

        BufferedReader bri =
            new BufferedReader(new InputStreamReader(p.getInputStream()));

        String line;
        while ((line = bri.readLine()) != null) {
          result.append(line + "\n");
        }
      } catch (Exception e) {
        result = new StringBuilder("Problem running as another process");
        ReassignPartitionsCommand.main(reassignCmdArgs);
      }
Ansel Zandegran
  • 636
  • 8
  • 18
  • what do you mean with "capture"? – Lino Jan 23 '19 at 15:57
  • as a String so that I can send it as a REST response – Ansel Zandegran Jan 23 '19 at 15:58
  • Maybe this helps: https://stackoverflow.com/questions/18029609/how-can-we-read-or-use-the-contents-of-outputstream, the answer is: you can't. Though `System.out` may be an exception, and there is a way to read from it – Lino Jan 23 '19 at 16:03

1 Answers1

0

You should look at ProcessBuilder; you can specify where the output goes e.g. pb.redirectOutput(Redirect.appendTo(log)). Then simply read the output from the file you specify.

  • I'm currently doing that (See edit in question) which starts another process. I'm wondering if there is any other way. – Ansel Zandegran Jan 23 '19 at 17:44
  • How about spinning off a thread then? Have the new thread append to a string instead of printing to standard out, and return this string containing the output using Future (https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html). Or do you not want to use threads either? – MadSpaceBetweenStars Jan 23 '19 at 18:22
  • I don't have control over the class I'm running. So I cannot change printing to stdout – Ansel Zandegran Jan 24 '19 at 09:15