VertxUI: Java as a Front-End Language

Posted on Posted in Javascript, web design

Yesterday I had a job interview for a senior Java back-end job. They asked me whether I was a full-stack developer or not. Although my answer was a proud yes, I stated that I don’t really like JavaScript, but I can find my way through HTML/CSS and JavaScript code. Then I had to explain why I don’t like JavaScript.Guest author’s biography
Niels Gorisse (39) is a senior full-stack Java developer with a lot of back-end experience. Also see cv.bonneville.nl.

I said I don’t like it because of many reasons. JavaScript doesn’t – or actually: didn’t – work the same on all browsers, there is a global scope with all variables in it, and besides that, there are thousands of libraries fixing missing language and API features. Even worse, it seems none of them can be considered to be ‘default.’ So, there is no chance of knowing whether you’ve picked the lasting libraries. I guess I did not get the job.

Just like most senior Java developers, I wrote my first JavaScript lines of code well before 2000. Of course, that is the reason for my grunge against it. But things have changed. Nowadays, after more than ten years of browser disaster, ECMAscript5 has become the standard: more than 97% of all browsers in use support it. Yes, JavaScript still has the ugly language features, but you can write a piece of JavaScript code that works anywhere. And JavaScript is becoming a decent language complete with classes, exceptions, lambda notation, worker thread, packaging, annotations, futures, library management, and much more.

But why waste time on learning new language features and lots of frameworks, taking the risk that you’re learning tools that won’t ever be updated again? There is another language that can run anywhere too, except directly in a browser. What if Java could directly run in a browser?

Mind you, many features which are fairly new to JavaScript have been added to Java many years earlier. In almost every case, this means they’ve become pretty stable and mature over the years:

