New version is available You are viewing the documentation for JxBrowser 6 which is not supported since December 2019. Go to the current documentation.
List icon Contents

This guide describes how to access JavaScript on a loaded web page, execute JavaScript code, inject Java objects to call Java from JavaScript, etc.

Executing JavaScript

To execute JavaScript code asynchronously, without blocking current thread execution until the code is executed and ignore return value, use the Browser.executeJavaScript(String javaScript) method. This method tells Chromium engine to execute the given JavaScript code asynchronously. The return value of JavaScript code execution is ignored.

The following code updates document.title property with “My title” value:

browser.executeJavaScript("document.title = 'My title';");

Executing JavaScript and Return Value

To execute JavaScript code and return value use the Browser.executeJavaScriptAndReturnValue(String javaScript) method. This method blocks current thread execution and waits until code is executed. The result of execution is stored in JSValue object.

The following code updates document.title property with “My title” value and returns JSValue object with string value that represents document.title value:

JSValue title = browser.executeJavaScriptAndReturnValue(
        "document.title = 'My title'; document.title");
System.out.println("title = " + title.getStringValue());

Accessing JavaScript Objects

You can access JavaScript objects on the loaded web page using the Browser.executeJavaScriptAndReturnValue(String javaScript) method. If return value represents JavaScript object, then JSValue will contain JSObject instance that represents Java wrapper for JavaScript object. JSObject class provides functionality that allows working with JavaScript object properties and calling its functions.

Getting Properties

To access JavaScript object property use the JSObject.getProperty(String name) method. The following code demonstrates how to get value of the document.title property:

JSValue document = browser.executeJavaScriptAndReturnValue("document");
JSValue titleValue = document.asObject().getProperty("title");
String title = titleValue.getStringValue();

Setting Properties

To modify JavaScript object property with specified value use the JSObject.setProperty(String name, Object value) method. The following code demonstrates how to modify document.title property with “My title” value:

JSValue document = browser.executeJavaScriptAndReturnValue("document");
document.asObject().setProperty("title", "My title");

Calling Functions

JavaScript object property can represent a function. You can invoke JavaScript object function using the following approach:

JSValue document = browser.executeJavaScriptAndReturnValue("document");
JSValue write = document.asObject().getProperty("write");
write.asFunction().invoke(document.asObject(), "<html><body>Hello</body></html>");

Since JxBrowser 6.9, you can also invoke JavaScript function asynchronously and access the result of the invocation through the Future<JSValue> object:

JSValue document = browser.executeJavaScriptAndReturnValue("document");
JSValue async = document.asObject().getProperty("asyncFunc");
Future<JSValue> asyncResult = 
        async.asFunction().invokeAsync(document.asObject(), "Hello World Async!");
String result = asyncResult.get().asString().getStringValue();

Working With Arrays

JavaScript Java Bridge API provides JSArray class that represents a wrapper for JavaScript array object. If JavaScript returns an array to Java code, the array value will be represented in Java code as JSArray object. For example:

JSValue result = browser.executeJavaScriptAndReturnValue("[1, 'test', 3]");
JSArray array = result.asArray();

In the example above JavaScript code returns an array with three items (1, ’test’, 3) to Java code. The JSValue can be cast to JSArray type to work with JavaScript array. Using JSArray class you can get length of the array, access array items, and modify JavaScript array with new items.

JSArray points to existing JavaScript array on the loaded web page. If the web page was reloaded or unloaded, JSArray object will point to an invalid JavaScript array that was disposed during unloading the web page. If you try to use this JSArray instance, the IllegalStateException error will be thrown.

Getting Array Length

To get the array length use the JSArray.length() method. For example:

JSValue result = browser.executeJavaScriptAndReturnValue("[1, 'test', 3]");
JSArray array = result.asArray();
assert array.length() == 3;

Getting Array Items

To access the array item at specific index use the JSArray.get(int index) method. The index cannot be negative. It can be more than array length. In this case the “undefined” value will be returned. For example:

assert array.get(0).asNumber().getInteger() == 1;
assert array.get(1).getStringValue().equals("test");
assert array.get(2).asNumber().getInteger() == 3;
assert array.get(100).isUndefined();

