Runtime API

Alessandro Pignotti edited this page Nov 23, 2018 · 33 revisions

CheerpJ exposes a simple API to interact with a Java application converted to JavaScript. This API can be use to initialise CheerpJ, invoke Java methods, convert data and to enable/disable certain debugging features.

Integrating an application converted with CheerpJ in a HTML page

A basic HTML file to load a CheerpJ application will look as follows:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>CheerpJ test</title>
    <script src="https://cjrtnc.leaningtech.com/latest/loader.js"></script>
  </head>
  <body>
  </body>
  <script>
      cheerpjInit();
      cheerpjCreateDisplay(800,600);
      cheerpjRunMain("AppClass", "/app/my_application_archive.jar:/app/my_dependency_archive.jar"); 
  </script>
</html>

Loading the CheerpJ runtime

To load the most recent runtime, use the following link:

<script src="https://cjrtnc.leaningtech.com/latest/loader.js"></script>

More in general, you can use this line:

<script src="https://cjrtnc.leaningtech.com/version/loader.js"></script>

where version is the specific runtime version you want to link to.

cheerpjInit

cheerpjInit must be called once in the page to setup and initialise the CheerpJ runtime environment. cheerpjInit accepts an optional object argument which can be used to set options.

This method is to be invoked as follows: cheerpjInit({option:"value"});

At this time only the status, listener and logCanvasUpdates options are available.

status

This option determines the level of verbosity of CheerpJ in reporting status updates.

  • "default": Enables status reporting during initialization and short-lived "Loading..." messages every time new runtime code is being downloaded.
  • "splash": Enabled status reporting only during initialization. There will be no feedback after the first window is shown on screen.
  • "none": Disable all status reporting.

listener

An object containing callbacks that CheerpJ will use to report various debugging information to the developer. Please note that enabling any listener may have significant performance impact and should not be used in production. Currently only the jsLoadReason callback is supported.

jsLoadReason(scriptName, directReason, userReason)

For each new .jar.js to be loaded, CheerpJ will call this function. This can be useful to debug the reason why some parts of the runtime are loaded, if unexpected.

  • scriptName: The name of the JS file being loaded
  • directReason: A CheerpJ uncompressed and mangled symbol. The method that most directly caused the load. This might not be very useful since it will most often be a java.lang.ClassLoader method. Can be (Internal) if it could not be detected.
  • userReason: A CheerpJ uncompressed and mangled symbol. The last non-runtime method in the stack before the loading. This should be more useful in understanding the user code that introduces the dependency. Can be (Internal) if it could not be detected.

Example usage:

var cheerpjListener = {jsLoadReason:function(scriptName, directReason, userReason){ ... }};
cheerpjInit({listener:cheerpjListener});

logCanvasUpdates

When set to true, it enables logs on the console about the display areas which are being updated. Useful to debug overdrawing.

Example:

cheerpjInit({logCanvasUpdates:true});

preloadResources

By using preloadResources, you can provide CheerpJ with a list of runtime files which you know in advance will be required for the specific application. The list should be given as a JavaScript array of strings.

Example:

cheerpjInit({preloadResources:["/lts/file1","/lt/file2"]});

See also cjGetRuntimeResources.

disableErrorReporting

CheerpJ automatically reports errors at runtime. Setting this option to true disables this system.

Example:

cheerpjInit({disableErrorReporting:true});

clipboardMode

By default CheerpJ supports an internal clipboard which is local to the Java application and is not integrated with the system clipboard. To change this behaviour you can initialize CheerpJ in the following way:

cheerpjInit({clipboardMode:"system"});

In system mode CheerpJ will share the clipboard with the system. Browsers enforce serious limitations on how the system clipboard can be accessed. In practice it is generally accessible when the Ctrl+C and Ctrl+V shortcuts are used (Cmd+C and Cmd+V on MacOSX). Due to these limitations the UX when using clipboardMode:"system" is:

  • Ctrl+C/Cmd+C: the user has to press the shortcut twice to give CheerpJ access to the system clipboard. CheerpJ will block the execution while waiting for the second Ctrl+C.
  • Ctrl+V/Cmd+V: this shortcut behaves normally, there is no difference with native execution.
  • Menu based Copy/Paste: Ctrl+C/Ctrl+V are needed to access the clipboard. CheerpJ will block the execution while waiting the appropriate shortcut.

Commercial users adopting this integration have so far reported that this change in UX is not a significant burden for users. Moreover, in the future we plan to add an additional clipboard mode to take advantage of a new permission-based browser API which is currently being standardized. This future mode will provide native like user experience in all cases.

enableProguardTrace

When this option is set to true CheerpJ will automatically keep track of the classes actually used at runtime. Moreover, it will also keep track of classes which are accessed by reflection. After the application has been fully tested you can use the cjGetProguardConfiguration() function from the browser console to download a proguard configuration file (cheerpj.pro) that you can directly use with proguard to remove unneeded classes, methods and fields from the application, greatly reducing the download size and startup time.

enableInputMethods

When this option is set to true CheerpJ will be able to receive text input from the input method framework of the platform. This is useful to support text input for languages such as Chinese, Japanese and Korean.

