3

I want to run one HTML page with JavaScript and want to access its output in Java. Is there any way to access JavaScript console output of browser in Java code?

First, I tried executing JavaScript using Java (htmlunit) but it gave an error due to jQuery in the JS.

The JS function which I need to execute uses associated HTML elements, and that's why I preferred to save the page, add my JS to that page, and run it locally. I can then see the output on the JavaScript console, and now I want to get that output in Java code for further processing.

tckmn
  • 57,719
  • 27
  • 114
  • 156
Pradeep
  • 6,303
  • 9
  • 36
  • 60
  • Is the Java executing the Javascript? Or do you want to link to a js file and the java logs all the `console.log` outputs? You'll have to be more specific... – jeremy Sep 08 '12 at 20:16
  • 1
    One does not run an HTML page. You might want to look into V8 or another Javascript engine if you want to be able to access its output. – Waleed Khan Sep 08 '12 at 20:36
  • but problem is , i can't run javascript alone as it uses some dynamic html elements from web page , am i be able to execute them(js+html) using these engines ? – Pradeep Sep 08 '12 at 20:39
  • Are you trying to write tests for your JavaScript code? You might want to look at a web browser testing framework like Selenium or Watir. – Daniel Pryden Sep 08 '12 at 20:47
  • No i am not running tests, i just want to take output from ofuscated java script by calling java script method – Pradeep Sep 08 '12 at 20:50

5 Answers5

2

Thanks all for quick responses, we solved the problem using Greasemonkey and firefox. Instead of console we are writing output to the file using one servlet. The installed js inside Greasemokey execute js method and output from that is passed over one Servlet(locally running) get request and it writes input to file and we can use that file in java, Inside file write code just added synchronized block in case multiple links opened by Greasemonkey :D

Pradeep
  • 6,303
  • 9
  • 36
  • 60
1

Try Selenium to access the page. It opens a real browser instance and clicks (solves the jquery issues) and should also be able to fetch console.log.

Maybe this list of JS unit test tools might help you as well: JavaScript unit test tools for TDD

Community
  • 1
  • 1
Peter Ilfrich
  • 3,727
  • 3
  • 31
  • 35
1

Ofcourse. Read slowly:

One brilliant thought I got is, since you are running java, why not make it a server that will listen on a specific port? You can easily do that.

Once you have got a simple thread listening on a port, in what ever javascript code your are executing, at the end when you want to log some variables to console, send an ajax call to this local server with all the data you want to send to java.

Once you get a request in server, pass the data to other thread and yield.

Even if it looks complex, seems like a pretty feasible solution to me.

Lesmana
  • 25,663
  • 9
  • 82
  • 87
Prasanth
  • 5,230
  • 2
  • 29
  • 61
1

I liked Prasanth's suggestion, and it worked well for me. Here's my code.

RCP:

logger = ...
private void startJSConsole() {
        jsConsoleJob = new Job("JS Console Server") {

            @Override
            protected IStatus run(IProgressMonitor monitor) {
                Socket connectionSocket = null;
                try {
                    jsSocket = new ServerSocket(6789);
                    while (!monitor.isCanceled()) {
                        connectionSocket = jsSocket.accept();
                        readSocketData(connectionSocket);
                    }
                } catch (IOException e) {
                    if (!"Socket closed".equals(e.getMessage())) {
                        logger.logError("Unable to open or read from Javascript console server socket", e);
                    }
                    return Status.CANCEL_STATUS;
                } finally {
                    try {
                        if (jsSocket != null) {
                            jsSocket.close();
                        }
                        if (connectionSocket != null) {
                            connectionSocket.close();
                        }
                    } catch (IOException e) {
                        //pass
                    }
                }
                return Status.OK_STATUS;
            }
        };
        jsConsoleJob.setUser(false);
        jsConsoleJob.setSystem(true);
        jsConsoleJob.schedule();
    }

    //I copied this code from here: http://stackoverflow.com/a/21729100/2036650
    private void readSocketData(Socket connectionSocket) {
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
            // read request
            String line;
            line = in.readLine();
            StringBuilder raw = new StringBuilder();
            raw.append("" + line);
            boolean isPost = line.startsWith("POST");
            int contentLength = 0;
            while (!(line = in.readLine()).equals("")) {
                raw.append('\n' + line);
                if (isPost) {
                    final String contentHeader = "Content-Length: ";
                    if (line.startsWith(contentHeader)) {
                        contentLength = Integer.parseInt(line.substring(contentHeader.length()));
                    }
                }
            }
            StringBuilder body = new StringBuilder();
            if (isPost) {
                int c = 0;
                for (int i = 0; i < contentLength; i++) {
                    c = in.read();
                    body.append((char) c);
                }
            }
            raw.append(body.toString());
            System.err.println("JS: " + body.toString());
            connectionSocket.close();

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

Javascript:

<html>
      <head>
    ...
    <script>
        var global = global || {};
        global.consoleLog = function(msg) {
            var xhttp = new XMLHttpRequest();
            xhttp.open("POST", "http://localhost:6789", true);
            xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            xhttp.send(msg);
        }
    </script>
    <script src="js/sigplot-minimized.js"></script>
</head>
<body>
...
</body>
</html>

Then from anywhere in the Javascript code:

global.consoleLog(logMessage);
MidnightJava
  • 1,927
  • 2
  • 18
  • 38
0

For to complete @MinuitJava answer, you can also add a listener on error events.

window.addEventListener('error', function (e) {
  console.log(e.type +  " : " + e.message + "\n");
  console.log(e);

  // var xhttp = new XMLHttpRequest();
  // code . . .
});

MDN doc: Window: error event

JTorleon
  • 108
  • 1
  • 9