Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

1. Overview

TeaVM is a powerful tool for translating Java bytecode into JavaScript, enabling Java applications to run directly in the browser. This allows us to maintain a Java-based codebase while targeting web environments.

In this tutorial, we’ll explore how to bridge the gap between Java and JavaScript using TeaVM’s ability to interact with the DOM and call Java methods from JavaScript.

2. Main Uses of TeaVM

When we have complex Java-based logic, it’s not practical to rewrite the same functionality for the web. TeaVM allows us to avoid redundancy by efficiently compiling our Java code into JavaScript, optimizing the size and performance of the final script.

Either way, let’s remember that our Java code must fit within the confines of the Java Class Library (JCL) emulation. For example, Swing and JavaFX aren’t supported.

2.1. Single-Page Application (SPA)

TeaVM can be the right solution for creating a Single-Page Application (SPA) from scratch almost entirely in Java and CSS, minimizing the need to write JavaScript and HTML code. This is because TeaVM has these web-specific features:

  • Call Java methods directly from JavaScript, as we’ll see in the upcoming examples
  • Create native Java methods implemented in JavaScript using the @JSBody annotation
  • Manipulate web elements with Java using the JSO library

However, TeaVM doesn’t completely replace the need for JavaScript or HTML, especially with regard to layout and some browser-specific logic. In addition, TeaVM doesn’t handle CSS, which we have to write manually or manage through external frameworks.

2.2. Existing Website

TeaVM is also great for adding features written in Java to an existing website developed with a traditional CMS like WordPress or Joomla. For example, we can create a PHP plugin for our CMS that exposes functionality to TeaVM via a REST API and include a JavaScript compiled by TeaVM on a page of our website.

Such a script, taking advantage of our REST API, can convert JSON to Java objects and vice versa, and execute our business logic written in Java. It can also modify the DOM to create a user interface or integrate into an existing one.

This use case makes sense when the client-side business logic is so complex that we are more comfortable, skilled, and familiar with Java code than with JavaScript.

2.3. Other Cases

In addition, TeaVM has WebAssembly support under active development, with a new version in the works that will allow our JavaScript-targeted applications to be ported to WebAssembly with minimal changes. However, this feature is still in an experimental phase and not yet ready.

TeaVM can also transpile Java to C. We can use this functionality as an ultra-lightweight subset of GraalVM native images. Even if this functionality is stable and ready to use, we won’t go into it because it’s beyond the main use of TeaVM.

3. Maven Setup and TeaVM Configuration

First, the current 0.10.x version of TeaVM supports Java bytecode up to JDK 21 and requires at least Java 11 to run its Java-to-JavaScript compiler. Of course, these requirements may change in later versions.

We’ll use Maven and keep the pom.xml minimal by configuring TeaVM programmatically within a Java class. This approach allows us to dynamically change the configuration based on the parameters passed to the main(…) method via Maven’s -Dexec.args option. This helps to generate different JavaScript outputs from the same project for different purposes, all while sharing the same codebase.

If we prefer an alternative method, or if Maven isn’t in use, the official TeaVM Getting Started guide provides further instructions.

3.1. pom.xml

After checking what the latest version of TeaVM is in the Maven repository, let’s add the dependencies:

<dependency>
    <groupId>org.teavm</groupId>
    <artifactId>teavm-core</artifactId>
    <version>0.10.2</version>
</dependency>
<dependency>
    <groupId>org.teavm</groupId>
    <artifactId>teavm-classlib</artifactId>
    <version>0.10.2</version>
</dependency>
<dependency>
    <groupId>org.teavm</groupId>
    <artifactId>teavm-tooling</artifactId>
    <version>0.10.2</version>
</dependency>

Adding these three dependencies automatically adds other TeaVM transitive dependencies. The teavm-core includes libraries such as teavm-interop, teavm-metaprogramming-api, relocated ASM libraries (for bytecode manipulation), HPPC, and Rhino (JavaScript engine). In addition, teavm-classlib brings in teavm-jso, commons-io, jzlib and joda-time. The teavm-tooling dependency also includes a relocated version of commons-io.

These transitive dependencies provide essential functionality without the need to add them manually.

3.2. TeaVMRunner.java

This class configures TeaVM, we need to specify it using Maven’s -Dexec.mainClass option:

public class TeaVMRunner {
    public static void main(String[] args) throws Exception {
        TeaVMTool tool = new TeaVMTool();
        tool.setTargetDirectory(new File("target/teavm"));
        tool.setTargetFileName("calculator.js");
        tool.setMainClass("com.baeldung.teavm.Calculator");
        tool.setTargetType(TeaVMTargetType.JAVASCRIPT);
        tool.setOptimizationLevel(TeaVMOptimizationLevel.ADVANCED);
        tool.setDebugInformationGenerated(false);
        tool.setIncremental(false);
        tool.setObfuscated(true);
        tool.generate();
    }
}

