<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dmitrii Tikhomirov</title>
    <description>The latest articles on Forem by Dmitrii Tikhomirov (@treblereel).</description>
    <link>https://forem.com/treblereel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F711309%2F22593fdd-f2a7-4c52-8a9b-9e0ea88a7ebb.jpeg</url>
      <title>Forem: Dmitrii Tikhomirov</title>
      <link>https://forem.com/treblereel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/treblereel"/>
    <language>en</language>
    <item>
      <title>GraalVM + WASM from the Perspective of a J2CL/GWT Developer</title>
      <dc:creator>Dmitrii Tikhomirov</dc:creator>
      <pubDate>Fri, 11 Jul 2025 06:15:00 +0000</pubDate>
      <link>https://forem.com/treblereel/graalvm-wasm-from-the-perspective-of-a-j2clgwt-developer-4i</link>
      <guid>https://forem.com/treblereel/graalvm-wasm-from-the-perspective-of-a-j2clgwt-developer-4i</guid>
      <description>&lt;p&gt;I recommend watching the talk “&lt;a href="https://www.youtube.com/watch?v=Z2SWSIThHXY" rel="noopener noreferrer"&gt;The Future of Write Once, Run Anywhere: From Java to WebAssembly&lt;/a&gt;” by Patrick Ziegler &amp;amp; Fabio Niephaus for additional context.&lt;/p&gt;

&lt;p&gt;For a long time, GWT and later J2CL were the primary methods for building complex web applications in Java. However, many of the original GWT use cases (dating back almost 20 years) are now obsolete. At the same time, the emergence of frameworks like React and the TypeScript language raises the question: is it still worthwhile to use such a niche solution?&lt;/p&gt;

&lt;p&gt;One of the main drawbacks of both GWT and J2CL is that they require source code compatible with their jre/supported features in order to produce JavaScript. As a result, very few libraries are available, because you have to either port existing ones (and then maintain them) or develop them from scratch, which is quite time-intensive.&lt;/p&gt;

&lt;p&gt;I personally dedicated a substantial amount of time to building several core GWT/J2CL libraries—JSON, YAML and XML marshallers plus a dependency‐injection framework, but such an investment is difficult to justify from a business standpoint, as no stakeholder is likely to underwrite that level of development effort.&lt;/p&gt;

&lt;p&gt;When I learned that the Oracle GraalVM Team is working on WebAssembly compilation, it immediately caught my attention: one of the standout features is that bitecode is used as the build input. Although not all features are supported yet (for example, multithreading is not available due to current WebAssembly limitations), it was worth experimenting.&lt;/p&gt;

&lt;p&gt;After trying a few sample projects, I found:&lt;/p&gt;

&lt;p&gt;✔ Setup and build&lt;/p&gt;

&lt;p&gt;No special configuration required: everything works within a standard Maven environment (using an &lt;a href="https://github.com/graalvm/oracle-graalvm-ea-builds/releases" rel="noopener noreferrer"&gt;Oracle GraalVM Early‐Access build&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Build steps mirror those for GraalVM native images&lt;/p&gt;

&lt;p&gt;✔ Runtime features&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reflection support (classes must be registered in reflect-config.json)&lt;/li&gt;
&lt;li&gt;ServiceLoader support&lt;/li&gt;
&lt;li&gt;CLDR support (e.g. DateTimeFormatter works without hacks; full date/time and time-zone handling)&lt;/li&gt;
&lt;li&gt;String.format works :) (unavailable in J2CL/GWT)&lt;/li&gt;
&lt;li&gt;Several XML/JSON marshallers run out of the box&lt;/li&gt;
&lt;li&gt;In other words, mostly any libraries will work out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✘ Current limitations&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No direct DOM access: JsInterop exists in an early stage and is not yet suitable for GUI construction (improvements promised)&lt;/li&gt;
&lt;li&gt;WASM exports not yet functional, though a fix is pending via pull request&lt;/li&gt;
&lt;li&gt;No source-map support, making debugging difficult&lt;/li&gt;
&lt;li&gt;No threading, networking or graphics support (expected at this stage)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To test a real-world scenario, I compiled and ran Drools - a Business Rule Management System and rules engine. In a standard JVM setup, Drools compiles DRL into .class files at runtime, loads them and uses them for validation. Because native images cannot load classes dynamically (&lt;a href="https://github.com/oracle/graal/issues/11327" rel="noopener noreferrer"&gt;though this may change soon&lt;/a&gt;), I moved DRL rules into a separate module and precompiled them with kie-maven-plugin. I also adjusted Drools to handle resource reading inlined into WASM. As usual, I added classes and resources to reflect-config.json, resource-config.json and native-image.properties.&lt;/p&gt;