Feature JavaScript since Java since
worker threads ES5 2009 Java 1.0.2 1997
exception handling ES5 2009 Java 1.0.2 1997
compiler checks lint (node-jslint) 2011 Java 1.0.2 1997
jar-like packaging require.js 2011 Java 1.0.2 1997
bytecode asm.js 2013 Java 1.0.2 1997
strong typing TypeScript 2014 Java 1.0.2 1997
classes modules, ES6 2015 Java 1.0.2 1997
unobfuscated stacktrace gulp sourcemaps 2014 Java 1.0.2 1997
unit testing mocha (Jasmine, tape) 2011 jUnit 1998
instant deployment browser-sync / gulp / grunt 2014 Tomcat 2000
logging framework WinstonJS 2013 Log4J 1.0.4 2001
dependency management npm 2011 Maven 2002
dependency injection gulp-inject / inversify / … 2014 Spring 2004
Annotations Decorators (ES7) ? Java5 2005
futures promises, ES6 2015 Java8 2014
Lambdas fat arrow functions, ES6 2015 Java8 2014
Async-await (C#) ES7 ? ? ?

VertxUI and Fluent

VertxUI is a 100% Java library which tries to answer what if we could run Java directly in the browser. And because pure HTML with CSS is enough to build web pages, VertxUI provides – besides low-level access to the browser – also a lightweight fluent API called Fluent, which simplifies building HTML and CSS with code only. Fluent works with method names corresponding to HTML tags. The first argument of these methods is always a CSS class. So VertxUI does not have any templates, just code. Consider a menu in bootstrap. Using HTML, we’d define a Bootstrap menu like so:

<ul class="nav navbar-hav">
  <li class="active"><a href="#home">Home</a>
  <li><a href="#about">About</a>
</ul>

Using Fluent, we can use to generate the same HTML code like so:

	...
	Fluent ul = body.ul("nav navbar-nav");
	ul.li("active").a(null, "Home", "#home", controller::onMenuHome);
	ul.li(null).a(null, "About", "#about", controller::onMenuAbout);

The variable body is a static import from the class Fluent. Similarly, you can also use the methods console, document, and window.

Actually, the Java source code generates code doing slightly more than the HTML snippet above. It also shows how to call Java code when clicking a menu entry. In our example, an instance of a controller (controller::someMethod) takes care of the event handling.

Although not displayed in the previous snippet, there is also a class Store, maintaining a list of class Model. This traditional MVC (model-view-controller) setup is not necessary, but it turns out to be useful when writing JUnit tests.

Of course, you can also use the lambda notation too. For example, let’s create a Bootstrap form. The methods .css() and .att() are also used to show you how they work. This is basically all you need to write HTML and CSS:

Desired HTML snippet:

<div class="form-group">
  <label style="font-size: 200%" for="n">Wat</label>
  <input class="cssClass" type="text" id="n">
</div>

Generating the some code using Fluent:

Fluent div = body.div("form-group");
div.label(null, "Wat")
   .style(Style.fontSize, "200%")
   .att(Att.for, "n");
div.input("cssClass", "text").id("n").
    keydown( (fluent, keyEvent) -> {
      console.log("You typed: " + fluent.domValue());
    });

How it’s done

Of course, the Java code isn’t run in the browser. It’s compiled to JavaScript before. At this point, people often get a wrong impression when they hear which compiler is used, so let’s mention first that VertXUI has been developed using TeaVM. However, TeaVM wasn’t without flaws. In particular, there were a couple of bugs concerning Lambdas. So now VertxUI uses the cross-compiler of GWT to do that, but without using the original GWT toolkit. Don’t confuse it with Vaadin or GWT itself. VertxUI is a completely differerent, unique approach.

View on … model

The real power of Fluent shows when you are about to change the DOM – because you don’t have to. Changes are updated as efficiently as possible, comparable to ReactJS (from Facebook) which makes sure that your Facebook list of friends does not get completely re-rendered when one online status changes.

You can create a ViewOn<Model> with the .add() method. This takes two arguments: an initial model (or reference to a model) and a method translating this model to a Fluent object. For example:

Result:

<table>
  <tbody class="striped">
  (per subscribed person:)
  <tr>
    <td class="fat">*name*</td>
    <td>*quantity*</td>
  </tr>
  </tbody>
</table>

Code:

public View {
  private ViewOn<List<Person>> table;

  public void start(Controller controller){
    List<Person> initialPersons = controller.getPersons();

    Fluent middle = body.div();
    ...
    table=middle.add(initialPersons, persons -> {
      if(persons == null || persons.isEmpty()) {
        return Span("big","No people yet");
      }
      Fluent result = Table().tbody("striped");
      for(Person person:persons) {
        if(person.isSubscribed()) {
          result.tr(
              Td("fat",person.getName()),
              Td(null,person.getQuantity()));
        }
      }
      return result;
    });
  }

  public void syncPersons() {
    table.sync();
  }
}

You probably noticed the syncPerson() method. This redraws all ViewOn objects having a link to the Person entity. As said previously, you do not need a controller, but here the controller calls that method after a change. Note that it is quite easy to write quite complex user interfaces (like wizards) because you’re just declaratively writing down what your UI should look like. You can even nest ViewOn objects.

All code is pure Java, so if you prefer streams, then that is no problem. The tbody – just like a lot of other containers like tags – takes a CSS class and a list or stream of Fluent objects.

table = middle.add(initialPersons, persons -> {
  if (persons == null || persons.isEmpty()) {
    return Span("big", "No people yet");
  }
  return Table().tbody("striped", persons
      .filter(person -> person.subscribed())
      .map(person -> Tr(
          Td("fat", person.getName()), 
          Td(null, person.getQuantity()))));
});

View on … state

In the previous Bootstrap menu example, the CSS item which has the “active” class should switch to the selected one when you click on it. This is what we can call a ‘state.’ It is handy to recognize a state and to treat it as an entity which happens never to be saved into a database. You can also use ViewOn<> for a state:

String initState = "home"; // or something else which you have extracted from the URL
...
Fluent menu = body.add(initState, state -> {
  Fluent ul = Ul("nav navbar-nav");
  ul.li(state.equals("home") ? "active" : null).a(null, "Home", "#home", controller::onMenuHome);
  ul.li(state.equals("about") ? "active" : null).a(null, "About", "#about", controller::onMenuAbout);
});

JUnit – unit testing

Because Fluent has a virtual DOM internally, you can easily ‘abuse’ this for JUnit testing without firing up a browser. This is extremely fast because there is no compilation to JavaScript and there is no starting and stopping of a browser in the background.

In practice, the class Store is often mocked in JUnit tests to prevent network traffic, but in the next example we mock the Controller call directly:

class Test {

  @Test
  public void test() {
    // Fake result after some network traffic
    List<Person> persons = new ArrayList<>();
    String name = "John " + Math.random();
    persons.add(new Person(name, 2000, true));
  
    // Startup sequence
    View view = new View();
    Controller controller = Mockito.spy(Controller.class);
    Mockito.when(controller.getPersons()).thenReturn(persons);
    view.start(controller);
  
    assertEquals("1 row",1,VirtualDomSearch.getElementsByTagName("TR", body));
    List<Fluent> tds = VirtualDomSearch.getElementsByTagName("TD", body);
    assertTrue("2 columns", 2, tds.length());
    assertTrue("name test", name, tds.get(0).txt());
  }
}

JUnit – integration tests

As your project grows and starts using external JavaScript libraries, integration tests get more and more important. In Fluent you can perform dual-language tests in a headless browser with a ‘register-and-run’ construction. You have slightly more control over your runtime environment than with Selenium because you can easily run and combine JavaScript assets and Java assets together in one test-run.

As an example, we take that dull first Bootstrap menu example, and we simulate a menu click by directly calling controller.onMenuAbout(). Let’s see whether the previous example, which changes the content of the ‘active’ class, actually works. The following code is really all you need. The Java-to-JavaScript compilation happens on the fly:

class Test extends TestDOM {

  @Test
  @GwtIncompatible
  public void test() throws Exception {
    System.out.println("Java");
    runJS(100); // run slot '100'
  }

  @Override
  public Map<Integer, Runnable> registerJS() {
    Map<Integer, Runnable> result = new HashMap<>();
    result.put(100, () -> testWithDOM()); // register slot '100'
    return result;
  }

  public void testWithDOM() {
    console.log("JavaScript");
    
    View view = new View();
    Controller controller = new Controller(new StoreEmpty(), view);
    view.start(controller);

    // search the active menu item
    NodeList actives = document.getElementsByClassName("active");
    assertEquals("quantity test 1", actives.length(), 1);
    assertTrue("titletest 1",((Element) actives.item(0).getChildNodes().at(0))
      .getTextContent().equals("Home"));
    
    controller.onMenuAbout(null, null);
    
    // search again
    actives = document.getElementsByClassName("active");
    assertEquals("quantity 2", actives.length(), 1);
    assertTrue("titletest 2",((Element) actives.item(0).getChildNodes().at(0))
      .getTextContent().equals("About"));
  }
}

Notice that this example could have been put in a non-DOM test, which runs a lot faster.

VertX

You can run VertxUI in any back-end software, but together with VertX, it provides several facilities like FigWheely and POJO traffic. VertxUI with VertX is easier than easy: just start the main() and point your browser to http://localhost. You don’t have to install any IDE-plugin. Neither do you have to deal with a *.war or *.jar. Just start the main class, and you’re good to go!

VertX is completely asynchronously and works with callbacks, just like JavaScript. So, for example, it doesn’t block until TCP data has arrived, but instead it will continue to run the stack when something has arrived. The big difference is that because Java is a very structured language, you’ll never get a callback hell like in JavaScript. You will probably call another method in another class when something asynchronously has happened.

VertX – FigWheely

FigWheely is the runtime helper of VertxUI. It keeps a WebSocket open with the browser and receives notifications when files have changed on the server. If the files that have changed happen to be .java files, FigWheely will recompile your browser code and notify the browser too.

FigWheely works -just like VertxUI- without any IDE-plugin because the compilation to JavaScript happens when you start the (VertX) server and when the source code is found. During startup, a one-line index.html is also generated, but you can also turn this off to use an existing website. Or you can use HTML itself as HTML template when using jQuery Mobile.

VertX – POJO

VertxUI facilitates POJO traffic between server and browsers for ajax calls, WebSocket, sockJS, and the VertX event bus. This means strong-typed traffic, even though Json is used underneath. Having the client and server in the same language has quite some nice advantages: when you want to add a table column, it might just be adding one line of code to the entity and one line for an extra ‘TD’ in the view.

Here is a client-side example of a chat application with a POJO receiver:

WebSocket socket = window.newWebSocket("ws://localhost/chatWebsocket");
socket.setOnmessage(event -> {
  // POJO: receive the a color and put it between a new <li>...</li>
  if (POJOfy.socketReceive(urlPOJO, event, POJOMapper,
	pojo -> messages.li("colored", "Received: " + pojo.getColor()))) {
	return;
  }
  // otherwise, receive the text and put it in a new <li>..</li>
  messages.li("flat", ((MessageEvent) event).getData().toString());
});

and here is the server side, which can also receive a POJO. It looks so simple that you might forget that this is an extremely powerful web server, more powerful than a regular locking multithreaded servlet environment:

List<String> ids = new ArrayList<>(); // all ids
vertx.createHttpServer().websocketHandler(socket -> { // entering
  String id = socket.textHandlerID();
  ids.add(id);
  socket.closeHandler(data -> { // leaving
    ids.remove(id);
  });
  socket.handler(buffer -> { // receiving
    if (POJOfy.socket(socket, View.urlPOJO,buffer, Dto.class,aService::handle)){
      return;
    }
    String message = buffer.toString();
    ids.forEach(id -> vertx.eventBus().send(id, message)); // broadcasting
  });
}).listen(80);

Wrapping it up

No matter what happens in the future with the client side and the JavaScript language, you can already create very well testable single page web applications in the very grown-up language Java backed by the well developed VertX server environment and backed by any well-developed CSS framework like Bootstrap. The test facilities of VertxUI alone should be interesting enough to try out VertUI for a new project. Let alone the POJO traffic, strong-typed code, a well developed IDE, and so forth, in other words: Java.

JavaScript and its libraries will grow up, but this will take years, and the chances are small that you can pick the right libraries now and prevent refactoring and learning new language features that get deprecated before you’re used to them.

If you’re familiar with React.js or Angular, you’re used to just changing the model to update the view. Actually, this seamless integration between the view and the model made React and Angular popular. It was a major improvement over the older approach modifying the DOM manually. Changing the DOM is error-prone. Using a framework for that makes you write clean code. VertxUI brings this idea to the Java world.

Dig deeper

VertxUI
VertX

7 thoughts on “VertxUI: Java as a Front-End Language

  1. What do u think comparing to projects like zk ir vaadin? They are really mature!

    Btw i like vertx but for backend

    1. I’m sure Vaadin is mature. I can’t say anything about zk because I don’t know it yet (but I’ll bookmark it for later research).

      On the other hand, the article doesn’t claim VertxUI to be mature. Maybe it is, but most of all it’s new and widely unknown. When I invited Niels to contribute a guest article, I was under the impression that he’s created something interesting and innovative. I still am. So that’s the intention of the article: to give a new framework the opportunity to grow and rise, and to become every bit as mature as Vaadin.

      That said, I’m a bit skeptic about the future of Vaadin. More to the point, I’m skeptical about the future of GWT. GWT is a great framework that’s been overtaken by the client-side frameworks. Maybe – just maybe – this results in Google dropping it one day or another. Vaadin is built on GWT, so things become interesting at this point. No idea what’s going to happen. Maybe the Vaadin team continues the GWT work, or maybe they won’t.

      BTW, that’s also a topic for VertxUI, but it’s more independent. It only relies on the GWT cross-compiler. So even if Google drops GWT, VertxUI continues to work. Maybe it doesn’t support the latest Java version, but it’s still functional. Plus, there are other Java-to-JavaScript compilers, so maybe Niels finds an alternative to the GWT compiler. Cutting a long story short: GWT is a great tool, but in the case of VertxUI, is a tool which probably can be replaced by other tools if need be.

      1. First of all: VertxUI is not bound to GWT. Actually, I switched to GWT in a few hours in the last part of developing VertxUI, because it was the best and only bug-free java to javascript compiler I could find. VertxUI was first developed by using TeaVM as the java-to-javascript compiler. However, TeaVM has some bugs in the implementation, especially with the lambda notation. I also tried jSweet (took me about one hour), that is nice but it doesn’t support a whole range of Java language constructs.

        So to say, VertxUI is not comparable to any of the GWT frameworks. At all. It’s not even related.

        The biggest difference is that these frameworks have a very complex way of showing the user interface in terms of HTML and CSS. Big beasts. Some of them are still using tables for layout, and it is difficult to write something outside of the framework. That’s because everything is done for you. That has it advantages, but don’t try to do anything outside it.

        Vaadin and GWT are also beasts on the back-end side. You’re stuck on using a servlet-based container to begin with, and choosing which database -or how to interact with it- is also pretty much defined for you.

        That being said, I think the big difference is that with VertxUI you not bind to anything except the browser. You are always using external libraries (or none) for the UI, and there is more freedom on the back-end side. Is there a new Bootstrap version? No worries, you can easily shift to it. You just want to write some plain HTML? Well, VertxUI cán only write HTML, so go ahead. Use a new Amazone service for storing? Do your thing!

  2. Yes that would be no problem. However the runtime part (Figwheely) will not be spinned. I guess I shortly have to provide an implementation for that.

  3. Actually, I found several bugs with lambdas. We mailed with each other, but at one point there was no reply anymore. I switched to GWT and that was a success. It’s a lot slower (say 10 seconds instead of 2), but only using the Elemental stuff means only one compile round and not much overhead in the resulting .js at all (it’s all optimized away in the compilation process I guess). I can quite easily put VertxUI back to TeaVM, so I might do that in a later version, but not before fulfilling a long list of requests first (integration with SpringMVC, some specific examples etc).

Leave a Reply

Your email address will not be published.