Java and JavaScript Interoperability

Learn how to enable Java and JavaScript communication using CheerpJ

A Java application running in CheerpJ can call JavaScript, and JavaScript can call the Java application.

This tutorial sets up two-way communication between a Swing application and the web page that hosts it. Java sends text to the page through a native method implemented in JavaScript, and the page sends text to Java by calling a method on a Java object.

To let JavaScript call into Java at any time, the application keeps a Java thread waiting inside a native method. For calls into Java made while a native method runs, see calling back into Java from JavaScript in the native methods guide.

Prerequisites

Terminal window
git clone https://github.com/leaningtech/cheerpj-meta.git
  • Go to the projectTemplate directory of the Interoperability example:
Terminal window
cd examples/Interoperability/projectTemplate

Project structure

The template contains these files:

projectTemplate/
β”œβ”€β”€ com/example/
β”‚ β”œβ”€β”€ Example.class
β”‚ β”œβ”€β”€ Example$1.class
β”‚ β”œβ”€β”€ Example.java
β”‚ └── manifest.txt
β”œβ”€β”€ Makefile
β”œβ”€β”€ example.jar
└── index.html

example.jar is the compiled application. In this tutorial you implement its native methods in JavaScript in index.html.

The finished example is on GitHub.

Java source code: Example.java

The Java class opens a small Swing window. It sends the text typed in the window to the page, and shows the text it receives from the page.

Example.java
package com.example;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Example extends JFrame {
// Native method to set the Java application instance in JavaScript
public static native void nativeSetApplication(Example myApplication);
// Native method to send text to the HTML UI
public static native void sendToHTML(String s);
private JTextField javaTextField; // Input text field
private JTextField javaTextField2; // Output display field
public Example() {
// Set up the JFrame (Java window)
setTitle("Example App");
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
// Create a text field for sending input to JavaScript
javaTextField = new JTextField("");
javaTextField.setBounds(50, 50, 300, 30);
add(javaTextField);
// Create a read-only text field for displaying input from JavaScript
javaTextField2 = new JTextField("");
javaTextField2.setEditable(false); // Disable editing
javaTextField2.setBounds(50, 200, 300, 30);
add(javaTextField2);
// Create a button to send input to JavaScript
JButton sendButton = new JButton("Send to HTML");
sendButton.setBounds(100, 100, 200, 50);
sendButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String textToSend = javaTextField.getText();
sendToHTML(textToSend); // Call the native method
}
});
add(sendButton);
}
// Example method to process input from JavaScript
public String processInput(String input) {
System.out.println("Received input from JavaScript: " + input);
javaTextField2.setText(input);
return "Java received: " + input; // Send response back to JavaScript
}
public static void main(String[] args) {
Example app = new Example();
// Start a thread for initializing the Java application instance in JavaScript
new Thread(() -> {
nativeSetApplication(app);
System.out.println("Starting Thread");
}).start();
app.setVisible(true);
}
}

The class has these methods:

  • sendToHTML: a static native method implemented in JavaScript. The Send to HTML button calls it with the text of the first text field.
  • processInput: called from JavaScript. It prints the input to the console, shows it in the read-only text field and returns a response string.
  • nativeSetApplication: a static native method implemented in JavaScript. main calls it from a new thread to hand the Example object to JavaScript.
Note

There is no need to recompile the Java code for this tutorial: the template includes the compiled example.jar. If you change the Java code, recompile it as described in Running the example.

JavaScript native method implementation

For Java and JavaScript to communicate, implement the Java native methods in JavaScript.

Add the code in this section to the <script> tag in the <body> of index.html. The comments in the template mark where each part goes.

1. Define JavaScript native methods

For each native method, create an async function named Java_<fully-qualified-class-name>_<method-name>. Its first parameter is lib, which gives access to the Java classes. For an instance method the second parameter is the Java object the method was called on. Both methods here are static, so the method’s own parameters follow lib. See the native method guide for details.

You can also move these functions to a separate .js file and include it with a <script> tag.

index.html
async function Java_com_example_Example_sendToHTML(lib, str) {
document.getElementById("javaOutput").innerText =
"JavaScript received: " + str;
console.log("Received input from Java: " + str);
}
async function Java_com_example_Example_nativeSetApplication(
lib,
myApplication
) {
window.myApplication = myApplication;
console.log("Java application instance set on JavaScript side.");
// Make the inputDiv visible after initialization
document.getElementById("inputDiv").style.display = "block";
return new Promise(() => {}); // Keeps the function from returning
}

The Java_com_example_Example_nativeSetApplication function:

  • Stores the Java Example object in window.myApplication.
  • Shows the input field and button on the page.
  • Returns a promise that never resolves, so the Java thread that called it stays inside the native call. This is what keeps window.myApplication usable from JavaScript for as long as the page is open.

The Java_com_example_Example_sendToHTML function:

  • Receives a string from Java.
  • Shows it on the page and logs it to the console.

2. Implement the sendInputToJava function

Add the function that the Send to Java button calls:

index.html
async function sendInputToJava() {
const inputText = document.getElementById("inputText").value;
const response = await window.myApplication.processInput(inputText);
}

The sendInputToJava function:

  • Reads the text from the input box on the page.
  • Calls the Java processInput method on window.myApplication with it. Calls into Java are asynchronous, so the result is awaited. response holds the string processInput returns; this example does not use it.

3. Initialise CheerpJ

Add the CheerpJ loader to the <head> of index.html:

index.html
<script src="https://cjrtnc.leaningtech.com/5.0/loader.js"></script>

Then initialise CheerpJ with the native methods and run the JAR:

index.html
(async () => {
await cheerpjInit({
version: 8,
natives: {
Java_com_example_Example_sendToHTML,
Java_com_example_Example_nativeSetApplication,
},
});
cheerpjCreateDisplay(400, 300);
await cheerpjRunJar("/app/example.jar");
})();

What this does:

  • cheerpjInit initialises CheerpJ with these options:
    • version: the Java version to run, here Java 8.
    • natives: the JavaScript implementations of the Java native methods.
  • cheerpjCreateDisplay creates a 400x300 display for the Swing window.
  • cheerpjRunJar runs example.jar, whose manifest names com.example.Example as the main class.

Running the example

  1. There is no need to recompile the Java code, because only the JavaScript changed and the template includes the compiled example.jar. If you change the Java code, recompile it with the provided Makefile (requires a Java installation):
Terminal window
make

Alternatively, compile and package it manually from the projectTemplate directory:

Terminal window
javac -d . com/example/Example.java
jar cvfm example.jar com/example/manifest.txt com/example/*.class
  1. Start a local server: serve the projectTemplate directory with an HTTP server such as http-server:
Terminal window
npx http-server -p 8080
  1. Run the example: open http://localhost:8080/index.html in the browser. Type in the page’s input box and click Send to Java to send text to Java, or type in the Java window and click Send to HTML to send text to the page.

The result

Source code

View full source code on GitHub

Build with Java for the browser.