&lt;p&gt;Result: Drools runs in the browser as a .wad file; the complete application size is 41 MB, and a single rule executes in 6 ms.&lt;/p&gt;

&lt;p&gt;The GraalVM Team claims that WASM compilation is production-ready, but tooling (for example, exports) is not fully mature. Overall, however, this looks very promising. I see huge potential for running large Java applications in WebAssembly. I’m particularly interested in the WebAssembly Component Model, which could enable assembling applications like LEGO, each component written in its own language. Challenges remain, but progress is encouraging.&lt;/p&gt;

&lt;p&gt;I will continue to monitor GraalVM WASM development closely. If I discover further insights, I will report them here.&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>java</category>
      <category>graalvm</category>
      <category>gwt</category>
    </item>
    <item>
      <title>Java for web frontend developers, part 2: getting started with J2CL</title>
      <dc:creator>Dmitrii Tikhomirov</dc:creator>
      <pubDate>Mon, 06 Jun 2022 23:47:34 +0000</pubDate>
      <link>https://forem.com/treblereel/java-for-web-frontend-developers-part-2-getting-started-with-j2cl-314g</link>
      <guid>https://forem.com/treblereel/java-for-web-frontend-developers-part-2-getting-started-with-j2cl-314g</guid>
      <description>&lt;p&gt;In the previous article I described how to create and run a simple Java application in a web browser using &lt;a href="https://github.com/Vertispan/j2clmavenplugin"&gt;j2cl-maven-plugin&lt;/a&gt;, so if you aren’t familiar with J2CL or Google Closure Compiler I’d recommend taking a look at &lt;a href="https://dev.to/treblereel/java-for-web-frontend-developers-part-1-generating-a-simple-project-41jp"&gt;that article first&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article I’m going to show you 3 scenarios of running J2CL applications:&lt;/p&gt;

&lt;p&gt;1) Running our app as a standalone application&lt;br&gt;
2) Calling methods of our application from JavaScript via a window object &lt;br&gt;
3) Exporting methods from our Java to JavaScript environment &lt;/p&gt;

&lt;p&gt;Before we begin: &lt;/p&gt;

&lt;p&gt;In the examples below, I'll be rewriting parts of the demos code. To try out complete demos you can check my &lt;a href="https://github.com/treblereel/Beginning_J2CL/tree/main/work-with-j2cl-app-from-js"&gt;GitHub repo&lt;/a&gt; that contains all demos in one place.&lt;/p&gt;

&lt;p&gt;If you have questions about running the demos, check my previous article.&lt;/p&gt;

&lt;p&gt;1) &lt;a href="https://github.com/treblereel/Beginning_J2CL/tree/main/work-with-j2cl-app-from-js/simple-xml-marshaller"&gt;Standalone applications&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, I created a simple POJO called &lt;code&gt;User.java&lt;/code&gt; with several properties inside and a simple form with corresponding inputs that were passed to the properties of the POJO. To marshall an instance of User to XML I’ll be using the &lt;a href="https://github.com/treblereel/mapper-xml"&gt;mapper-xml&lt;/a&gt; project. It’s an implementation of JAXB (Java Architecture for XML Binding) for GWT and J2CL. I like JAXB because it’s very flexible and allows us to process complex XML structures by annotating Java Beans.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@XMLMapper&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;secondName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="n"&gt;getters&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;setters&lt;/span&gt; &lt;span class="n"&gt;omitted&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@XMLMapper&lt;/code&gt; is necessary here to trigger a JAXB annotation processor to generate the &lt;code&gt;User_XMLMapperImpl&lt;/code&gt; marshaller for this POJO. &lt;code&gt;User_XMLMapperImpl&lt;/code&gt; can be used to serialize and deserialize User to XML and back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

 &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;AbstractObjectMapper&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User_XMLMapperImpl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

 &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onModuleLoad&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="nc"&gt;HTMLDivElement&lt;/span&gt; &lt;span class="n"&gt;xmlDivElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HTMLDivElement&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getElementById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"xml"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

   &lt;span class="nc"&gt;HTMLButtonElement&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HTMLButtonElement&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getElementById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
   &lt;span class="nc"&gt;HTMLInputElement&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getElementById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"firstName"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
   &lt;span class="nc"&gt;HTMLInputElement&lt;/span&gt; &lt;span class="n"&gt;secondName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
       &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getElementById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"secondName"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
   &lt;span class="nc"&gt;HTMLInputElement&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getElementById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addEventListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
       &lt;span class="s"&gt;"click"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;evt&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
           &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
           &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setFirstName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;textContent&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
           &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSecondName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secondName&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;textContent&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

           &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;_age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;textContent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
           &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAge&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parseInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;

           &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
           &lt;span class="n"&gt;xmlDivElement&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

           &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#exampleModal"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;modal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"show"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

         &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
           &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Exception "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
         &lt;span class="o"&gt;}&lt;/span&gt;
       &lt;span class="o"&gt;});&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, I have added a listener to the &lt;code&gt;submit&lt;/code&gt; button that collects values from the fields and sets them to the instance of the User object. When it’s done I call a mapper, which is an instance of the User’s marshaller, pass User into it and print the resulting XML on the screen. Simple and nice.&lt;/p&gt;

