DEV Community

Cover image for Java WebAssembly Meets WebForms Core 2.2
Elanat Framework
Elanat Framework

Posted on

Java WebAssembly Meets WebForms Core 2.2

WebAssembly allows applications written in languages other than JavaScript to execute directly in the browser. With WebForms Core 2.2, Java can also be used as a WebAssembly Commander and generate WebForms commands that are executed by WebFormsJS.

For Java, WebForms Core currently supports TeaVM as its supported WebAssembly compiler.

The architecture is straightforward:

Java
 ↓
TeaVM
 ↓
WebAssembly
 ↓
WebForms Core
 ↓
WebFormsJS
 ↓
HTML DOM
Enter fullscreen mode Exit fullscreen mode

The important point is that Java does not manipulate the browser DOM directly. The Java code generates a WebForms response, and WebFormsJS executes that response in the browser.

Java WebAssembly with TeaVM

TeaVM compiles Java bytecode to WebAssembly. WebForms Core can use the resulting WebAssembly module as a Commander.

For this example, the Java WebForms Classes package is used:

<dependency>
    <groupId>net.elanat</groupId>
    <artifactId>WFC</artifactId>
    <version>2.2.0</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

The Java class contains three methods:

package com.example.demo;

import org.teavm.jso.JSExport;
import webformscore.WebForms;

public class MyClass
{
    @JSExport
    public static int Add(int a, int b)
    {
        return a + b;
    }

    @JSExport
    public static String SetData(
        String inputPlace,
        String text,
        String backgroundColor,
        String fontSize)
    {
        WebForms form = new WebForms();

        form.setText(inputPlace, text);
        form.setBackgroundColor("-", backgroundColor);
        form.setFontSize("-", fontSize);

        return form.response();
    }

    @JSExport
    public static String GetHtml()
    {
        return "<marquee>Tag From Wasm!</marquee>";
    }
}
Enter fullscreen mode Exit fullscreen mode

The Add method returns a normal Java value.

The SetData method uses the WebForms Class to generate WebForms commands. The Java code does not need to know anything about the browser DOM.

GetHtml simply returns an HTML fragment.

Compiling Java to WebAssembly

TeaVM can generate WebAssembly GC output for the Java application.

The important configuration is:

<configuration>
    <mainClass>com.example.demo.MyClass</mainClass>
    <targetType>WEBASSEMBLY_GC</targetType>
    <optimizationLevel>FULL</optimizationLevel>
</configuration>
Enter fullscreen mode Exit fullscreen mode

The resulting WebAssembly module can then be used by WebForms Core.

For example:

/web-assembly/java/tea_vm/classes.wasm
Enter fullscreen mode Exit fullscreen mode

TeaVM can also generate its runtime JavaScript:

/web-assembly/java/tea_vm/classes.wasm-runtime.js
Enter fullscreen mode Exit fullscreen mode

WebForms Core can accept either form.

Using Java WebAssembly from CodeBehind

WebForms Core WASM by JAVA

The CodeBehind controller defines the WebAssembly path and uses the WebForms Core WASM API.

using CodeBehind;

public partial class WasmJavaController : CodeBehindController
{
    public void PageLoad(HttpContext context)
    {
        string WasmPath = "/web-assembly/java/tea_vm/classes.wasm"; // Using TeaVM
        //string WasmPath = "/web-assembly/java/tea_vm/classes.wasm-runtime.js"; // Using TeaVM

        WebForms form = new WebForms();

        form.AddText("<b>", Fetch.WasmMethod(WasmLanguage.JAVA, WasmPath, "Add", [10000, 3]));

        form.SetWasmEvent("WasmEvent", HtmlEvent.OnClick, WasmLanguage.JAVA, WasmPath, "SetData", ["h3Tag", "Text From Wasm", "lightgreen", "30px"]);
        form.SetWasmEvent("WasmEventWithOutput", HtmlEvent.OnClick, WasmLanguage.JAVA, WasmPath, "GetHtml", [], "WasmHtmlOutput");

        Write(form.ExportToHtmlComment());
    }
}
Enter fullscreen mode Exit fullscreen mode

The first call executes Add and places its result in the generated WebForms response:

form.AddText("<b>", Fetch.WasmMethod(
    WasmLanguage.JAVA,
    WasmPath,
    "Add",
    [10000, 3]));
Enter fullscreen mode Exit fullscreen mode

The result is therefore produced by Java WebAssembly.

The next command connects a browser event to the Java WebAssembly method:

form.SetWasmEvent(
    "WasmEvent",
    HtmlEvent.OnClick,
    WasmLanguage.JAVA,
    WasmPath,
    "SetData",
    ["h3Tag", "Text From Wasm", "lightgreen", "30px"]);
Enter fullscreen mode Exit fullscreen mode

When the button is clicked, WebForms Core executes the Java method and applies its WebForms response.