Let’s take a closer look:

  • setTargetDirectory(…) → Output directory where TeaVM will place the generated files
  • setTargetFileName(…) → Name of the generated JavaScript file
  • setMainClass(…) → Fully qualified name of the main class of the application
  • setTargetType(…) → JavaScript, WebAssembly, or C
  • setOptimizationLevel(…) → The ADVANCED level produces the smallest JavaScript files, even smaller than the FULL level
  • setDebugInformationGenerated(…) → Only useful for creating a debug information file for the TeaVM Eclipse plugin
  • setIncremental(…) → If enabled, compiles faster, but reduces optimizations, so it’s not recommended for production
  • setObfuscated(…) → It reduces the size of the generated JavaScript by two or three times when enabled, so it should be preferred in most cases

There are also other options documented in the Tooling section of the official guide, e.g. for generating source maps.

The most important thing to note is that using setMainClass(…) creates a JavaScript main() function with global scope that executes the translated version of the Java main(String[]). We’ll see an example of this later.

3.3. HTML Page

While simple, this is a complete example of how to include the Javascript file generated by TeaVM. We’ve left out meta tags to optimize for mobile devices, indexing, and other requirements unrelated to TeaVM:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" >
    <title>TeaVM Example</title>
    <script type="text/javascript" src="calculator.js" ></script>
    <script type="text/javascript" >
        document.addEventListener('DOMContentLoaded', function() {
            // Call JS functions here
        });
    </script>
</head>
<body>
<h1>TeaVM Example</h1>
<div id="calculator-container" ></div>
</body>
</html>

In this example, calculator.js is the file we specified earlier in setTargetFileName(…). We’ll see what to put in place of the “Call JS functions here” comment in a moment. Finally, <div id=”calculator-container” ></div> is a placeholder that we’ll use to create a sample calculator.

4. Calculator Example

Let’s take a simple addition example.

4.1. Calling a Java Method From Javascript

This is the class we previously specified in setMainClass(…):

public class Calculator {

    public static void main(String[] args) {
    }

    @JSExport
    public static int sum(int a, int b) {
        return a + b;
    }
}

The @JSExport annotation in TeaVM is used to make Java methods, fields, or classes accessible to JavaScript, allowing them to be called directly from JavaScript code. So, after compiling the code, let’s call the sum(…) function in our example HTML page:

[...]
document.addEventListener('DOMContentLoaded', function() {
    // Call JS functions here
    let result = sum(51, 72);
    console.log("Sum result: " + result);
[...]

This is the output of the browser’s JavaScript console:

Sum result: 123

The result is as expected.

4.2. Java-Based DOM Manipulation

Now let’s implement the main(…) function. Let’s notice that document.getElementById(“calculator-container”) goes to select the <div id=”calculator-container” ></div> tag that we previously inserted in the example HTML file:

public static void main(String[] args) {
    HTMLDocument document = HTMLDocument.current();
    HTMLElement container = document.getElementById("calculator-container");

    // Create input fields
    HTMLInputElement input1 = (HTMLInputElement) document.createElement("input");
    input1.setType("number");
    container.appendChild(input1);

    HTMLInputElement input2 = (HTMLInputElement) document.createElement("input");
    input2.setType("number");
    container.appendChild(input2);

    // Create a button
    HTMLButtonElement button = (HTMLButtonElement) document.createElement("button");
    button.appendChild(document.createTextNode("Calculate Sum"));
    container.appendChild(button);

    // Create a div to display the result
    HTMLElement resultDiv = document.createElement("div");
    container.appendChild(resultDiv);

    // Add click event listener to the button
    button.addEventListener("click", (evt) -> {
        try {
            long num1 = Long.parseLong(input1.getValue());
            long num2 = Long.parseLong(input2.getValue());
            long sum = num1 + num2;
            resultDiv.setTextContent("Result: " + sum);
        } catch (NumberFormatException e) {
            resultDiv.setTextContent("Please enter valid integer numbers.");
        }
    });
}

The code is self-explanatory. In a nutshell, it dynamically creates input fields, a button, and a result display area within the web page, all using Java. The button listens for a click event, retrieves the numbers entered in the input fields, calculates their sum, and displays the result. If invalid input is provided, an error message is shown instead.

Let’s remember to call the main() function:

document.addEventListener('DOMContentLoaded', function() {
    // Call JS functions here
    main();
});

Here is the result:

TeaVM Example Calculator

Starting with a simple example like this, we can modify the DOM as we like to create any layout, even with the help of CSS.

5. Conclusion

In this article, we explored how TeaVM facilitates the translation of Java bytecode into JavaScript, allowing Java applications to run directly in web browsers. We covered key features such as how to call Java methods from JavaScript, perform Java-based DOM manipulation, and implement simple web applications without having to write extensive JavaScript code. Through a practical calculator example, we demonstrated the ease of bridging Java and web development using TeaVM.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Course – LS – NPI (cat=Java)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)
2 Comments
Oldest
Newest
Inline Feedbacks
View all comments