&lt;p&gt;2) &lt;a href="https://github.com/treblereel/Beginning_J2CL/tree/main/work-with-j2cl-app-from-js/bind-to-window-xml-marshaller"&gt;Calling an XML marshaller from an existing application&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s say, we already have an existing JavaScript application and we want to add an XML export feature to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="err"&gt;''&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;secondName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="err"&gt;''&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The User object from the existing JavaScript application should be bound to the existing &lt;code&gt;User.java&lt;/code&gt;, which is its representation in Java. To achieve that we need to do 2 steps. First, we add the &lt;code&gt;@JsType&lt;/code&gt; annotation to the User (&lt;code&gt;@JsType&lt;/code&gt; is part of the JsInterop API of J2CL and definitely deserves a separate article):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@XMLMapper&lt;/span&gt;
&lt;span class="nd"&gt;@JsType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isNative&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;JsPackage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GLOBAL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"User"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;secondName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Secondly, we have to tell the Closure Compiler that a JavaScript User object exists in the global scope and it has to deal with it, so I added an extern (something like &lt;code&gt;d.ts&lt;/code&gt; from TS) for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
* @externs
*/&lt;/span&gt;

&lt;span class="cm"&gt;/**
* @constructor
*/&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="cm"&gt;/**
* @type {string|undefined}
*/&lt;/span&gt;
&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prototype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
* @type {string|undefined}
*/&lt;/span&gt;
&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prototype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;secondName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
* @type {number|undefined}
*/&lt;/span&gt;
&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prototype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to publish our marshaller to make it discoverable from JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

 &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;AbstractObjectMapper&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User_XMLMapperImpl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

 &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;onModuleLoad&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="nc"&gt;Js&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asPropertyMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
       &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
           &lt;span class="s"&gt;"toXml"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
           &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OnCall&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
               &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                 &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
                 &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                   &lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                 &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                   &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Exception "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
                 &lt;span class="o"&gt;}&lt;/span&gt;

                 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
               &lt;span class="o"&gt;});&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt;

 &lt;span class="nd"&gt;@JsFunction&lt;/span&gt;
 &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;OnCall&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, I created the &lt;code&gt;OnCall&lt;/code&gt; function. It will receive a JavaScript User object, pass it to the marshaller and return a &lt;code&gt;Promise&amp;lt;String&amp;gt;&lt;/code&gt; with a resulting XML. I bind this function to a window object using the property name &lt;code&gt;toXML&lt;/code&gt;. So all we need is to call it from JavaScript, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#submit"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"click"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;secondName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="n"&gt;secondName&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

   &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toXml&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".modal-body #xml"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
       &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="n"&gt;exampleModal&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;modal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
       &lt;span class="o"&gt;}&lt;/span&gt;
   &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) &lt;a href="https://github.com/treblereel/Beginning_J2CL/tree/main/work-with-j2cl-app-from-js/js-native-xml-marshaller"&gt;Using Google Closure Compiler to export methods to JavaScript&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Closure Compiler has very powerful ways to simplify interoperability with an existing JavaScript environment. To simplify its usage even further I created a project that helps with it. All we need is to add the following Maven dependencies and annotate the method we want to export with the &lt;code&gt;@GWT3Export&lt;/code&gt; annotation, like I did here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dependency&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;treblereel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;j2cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;annotations&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;dependency&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dependency&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;treblereel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;j2cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;processors&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;provided&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;dependency&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

 &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;AbstractObjectMapper&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User_XMLMapperImpl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INSTANCE&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

 &lt;span class="nd"&gt;@GWT3Export&lt;/span&gt;
 &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;toXml&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Exception "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The very last thing left: call it for the JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

   &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;marshaller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;treblereel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;j2cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;helloworld&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;App&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

   &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="err"&gt;''&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;secondName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="err"&gt;''&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;

   &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#submit"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"click"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

       &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
       &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
       &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;secondName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="n"&gt;secondName&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
       &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;val&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

       &lt;span class="n"&gt;marshaller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toXml&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
           &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".modal-body #xml"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
           &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'#&lt;/span&gt;&lt;span class="n"&gt;exampleModal&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;modal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
           &lt;span class="o"&gt;}&lt;/span&gt;
       &lt;span class="o"&gt;);&lt;/span&gt;
   &lt;span class="o"&gt;});&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this article I have shown you a few examples of how we can deal with applications written in Java and compiled to JavaScript with the help of the J2CL Maven plugin. There are many topics I would like to touch upon in my upcoming articles from the low-level ones like writing externs and using the JsInterop API, to the high-level ones like modern UI libraries and advanced frameworks.&lt;/p&gt;