cheerpjCreateDisplay

This method will create the HTML element that will contain all Java windows. It is only required to run graphical applications.

cheerpjCreateDisplay(width, height, /*optional*/parent)

The width and height parameter represent the display area size in CSS pixels. It is also possible to specify a parent element if required, if a parent element is not specified the display area will be appended to the page body element. If a parent is specified it is also possible to pass -1 to both width and height, in that case the size will correspond to the parent size and it will also change dynamically if the parent is modified by either CSS changes or browser window resize.

Running applications and JARs

Warning: CheerpJ does not support opening the HTML pages directly from disk. If the URL in your browser starts with file://, CheerpJ will not run. You must use a local Web server.

The most common way of starting an application is to use the cheerpjRunMain API, which lets you execute the static main method of a Java class in the classpath.

cherpjRunMain("fully.qualified.class.name", "/app/my_application_archive.jar:/app/my_dependency_archive.jar", arg1, arg2);

Alternatively, if your JAR is designed to be executed with java -jar my_application_archive.jar, you can use this simpler API.

cheerpjRunJar("/app/my_application_archive.jar", arg1, arg2);

Optionally, if your JAR also need additional dependencies, you can use.

cheerpjRunJarWithClassPath("/app/my_application_archive.jar", "/app/my_dependency_archive.jar", arg1, arg2);

In all cases the arguments should be JavaScript Strings.

cjCall / cjNew

These functions make it possible to conveniently call Java code from JS. Java code is always run asynchronously, so the returned values are Promises. See below for details.

Calling Java constructors from JavaScript:

/* Equivalent Java code: myClass object = com.my.Java.package.myClass(argument1)  */
var object = cjNew("com.my.Java.package.myClass", argument1);

Call static Java methods from JavaScript:

/* Equivalent Java code: int returnVal = com.my.Java.package.myClass.method(argument1, argument2, argument3); */
var returnVal = cjCall("com.my.Java.package.myClass", "method", argument1, argument2, argument3);

Call Java methods from JavaScript:

/* Equivalent Java code: int returnVal = object.method(argument1, argument2, argument3); */
var returnVal = cjCall(object, "method", argument1, argument2, argument3);

Both cjNew and cjCall return standard JavaScript Promises. They can be transparently used in other calls to cjNew/cjCall or you can use .then(...) and .catch(...) to access the resulting value and handle errors. It is also possible to use async/await (either natively or through a JS transpiler) to write sync-like code using cjNew/cjCall as async primitives.

cjResolveCall / cjResolveNew

Using cjCall/cjNew is convenient, but under the hood Java reflection APIs are used, which may have a significant performance impact if used heavily. If you plan to use cjCall/cjNew many times it is convenient to go through reflection APIs only once by using the cjResolveCall/cjResolveNew API.

Examples:

var promise1 = cjResolveCall("com.something.ClassName", "methodName", ["java.lang.String", "int", "double"]);
var promise2 = cjResolveNew("com.something.ClassName", ["java.lang.String", "int", "double"]);

cjResolveCall supports both instance and static methods of classes. The third parameter (for both APIs) is an array of Java types and it is only required if the methodName is not unique in the class (i.e. it is overloaded). The third parameter can be omitted (be null) if the method name (or constructor) is unique. For example:

var promise = cjResolveCall("com.something.ClassName", "uniqueMethodName", null);

cjResolveCall/cjResolveNew are async, like most of CheerpJ's APIs. To get the actual result you can either use .then() or the async/await functionality of JS. For example:

var resolvedMethod = await cjResolveCall("com.something.ClassName", "uniqueMethodName", null);
cjResolveCall("com.something.ClassName", "uniqueMethodName", null).then(function(resolvedMethod) { ... });

The returned value is an opaque handle to the desired method (or constructor), which can now be called an arbitrary number of times without going through Java reflection.

cjCall(resolvedMethod, arg1, arg2, arg3);
cjNew(resolvedConstructor, arg1, arg2, arg3);

Alternatively resolvedMethod can also be used directly as a function, for example:

resolvedMethod(arg1, arg2, arg3);

Please note that this convenient form can unfortunately only be used on the main thread, not on Workers. For more information see WebWorker API

Data conversion

cjStringJavaToJs(str) / cjStringJsToJava(str)

var jsString = cjStringJavaToJs(javaString);

This converts a Java string into a JavaScript string. This operation implies a copy.

String javaString = cjStringJStoJava(jsString);

This converts a JavaScript string into a Java string. This operations also implies a copy. String parameters passed to cheerpjRunMain, cjCall and cjNew are automatically converted so it is not necessary to use this methods in that case.

cjTypedArrayToJava

Converts a TypedArray to a Java compatible primitive array. This operation implies a copy. Data is converted as follows:

Typed Array Java array
Int8Array byte[]
Uint8Array byte[]
Int16Array short[]
Uint16Array char[]
Int32Array int[]
Uint32Array int[]
Float32Array float[]
Float64Array double[]

Preloading APIs

cjGetRuntimeResources

Returns a JavaScript string representing the data that should be passed to preloadResources. It is a list of files that have been loaded from the runtime up to the time this function is called.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.