The third example sends the returned HTML to a specific element:

form.SetWasmEvent(
    "WasmEventWithOutput",
    HtmlEvent.OnClick,
    WasmLanguage.JAVA,
    WasmPath,
    "GetHtml",
    [],
    "WasmHtmlOutput");
Enter fullscreen mode Exit fullscreen mode

HTML

The page remains ordinary HTML:

@page
@controller WasmJavaController
@layout "/layout.aspx"
@{
  ViewData.Add("title","Java Wasm");
}
<h3>Java Wasm</h3>
<b>Java WASM Result: </b>
<br>
<button id="WasmEvent">Wasm Event</button>
<br>
<h3 id="h3Tag">Wasm Tag Changing!</h3>
<button id="WasmEventWithOutput">Wasm Event With Output</button>
<p id="WasmHtmlOutput">Wasm Html Output</p>
Enter fullscreen mode Exit fullscreen mode

There is no additional WebForms-specific markup in the HTML.

WebForms Core generates its commands on the server:

Server
  ↓
CodeBehind
  ↓
WebForms
  ↓
WebAssembly command
  ↓
WebFormsJS
  ↓
HTML DOM
Enter fullscreen mode Exit fullscreen mode

This keeps the browser side lightweight and allows the Java WebAssembly code to remain a Commander rather than becoming a separate frontend framework.

What about Bytecoder?

Bytecoder was also tested as a possible Java-to-WebAssembly compiler for WebForms Core.

The problem was not the WebForms Core API itself.

The unchanged WebForms Classes implementation contains:

public void setText(String inputPlace, String text)
{
    add("st" + inputPlace, text.replace("\n", "$[ln];"));
}
Enter fullscreen mode Exit fullscreen mode

Bytecoder's compiler failed while analyzing this existing method and reported:

No such method :
java/lang/String.replace
(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Ljava/lang/String;
Enter fullscreen mode Exit fullscreen mode

Interestingly, the Bytecoder Java class library itself contains the corresponding String.replace(CharSequence, CharSequence) method. The problem occurred in Bytecoder's compiler/analyzer when resolving the method used by the existing WFC code.

Therefore, the WFC implementation was not changed to accommodate Bytecoder.

This is important because WebForms Core should not have to change its Java API simply to satisfy a particular compiler backend.

Bytecoder therefore remains an experimental option for Java WebAssembly with WFC rather than the supported route.

What about CheerpJ?

CheerpJ takes a different approach.

Unlike TeaVM, CheerpJ is not primarily producing a standalone Java-specific .wasm module together with a generated JavaScript wrapper in the way expected by WebForms Core's WASM model.

CheerpJ provides a WebAssembly-based Java runtime and executes Java bytecode/JAR files through that runtime.

The model is closer to:

Java JAR
   ↓
CheerpJ Runtime
   ↓
WebAssembly
   ↓
Browser
Enter fullscreen mode Exit fullscreen mode

rather than:

Java
   ↓
Java → WASM compiler
   ↓
Standalone WASM module
   ↓
WebForms Core
Enter fullscreen mode Exit fullscreen mode

CheerpJ therefore follows its own execution model and does not produce the JavaScript/WASM artifact structure expected by the current WebForms Core WASM integration.

This makes CheerpJ interesting as a Java-in-the-browser technology, but it is architecturally different from the WebAssembly Commander model used by WebForms Core.

For this reason, TeaVM is currently the Java WebAssembly implementation supported by WebForms Core.

Why TeaVM?

The important requirement for WebForms Core is not simply that Java can execute in a browser.

The requirement is that Java can act as a WebAssembly Commander:

Java Method
    ↓
WebForms Class
    ↓
WebForms Response
    ↓
WebFormsJS
    ↓
DOM
Enter fullscreen mode Exit fullscreen mode

TeaVM fits this model directly because it produces WebAssembly that can be loaded and invoked by the WebForms Core WASM infrastructure.

The Java code can therefore use the same WebForms Classes API used by other languages.

Conclusion

Java can be used with WebForms Core 2.2 as a WebAssembly Commander through TeaVM.

The resulting architecture is:

             Java
               │
               ▼
             TeaVM
               │
               ▼
         WebAssembly
               │
               ▼
        WebForms Core
               │
               ▼
          WebFormsJS
               │
               ▼
           HTML DOM
Enter fullscreen mode Exit fullscreen mode

The Java application does not need a separate JavaScript frontend.

It generates WebForms commands, and WebFormsJS executes those commands in the browser.

At present, TeaVM is the supported Java WebAssembly path for WebForms Core. Bytecoder has a compiler compatibility problem with existing WFC Java code, while CheerpJ follows a different runtime/JAR-oriented architecture instead of the standalone WebAssembly module model used by WFC.

Related links

On Elanat:

On GitHub:

On Maven:

Top comments (0)