&lt;p&gt;If you like my articles, feel free to join &lt;a href="https://gitter.im/gwtproject/gwt"&gt;GWT&lt;/a&gt; and &lt;a href="https://gitter.im/vertispan/j2cl"&gt;J2CL&lt;/a&gt; channels, follow me on &lt;a href="https://twitter.com/treblereel"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/treblereel/"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://github.com/treblereel"&gt;GitHub&lt;/a&gt; or even support me on &lt;a href="https://www.patreon.com/treblereel"&gt;Patreon&lt;/a&gt; or &lt;a href="https://buy.stripe.com/8wM6qO1JR9xy39S8wx"&gt;Stripe&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>j2cl</category>
      <category>webdev</category>
      <category>maven</category>
      <category>java</category>
    </item>
    <item>
      <title>Java for web frontend developers, part 1 : generating a simple project</title>
      <dc:creator>Dmitrii Tikhomirov</dc:creator>
      <pubDate>Mon, 06 Jun 2022 23:46:15 +0000</pubDate>
      <link>https://forem.com/treblereel/java-for-web-frontend-developers-part-1-generating-a-simple-project-41jp</link>
      <guid>https://forem.com/treblereel/java-for-web-frontend-developers-part-1-generating-a-simple-project-41jp</guid>
      <description>&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: Initially this article has been published by me on &lt;a href="https://blog.kie.org/2022/04/rise-of-j2cl-java-web-development-after-gwt.html"&gt;blog.kie.org&lt;/a&gt;. I republish it here with their permission.&lt;/p&gt;

&lt;p&gt;It looks like 15 years of GWT are coming to the end, and besides that web development has dramatically changed since 2006. There is now no chaos of conflicting browser implementations that require to run multiple permutations each. At the same time modern web development frameworks are far from ideal. For instance, a very strong advantage of GWT was the ecosystem around Maven – the stability and usability of this solution was incredible, especially when big teams worked on large projects.&lt;/p&gt;

&lt;p&gt;Google, the main developer of GWT, left the project and started J2CL, the successor of GWT, which takes the very best practices to a new level. Their documentation calls it out as being used in many high performance projects such as Gmail, Inbox, Docs, Slides, and Calendar.&lt;/p&gt;

&lt;p&gt;Initially J2CL was developed to be used in the Bazel environment. After several years of hard work the community, led by Colin Alworth, released the first public J2CL version for Maven – &lt;a href="https://github.com/Vertispan/j2clmavenplugin"&gt;J2CL Maven plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So let’s take a look at what it is and how it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;J2CL AND CLOSURE COMPILER&lt;/strong&gt;&lt;br&gt;
J2CL is responsible for only one task – to transpile a set of Java classes into a set of JavaScript files.&lt;/p&gt;

&lt;p&gt;Google’s Closure Compiler is responsible for merging this set of javascripts into one executable JS script, its optimization and minification.&lt;/p&gt;