Setting Array Items

You can modify existing array items or add new items using the JSArray.set(int index, Object value) method. The method returns a boolean value that indicates whether the given value was successfully inserted into the array. You can insert new values at the index more than array length. In this case the size of the array will be increased, the new item will be inserted at the given position, all items between the latest valid array element and the new one will be filled with “undefined” values.

assert array.set(0, "String value");
assert array.set(100, 123);

Java to JavaScript Types Conversion

JavaScript and Java work with different primitive types. JxBrowser implements automatic types conversion from Java to JavaScript types. Here’s how Java objects will be converted to their JavaScript equivalents by JxBrowser:

  • Java double, float, long, int, short, byte, java.lang.Double, java.lang.Float, java.lang.Long, java.lang.Integer, java.lang.Short, java.lang.Byte are converted to JavaScript Number
  • Java boolean, java.lang.Boolean are converted to JavaScript Boolean
  • java.lang.String to JavaScript String
  • Java null to JavaScript null
  • com.teamdev.jxbrowser.chromium.JSObject to Object
  • com.teamdev.jxbrowser.chromium.JSArray to Array
  • com.teamdev.jxbrowser.chromium.JSFunction to Function

Calling Java from JavaScript

JavaScript Java Bridge API allows injecting Java objects into JavaScript code. This is a powerful feature that allows accessing Java functionality from JavaScript.

To access JavaScript and inject Java object, make sure that web page is loaded completely and JavaScript support is enabled. If you inject/register Java object and then load web page, all registered Java objects will be destroyed and will not be available in JavaScript of the loaded web page.

Injecting Java Objects

To inject Java object into JavaScript you must associate the Java object with specified property of a JavaScript object. For example, you can add a new java property to global window JavaScript object (other objects would work as well) and associate this property with Java object using the following code:

JSValue window = browser.executeJavaScriptAndReturnValue("window");
window.asObject().setProperty("java", new JavaObject());

To inject Java object into JavaScript code, we recommend that you use the following approach:

browser.addScriptContextListener(new ScriptContextAdapter() {
    @Override
    public void onScriptContextCreated(ScriptContextEvent event) {
        Browser browser = event.getBrowser();
        JSValue window = browser.executeJavaScriptAndReturnValue("window");
        window.asObject().setProperty("java", new JavaObject());
    }
});

Implementation of JavaObject can be the following:

public static class JavaObject {
    public void print(String message) {
        System.out.println(message);
    }
}

Make sure that you inject Java object which class/interface is marked as public. Only public classes can be registered and accessed from JavaScript.

Now JavaScript code can invoke JavaObject public methods:

window.java.print('Hello Java!');

JavaScript code can access/invoke only public methods of registered Java object.

Getting Java Object from JSValue

You can inject Java object into JavaScript by setting it as a property value for existing JavaScript object:

JSValue window = browser.executeJavaScriptAndReturnValue("window");
window.asObject().setProperty("java", new JavaObject());

If you read the property value in Java code, then you can extract Java object associated with this JavaScript value:

JSValue value = window.asObject().getProperty("java");
if (value.isJavaObject()) {
    JavaObject object = (JavaObject) value.asJavaObject();
}

How It Works

When JavaScript calls a public method of a registered Java object, JavaScript parameters are automatically converted to corresponding Java objects/primitive values by JxBrowser.

If JxBrowser cannot convert passed JavaScript values or find a method with appropriate signature, JavaScript error will be thrown.

If registered Java object has several methods with same name and number of parameters, but different parameter types, JavaScript will invoke the first method declared in Java class. For example, if you register the following Java object:

public class JavaObject {
    public void doAction(int arg1, double arg2) {}
    public void doAction(double arg1, int arg2) {}
    public void doAction(double arg1, double arg2) {}
}

JavaScript to Java Types Conversion

