---
title: "Java and JavaScript Interoperability"
source: "https://cheerpj.com/docs/tutorials/interoperability-tutorial"
---

# 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](https://cheerpj.com/docs/guides/implementing-native-methods.md#calling-back-into-java-from-javascript) in the native methods guide.

## Prerequisites

- [Node.js](https://nodejs.org/en/) (>= 18)
- A copy of the tutorial [repository](https://github.com/leaningtech/cheerpj-meta.git)

```sh
  git clone https://github.com/leaningtech/cheerpj-meta.git
```

- Go to the `projectTemplate` directory of the Interoperability example:

```sh
  cd examples/Interoperability/projectTemplate
```

## Project structure

The template contains these files:

```plaintext
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](https://github.com/leaningtech/cheerpj-meta/tree/main/examples/Interoperability).

## 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`

```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](#running-the-example).

## JavaScript native method implementation

For Java and JavaScript to communicate, implement the Java [`native`](https://cheerpj.com/docs/guides/implementing-native-methods.md) 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`](https://cheerpj.com/docs/guides/implementing-native-methods.md) guide for details.

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

`index.html`

```js
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`

```js
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`

```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`

```js
(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`](https://cheerpj.com/docs/reference/cheerpjInit.md) initialises CheerpJ with these options:

  - [`version`](https://cheerpj.com/docs/reference/cheerpjInit.md#version): the Java version to run, here Java 8.
  - [`natives`](https://cheerpj.com/docs/reference/cheerpjInit.md#natives): the JavaScript implementations of the Java native methods.

- [`cheerpjCreateDisplay`](https://cheerpj.com/docs/reference/cheerpjCreateDisplay.md) creates a 400x300 display for the Swing window.

- [`cheerpjRunJar`](https://cheerpj.com/docs/reference/cheerpjRunJar.md) 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):

```bash
make
```

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

```bash
javac -d . com/example/Example.java
jar cvfm example.jar com/example/manifest.txt com/example/*.class
```

2. **Start a local server**: serve the `projectTemplate` directory with an HTTP server such as [`http-server`](https://www.npmjs.com/package/http-server):

```bash
npx http-server -p 8080
```

3. **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](https://github.com/leaningtech/cheerpj-meta/tree/main/examples/Interoperability)