&lt;p&gt;Closure Compiler is extremely efficient in minification and optimization of the JavaScript, it simply has no competitors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GENERATING OUR FIRST J2CL PROJECT&lt;/strong&gt;&lt;br&gt;
Let’s start from a simple one module application. Luckily for us, we can generate it from a pre-build archetype. Download the archetype if you don’t have it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;mvn&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maven&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;maven&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dependency&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;plugin:&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nc"&gt;DrepoUrl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nl"&gt;https:&lt;/span&gt;&lt;span class="c1"&gt;//repo.vertispan.com/j2cl/ \&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nc"&gt;Dartifact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;vertispan&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;j2cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;archetypes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;j2cl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;archetype&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;simple:&lt;/span&gt;&lt;span class="mf"&gt;0.19&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can generate a simple application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;mvn&lt;/span&gt; &lt;span class="nl"&gt;archetype:&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nc"&gt;DarchetypeGroupId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;vertispan&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;j2cl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;archetypes&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nc"&gt;DarchetypeArtifactId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;j2cl&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;archetype&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;simple&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nc"&gt;DarchetypeVersion&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.19&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s take a look at the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;pom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;xml&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;treblereel&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;           &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;j2cl&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;               &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;│&lt;/span&gt;               &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;native&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;js&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;webapp&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="no"&gt;WEB&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;INF&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;xml&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;css&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;simpleapp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;css&lt;/span&gt;
    &lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;html&lt;/span&gt;
    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
        &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;
            &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;
                &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;treblereel&lt;/span&gt;
                    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;j2cl&lt;/span&gt;
                        &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nc"&gt;AppTest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;– App.java is a starting point of our application and there’s one point I have to highlight below.&lt;/p&gt;

&lt;p&gt;– App.native.js used to specify how to start our application to the Closure Compiler, because it knows nothing about it. Usage of native.js is a very large topic and a separate article can be written about it.&lt;/p&gt;

&lt;p&gt;– AppTest.java is just a J2CL-compatible unit test that runs in HtmlUnit, it’s also possible to use ChromeDriver to run it in a real browser but it takes longer.&lt;/p&gt;

&lt;p&gt;– pom.xml – here the only interesting part for us is the j2cl-maven-plugin section. For now it contains only the &lt;code&gt;&amp;lt;compilationLevel&amp;gt;&lt;/code&gt; declaration used to set which level of optimization we are going to use during the compilation of the project. ADVANCED is the most efficient one, so Closure Compiler does aggressive renaming, dead code removal, global inlining and so on. But in some cases Closure Compiler needs our help and care – we have to declare which properties or methods should not be removed or renamed. BUNDLE is less strict and better suitable for development because each compilation round takes less time compared to ADVANCED. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RUNNING AND BUILDING OUR J2CL APPLICATION&lt;/strong&gt;&lt;br&gt;
j2cl-maven-plugin allows us to run our application in the development mode with build-in hot code reload and source map debug. To start devmode, run the following command in the terminal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mvn j2cl:watch&lt;/code&gt;&lt;br&gt;
When the application started, run the following command in the second terminal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mvn jetty:run&lt;/code&gt;&lt;br&gt;
There is no need to run &lt;code&gt;mvn clean&lt;/code&gt; each time because J2CL will recompile everything from scratch, and we can reuse the results from the previous run. Moreover, there is an option to use global cache between several projects to reduce compilation time.&lt;/p&gt;

&lt;p&gt;To build &lt;code&gt;.war&lt;/code&gt; we should run &lt;code&gt;mvn package&lt;/code&gt;, there is nothing new here, everything is pretty familiar to GWT developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OK, WHAT IS NEW COMPARED TO GWT&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GWT modules are gone, yes, no more modules. So J2CL will try to compile direct and transitive dependencies from pom.xml, that is why we should set &lt;code&gt;provided&lt;/code&gt; scope to annotation processors and shade them.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;GWT.create&lt;/code&gt; gone as well&lt;/li&gt;
&lt;li&gt; GWT generators are gone, now we should use APT-based generators.&lt;/li&gt;
&lt;li&gt; What about GWT components and widgets we used before ? Most of them have been ported to J2CL.&lt;/li&gt;
&lt;li&gt; Does &lt;code&gt;@GwtIncompatible&lt;/code&gt; work? Yes, it is still here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;AND WHAT IS THE VALUE OF IT FOR US?&lt;/strong&gt;&lt;br&gt;
Right now we are focused on migration of our existing projects from GWT2 to J2CL. There are many libraries that have been migrated to J2CL and many other libraries support both GWT2 and J2CL. I'd like to highlight elemental2-* wrappers, &lt;a href="https://github.com/DominoKit"&gt;DominoKit&lt;/a&gt;, &lt;a href="https://github.com/NaluKit"&gt;Nalu&lt;/a&gt;, and many others.&lt;br&gt;
GWT2 has been ported as the GWT Project which is a set of migrated modules. The Errai project, once a very popular dependency injection framework, is the core component of applications we use internally. Errai has been re-implemented as the &lt;a href="https://github.com/crysknife-io/crysknife"&gt;Crysknife&lt;/a&gt; project.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/treblereel/java-for-web-frontend-developers-part-2-getting-started-with-j2cl-314g"&gt;upcoming posts&lt;/a&gt; I'm going to address several topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Existing libraries and frameworks that are J2CL-compatible&lt;/li&gt;
&lt;li&gt;Defines – how to propagate variables to J2CL&lt;/li&gt;
&lt;li&gt;How we can improve generated code with native.js&lt;/li&gt;
&lt;li&gt;Externs – why do we need them and how to write our own externs&lt;/li&gt;
&lt;li&gt;Semi-reflection &lt;/li&gt;
&lt;li&gt;Interoperability with TS&lt;/li&gt;
&lt;li&gt;And maybe many more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you like my articles, feel free to join &lt;a href="https://gitter.im/gwtproject/gwt"&gt;GWT&lt;/a&gt; and &lt;a href="https://gitter.im/vertispan/j2cl"&gt;J2CL&lt;/a&gt; channels, follow me on &lt;a href="https://twitter.com/treblereel"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/treblereel/"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://github.com/treblereel"&gt;GitHub&lt;/a&gt; or even support me on &lt;a href="https://www.patreon.com/treblereel"&gt;Patreon&lt;/a&gt; or &lt;a href="https://buy.stripe.com/8wM6qO1JR9xy39S8wx"&gt;Stripe&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>j2cl</category>
      <category>java</category>
      <category>webdev</category>
      <category>maven</category>
    </item>
    <item>
      <title>Three.js for Java devs: J2CL, Closure, Bazel, etc ...</title>
      <dc:creator>Dmitrii Tikhomirov</dc:creator>
      <pubDate>Thu, 30 Dec 2021 06:05:38 +0000</pubDate>
      <link>https://forem.com/treblereel/threejs-for-java-devs-j2cl-closure-bazel-etc--28kc</link>
      <guid>https://forem.com/treblereel/threejs-for-java-devs-j2cl-closure-bazel-etc--28kc</guid>
      <description>&lt;p&gt;Let's say we really want to write web-based applications on Java using webgl/webxr/webgpu or something. What options do we have?&lt;/p&gt;