JavaScript and Java work with different primitive types. JxBrowser implements automatic types conversion from JavaScript to Java types. Here’s how JavaScript objects will be converted to their Java equivalents by JxBrowser:

  • JavaScript Number will be converted to Java double, float, long, int, short, byte, java.lang.Double, java.lang.Float, java.lang.Long, java.lang.Integer, java.lang.Short, java.lang.Byte
  • JavaScript Boolean will be converted to Java boolean, java.lang.Boolean
  • JavaScript String to java.lang.String
  • null to null
  • Object to com.teamdev.jxbrowser.chromium.JSObject
  • Array to com.teamdev.jxbrowser.chromium.JSArray
  • Function to com.teamdev.jxbrowser.chromium.JSFunction

Console Messages

JxBrowser API allows receiving all output messages sent to the Web Console via console.log() JavaScript function. You can listen to JavaScript Web Console messages with different levels: DEBUG, LOG, WARNING and ERROR. To start receiving Web Console messages you must register ConsoleListener for a specified Browser instance. For example:

browser.addConsoleListener(new ConsoleListener() {
    public void onMessage(ConsoleEvent event) {
        System.out.println("Message: " + event.getMessage());
    }
});

JSON

JxBrowser JavaScript Java Bridge API allows passing a string that represents JSON from Java side to JavaScript. On JavaScript side this JSON string will be parsed and converted to appropriate JavaScript object/objects. The following simple example demonstrates how to associate JSON with specific property of window JavaScript object:

JSValue window = browser.executeJavaScriptAndReturnValue("window");
window.asObject().setProperty("myObject", new JSONString("[123, \"Hello\"]"));

In the code above the "[123, \"Hello\"]" JSON string is associated with the window.myObject property. This JSON string will be converted to appropriate JavaScript object. In this case it will be converted to Array. The following JavaScript code shows how to work with the window.myObject property:

<script>
var length = window.myObject.length;
var numberValue = window.myObject[0];
var stringValue = window.myObject[1];
</script>

If you set JSONString with string value that doesn’t represent JSON, you will get JavaScript error.

JavaScript Context

When web page is loaded, Chromium engine creates JavaScript Context instance. This instance represents context in which all JavaScript code is executed. The JavaScript Context instance is created when web page is loaded completely, but JavaScript code on it hasn’t been executed yet. To get notifications about JavaScript Context creation use the ScriptContextListener.onScriptContextCreated(ScriptContextEvent event) event.

When web page is unloaded because of loading another web page or reloading existing one, Chromium engine destroys JavaScript Context and disposes all JavaScript objects running in scope of this context. To get notifications about JavaScript Context disposal use the ScriptContextListener.onScriptContextDestroyed(ScriptContextEvent event) event.

You might want to execute some JavaScript code before any other JavaScript on the loaded web page is executed. For example, to inject your own JavaScript objects/functions/properties. JxBrowser API provides functionality that allows receiving notifications before JavaScript code is executed on the loaded web page. To get such notification you must register ScriptContextListener and override its onScriptContextCreated(ScriptContextEvent event) method. Inside this method you can execute your JavaScript code. It will be executed before any other JavaScript on the loaded web page is executed. For example:

browser.addScriptContextListener(new ScriptContextAdapter() {
    @Override
    public void onScriptContextCreated(ScriptContextEvent event) {
        Browser browser = event.getBrowser();
        // Access and modify document.title property before any other
        // JavaScript on the loaded web page has been executed.
        JSValue document = browser.executeJavaScriptAndReturnValue("document");
        document.asObject().setProperty("title", "My title");
    }
});

@JsAccessible

JxBrowser provides functionality that allows injecting Java object into JavaScript code. By default, all public fields and methods of the injected Java object is accessible from JavaScript, so JavaScript code can access them. To tell JavaScript code what public fields/methods of the injected Java object can be accessible from JavaScript you can use the @JSAccessible annotation. If you need to let JavaScript code to access only specific public fields/methods, then you must mark them with the @JSAccessible annotation. For example:

public class JavaObject {
    @JSAccessible
    public String accessibleField;
    public String nonAccessibleField;
    
    public void doAction() {
    }
    
    @JSAccessible
    public void doAccessibleAction() {
    }
}

If you inject the JavaObject into JavaScript code, then JavaScript will be able to access only the accessibleField public field and the doAccessibleAction() public method. If JavaScript tries to access other public fields or methods, an exception in JavaScript code will be thrown.