&lt;h3&gt;
  
  
  GWT
&lt;/h3&gt;

&lt;p&gt;The first approach that comes to mind would be using GWT by Google. When it launched 15 years ago, GWT instantly grew very popular and gave rise to many amazing frameworks based on it, like Vaadin, Ext GWT/GXT, Smart GWT, and many others. But it looks like its time has finally come: Google left the GWT project passing it to the community.&lt;/p&gt;

&lt;h3&gt;
  
  
  If not GWT
&lt;/h3&gt;

&lt;p&gt;If not GWT, there are a few not very active and popular projects like JSweet (a syntax mapper to TypeScript) or TeaVM that’s rather dead according to GitHub activity. Not to worry about our project in the future, we would probably choose something stable and well-maintained.&lt;/p&gt;

&lt;h3&gt;
  
  
  J2CL
&lt;/h3&gt;

&lt;p&gt;There aren’t many options left, but, luckily for us, we can take a look at J2CL, a Java to Closure style JavaScript transpiler, that is a GWT successor. According to Google, J2CL is widely used in many projects such as Gmail, Inbox, Docs, Slides, and Calendar. At first glance, it’s exactly what we need, but there’s one little problem - it heavily depends on Bazel that differs a lot from our favourite good old Maven.&lt;/p&gt;

&lt;p&gt;J2CL is responsible for only one task – to transpile a set of Java classes into a set of JavaScript files. Merging this set of javascripts into one executable script, its optimization and minification is the responsibility of Google’s Closure Compiler.&lt;/p&gt;

&lt;p&gt;Google loves Bazel (yeah, a monorepo, reproducible and stable builds and so on), we usually use Maven or Gradle for our projects. Luckily, we can try &lt;a href="https://github.com/Vertispan/j2clmavenplugin"&gt;&lt;code&gt;j2cl-maven-plugin&lt;/code&gt;&lt;/a&gt; that is developed by Colin Alworth from Vertispan, but for now let’s try the Bazel way.&lt;/p&gt;

&lt;h3&gt;
  
  
  J2CL with Bazel
&lt;/h3&gt;

&lt;p&gt;First steps with Bazel are pain. What’s good, we can reuse 2 samples provided by the J2CL project, these 2 demos are more than enough to get us started. In short, the most important Bazel rules for us are &lt;code&gt;j2cl_library&lt;/code&gt; and &lt;code&gt;j2cl_application&lt;/code&gt; that can be used to set groups of files and transpile them into an executable JavaScript file. But for it to work one more step is required: we need to define an entry point for our application. It can be done in 2 ways: we can define it with a handwritten JavaScript script like it works in J2CL demos, or we can generate it with an &lt;a href="https://github.com/treblereel/gwt3-processors"&gt;annotation processor&lt;/a&gt; I wrote for this purpose, feel free to take a look at the demo too.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;TIP&lt;/strong&gt;&lt;/u&gt;: For more details on &lt;code&gt;j2cl_library&lt;/code&gt; and &lt;code&gt;j2cl_application&lt;/code&gt;, you could take a look at an amazing &lt;a href="https://dev.to/tbroyer/reverse-engineering-j2cl-bazel-integration-1o1f"&gt;article by Thomas Broyer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OK, so far so good. My favorite IDE is IntelliJ IDEA that has an official Bazel plugin by Google, but if you prefer VS Code you could try a &lt;a href="https://github.com/salesforce/bazel-vscode"&gt;plugin developed by salesforge&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Native APIs
&lt;/h3&gt;

&lt;p&gt;To work with browser APIs from Java we would use &lt;a href="https://github.com/google/elemental2"&gt;Elemental2&lt;/a&gt;, which is abstractions for JavaScript APIs, the set of Java wrappers based on the Closure Compiler externs.&lt;/p&gt;

&lt;p&gt;Externs are type definitions of, for instance, Browser APIs like HTML elements or WebGL classes, pretty much the same as d.ts, that helps Closure Compiler to recognize the types. By the way, Elemental2 libraries were generated from the built-in Closure Compiler externs using the &lt;a href="https://github.com/google/jsinterop-generator"&gt;JsInterop generator&lt;/a&gt;. Elemental2 does not cover the whole set of Web APIs, but it’s not too difficult to write missing parts like I did in &lt;a href="https://github.com/treblereel/elemental2-experimental/tree/main/maven"&gt;my research project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;TIP&lt;/strong&gt;&lt;/u&gt;: Peter Donald is working on an impressive &lt;a href="https://github.com/akasha/akasha"&gt;project Akasha&lt;/a&gt; that aims at creating a unified set of APIs generated from the latest WebIDL specs. It’s kept mostly up-to-date but is incompatible with Elemental2 (as a matter of fact, it’s incompatible with the built-in Closure externs).&lt;/p&gt;

&lt;h3&gt;
  
  
  JsInterop
&lt;/h3&gt;

&lt;p&gt;So it looks like we have pretty much everything except for the most important part: three.js that we can use from Java. And it’s a little bit of a complex part. To interop with JavaScript we should use &lt;a href="https://github.com/google/j2cl/blob/master/docs/jsinterop-by-example.md"&gt;J2CL JsInterop API&lt;/a&gt;, but there is a little problem: Closure Compiler must be able to recognize types of (most of the) three.js objects. Here we have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Annotate source classes of three.js by Closure type annotations and do some refactoring (Uniforms is pain).&lt;br&gt;
&lt;em&gt;Advantages&lt;/em&gt;: During the optimization phase, Closure Compiler does tree shaking, function inlining and other optimization and other techniques to reduce resulting JavaScript file size. It’s the smallest and fastest option.&lt;br&gt;
&lt;em&gt;Disadvantages&lt;/em&gt;: Adding type annotations to such a huge library like three.js is time-consuming and difficult. From my experience, it needs huge refactoring and is very difficult to maintain. Creating a proof of concept took me two months of hard work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use pure &lt;code&gt;three.min.js&lt;/code&gt; as is, load it via a JavaScript injection or script tag.&lt;br&gt;
&lt;em&gt;Advantages&lt;/em&gt;: Easy to maintain.&lt;br&gt;
&lt;em&gt;Disadvantages&lt;/em&gt;:&lt;br&gt;
i. Total code size will be &lt;code&gt;three.min.js&lt;/code&gt; + your app code.&lt;br&gt;
ii. We need externs to generate Java abstractions and make Closure Compiler happy.&lt;br&gt;
iii. But there is no externs for three.js.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Externs
&lt;/h3&gt;

&lt;p&gt;So I chose the last option: using pure &lt;code&gt;three.min.js&lt;/code&gt;. After some googling I found a well-supported d.ts – TypeScript declaration files for three.js by the DefinitelyTyped project.&lt;/p&gt;

&lt;p&gt;Well, sounds nice, writing externs from scratch for such a huge project like three.js is an overwhelming task for one person. But there was a little problem: how to convert d.ts to externs? The good news: we can use &lt;a href="https://github.com/angular/tsickle"&gt;Tsickle&lt;/a&gt;, the project aimed at generating externs from d.ts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tsickle
&lt;/h3&gt;

&lt;p&gt;The bad news for me was that after generation the resulting externs didn’t work. It took me a few hours to fix namespace and types issues, and enums had to be replaced by constants, I had no choice, enum support in J2CL is limited now. According to J2CL GitHub issues page, the team is working to improve it in the nearest future. &lt;/p&gt;

&lt;h3&gt;
  
  
  JsInterop generator
&lt;/h3&gt;

&lt;p&gt;OK, after three.js externs started to work almost as expected (well enough for the time being), I generated Java &lt;code&gt;@JSType&lt;/code&gt; based on those externs and finished the demo. &lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;You can take a look at the demo here:&lt;br&gt;
&lt;a href="https://static.treblereel.org/bazel-three4g"&gt;https://static.treblereel.org/bazel-three4g&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source code is published here: &lt;br&gt;
&lt;a href="https://github.com/treblereel/bazel_three_demo"&gt;https://github.com/treblereel/bazel_three_demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is how the working Demo class looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;demo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;elemental2.dom.DomGlobal&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.BoxGeometry&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.Mesh&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.MeshBasicMaterial&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.MeshBasicMaterialParameters&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.PerspectiveCamera&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.Scene&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.Texture&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.TextureLoader&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.WebGLRenderer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.treblereel.gwt.elemental2.three.WebGLRendererParameters&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Demo&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;PerspectiveCamera&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Mesh&lt;/span&gt; &lt;span class="n"&gt;mesh&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;WebGLRenderer&lt;/span&gt; &lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;Demo&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PerspectiveCamera&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;innerHeight&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Texture&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextureLoader&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://threejs.org/examples/textures/crate.gif"&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;MeshBasicMaterialParameters&lt;/span&gt; &lt;span class="n"&gt;meshBasicMaterialParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MeshBasicMaterialParameters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;meshBasicMaterialParameters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;BoxGeometry&lt;/span&gt; &lt;span class="n"&gt;geometry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BoxGeometry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;MeshBasicMaterial&lt;/span&gt; &lt;span class="n"&gt;material&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MeshBasicMaterial&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;meshBasicMaterialParameters&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;mesh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Mesh&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;geometry&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;material&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;mesh&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;WebGLRendererParameters&lt;/span&gt; &lt;span class="n"&gt;webGLRendererParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WebGLRendererParameters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;webGLRendererParameters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setAntialias&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebGLRenderer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webGLRendererParameters&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setPixelRatio&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;devicePixelRatio&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;innerWidth&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;innerHeight&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;appendChild&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;domElement&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addEventListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"resize"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;evt&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;onWindowResize&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;animate&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;  &lt;span class="nf"&gt;onWindowResize&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;aspect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;innerHeight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;updateProjectionMatrix&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;innerWidth&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;innerHeight&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;animate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;DomGlobal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;animate&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;mesh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.005&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;mesh&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rotation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;renderer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Bazel with J2CL works great for such tasks, Bazel is very fast!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s not difficult to maintain a Java three.js wrapper, we only need to keep externs updated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A huge minus is that testing is not opensourced yet, but j2cl-maven-plugin works around it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Source map for debugging doesn’t work (it’s reported at &lt;a href="https://github.com/google/j2cl/issues/93"&gt;J2CL and Closure GitHub issues page&lt;/a&gt;). Perhaps it’s possible to use Vertispan’s Closure Compiler fork that supports a Source map during debug.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It doesn’t look like Google is going to popularize J2CL (compared to Flutter). I think they are OK with the current state. I can only assume they use it to support their legacy applications, I hope I’m wrong.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Three.js is migrating to ES6. It’s possible to use &lt;a href="https://github.com/treblereel/gwt3-processors"&gt;ES6 classes with J2CL&lt;/a&gt; but not in the case of three.js example classes, I hope devs will continue to keep backward compatibility with the pre-ES6 ecosystem.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;TIP&lt;/strong&gt;&lt;/u&gt;: Some time ago I ported &lt;a href="https://github.com/treblereel/quake2-j2cl-port"&gt;Quake2 by id Software to J2CL&lt;/a&gt; using j2cl-maven-plugin with Quarkus backend, so you can take a look, it rocks!&lt;/p&gt;

&lt;p&gt;P.S. It’s my very first article ever, so I'll be happy to hear what I could fix or improve. &lt;br&gt;
P.P.S. The main question: Do we really need it all at all? If yes, I can publish it to Maven as a standalone library.&lt;/p&gt;

</description>
      <category>threejs</category>
      <category>java</category>
      <category>j2cl</category>
      <category>bazel</category>
    </item>
  </channel>
</rss>
