The Adventures of Blink #24: Javascript? Ain't Nobody Got Time Fo Dat
Tags: vaadin, webdev, java, tooling
Published: 2024-05-23 11:00:00

I have a confession.

I hate javascript.

I don't really know why.  Maybe it's because it says "java" in the name and doesn't even vaguely resemble Java.  Maybe it's because an entire new js framework that EVERYONE ABSOLUTELY MUST LEARN is released about every 27 seconds.  Maybe I'm disappointed that I have to buy another hard drive every time I run `npm install` because I have to download the freakin' UNIVERSE in order to Hello World.  Maybe my brain is just too slow to fully grok the idea of async calls and promises.  Maybe I'm just old and grouchy.

But I hate it.  I've tried a couple of times to pick it up - with React, and then Vue, and then straight Node.js.  And I was kinda able to be sort of ok with it, but I just feel like it makes me exert more effort than the reward I get from writing in it.

Go ahead, unfollow me. I know how Holy Wars are fought in Dev Circles. 🤷🏽‍♂️ 

The problem with hating javascript, of course, is that so many things are written in it.  I mean, it's pretty much the default language of websites, and... this internet thing doesn't seem to be a passing fad, does it?

So imagine how excited someone in that mindset gets if they hear that a product allows you to build web apps... in Java... without using javascript for anything.

![Gene Wilder as Willy Wonka - Meme that says Go on, I'm listening](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rggim6az1968khfxgd1d.png)

When I first encountered [Vaadin](https://vaadin.com/), it really intrigued me.  It's always bothered me that for a Java programmer to make an app based in the browser, they had to learn HTML and Javascript to actually finish the project.  Why the heck couldn't we just do it all in a single language?  Why all this front-end voodoo?  

Vaadin provides a large library of website components, free & open source, for you to be able to build in 100% Java.  There are some "special" components that are in a paid tier, but you can do a **lot** with just the free ones.

## TL:DR
Don't feel like reading the whole post?  Don't worry, I've got you!  Here's the youtube edition, go give me a like and a subscribe there:

{% embed https://www.youtube.com/watch?v=0I7WO_BpqnA %}

## Talk is Cheap, Ben.  

Let's go try it out, shall we?  To get started, you can pull down their example project from their [quick start page](https://vaadin.com/docs/latest/guide/quick-start)... or you could roll your own!  Vaadin has a maven repository you can use:

```xml
   <repositories>
        <repository>
            <id>Vaadin Directory</id>
            <url>https://maven.vaadin.com/vaadin-addons</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
```

The [Vaadin docs](https://vaadin.com/docs/latest/configuration/maven) have extensive information about what's available through their maven plugin.  

But for today's adventure, let's see what happens when we build from the sample project!

## Prerequisites

In order for this demo to work, you have to have your dev environment already set up to work in Java.  This means:

- Have a JDK installed correctly.  Instructions for this vary by platform, but [here](https://docs.oracle.com/en/java/javase/21/install/index.html) are Oracle's instructions for the "big 3".
- Have [Apache Maven](https://maven.apache.org/install.html) installed correctly.

> Please note that these instructions will result in the creation of extra entries in your system's `PATH` environment variable, as well as a need to create two new environment variables in your system's shell: `JAVA_HOME` and `M2_HOME`.  `JAVA_HOME` of course points to the folder where your JDK is installed (Specifically to `/Contents/Home` within the JDK folder).  Note that this path is different from what's put in the `PATH` variable - that will use `JAVA_HOME` + `/bin`.  `M2_HOME` points to wherever you installed maven.  Old hands with Java will probably be well aware of this but I was a newbie once upon a time and it took me a lot of reading to get someone to explain it effectively!

Once you have those things installed, you grab your IDE of choice (Eclipse?  IntelliJ?  VSCode? I'm not getting into that Holy War 😜) and open the project folder wherever you extracted it.

## There were... some slight modifications

The Vaadin tutorial provides you with a simple "todo list" web page - You can add items to the list, it creates an entry on the list with a checkbox. The data doesn't get stored anywhere, and the components aren't really connected to anything... just a quick place to start your tutorial.

I elected to go off the beaten path because I like to try weird stuff.  So I'm going to make my web page play Tic-Tac-Toe!

## This is gonna be a long blog post, blink

No, I promise to stay on topic!  We aren't going to talk about any of the implementation of the Tic-Tac-Toe game - suffice to say I made a few classes that handle the logic of the game and feed information back to an interface (which we're going to build *really* quickly in Vaadin!).  If you'd like to see the code, [I've posted it on my GitHub](https://github.com/LinkBenjamin/vaadin-tic-tac-toe).

## How to Vaadin

Vaadin's claim to fame is that you can make elegant web frontends without writing Javascript.  So here's mine, for playing tic-tac-toe.  We'll talk through it line-by-line so you can see how it works:

```Java
@Route("") 
```
Route defines the url that your user will use to reach this class.  This one is blank, so it's the root of my site (`http://localhost:8080/`, for the local dev copy).  If I wanted to have this class reached by `http://localhost:8080/tictactoe`, I'd change this to 
```Java
@Route("tictactoe")
```
which is something I actually tried at one point, and it was literally a single change to update the Route.  Sickeningly intuitive.

```Java
public class MainView extends VerticalLayout { 
```
Here we're defining that our class defaults to a vertical layout.  That is, when you tell it to display multiple Vaadin components on the page, it will stack them vertically by default.
```Java
  Game game = new Game();
  H3 turn = new H3("Click a button to play an X");
```
Here I'm creating an object to hold my game logic, and making a class variable to hold a text object that I'm going to update.  You'll notice the Vaadin component is called H3... because it displays the same as an HTML `<h3>` tag.
```Java
  public MainView() {
    
    VerticalLayout buttonBoard = createButtonBoard();
```
Ok, this one's kinda cheating.  I built the "buttonBoard" object in a method to keep my constructor smaller.  I'll show you that code in a bit.
```Java
    add( 
      new H1("Tic-Tac-Toe!"),
      turn,
      buttonBoard
    );
  }
```
Here's the instructions to render the page.  We're going to display (in `<h1>`) Tic-Tac-Toe!, then below that we'll show the `<h3>` line that prints whose turn it is, and below that, the buttonBoard.

Easy-peasy.

## What's a buttonBoard?

The buttonBoard is a collection that I built in a VerticalLayout so that I'd have the Tic-Tac-Toe board declared as 9 buttons, on 3 rows of 3 buttons each.  Here's the `createButtonBoard()` method I called earlier:

```Java
private VerticalLayout createButtonBoard() {
    Button[] buttons = new Button[9];
    
    for(int x=0;x<9;x++) {
      buttons[x] = new Button();
      buttons[x].setId(String.valueOf(x));
      buttons[x].addClickListener(event -> {
        event.getSource().setText(game.whoseTurn());
        game.play(Integer.parseInt(event.getSource().getId().get()));
        turn.setText("Click a button to play an " + game.whoseTurn());
        event.getSource().setEnabled(false);
        if(game.isGameOver()){
          for (int y = 0; y < 9; y++){
            buttons[y].setEnabled(false);
          }
          if(game.whoWon() == "X" || game.whoWon() == "O") 
            Notification.show("Game is over - " + game.whoWon() + " wins!  Refresh the screen to play again!");
          else  
            Notification.show("Game is over - outcome is a draw! Refresh the screen to play again!");
        }
      });
    }

    HorizontalLayout row1 = new HorizontalLayout(
      buttons[0],
      buttons[1],
      buttons[2]
    );

    HorizontalLayout row2 = new HorizontalLayout(
      buttons[3],
      buttons[4],
      buttons[5]
    );

    HorizontalLayout row3= new HorizontalLayout(
      buttons[6],
      buttons[7],
      buttons[8]
    );
    
    return new VerticalLayout(
      row1,
      row2,
      row3);
  }
```

Here are the important notes:

- We declare the Layouts much like you'd expect.  Note I use a `HorizontalLayout` for each row so that I can put 3 buttons on each, and then assemble the 3 `HorizontalLayout` rows into one `VerticalLayout`.  That's how you stack them so that you get all the buttons lined up neatly like a tic-tac-toe board.

- The other interesting part of this is the section with the click listener:

```Java
buttons[x].addClickListener(event -> {
        event.getSource().setText(game.whoseTurn());
        game.play(Integer.parseInt(event.getSource().getId().get()));
        turn.setText("Click a button to play an " + game.whoseTurn());
        event.getSource().setEnabled(false);
        if(game.isGameOver()){
          for (int y = 0; y < 9; y++){
            buttons[y].setEnabled(false);
          }
          if(game.whoWon() == "X" || game.whoWon() == "O") 
            Notification.show("Game is over - " + game.whoWon() + " wins!  Refresh the screen to play again!");
          else  
            Notification.show("Game is over - outcome is a draw! Refresh the screen to play again!");
        }
      });
```
As I initialize the buttons, I'm able to declare this Click Listener dynamically using the `->` operator.  This Listener is effectively an inline method that defines what to do if this button gets clicked (we can tell which button was clicked by getting its `Id` value from `event.getSource()`.

## Running the code

The tutorial comes with instructions about how to run the code in `README.md` but the short version is that there's a script included (`mvnw`) which you can run to start things up.  Try it out!

## Wrapping up

I was a little skeptical of a product that made the claims Vaadin makes... but I'm pretty pleased that I spent about twice as long coding up the Tic-Tac-Toe classes as I did figuring out an interface I'd never used before.  This project took me about 3 hours total, with ZERO prior Vaadin experience.  

With a large library of components, Java developers don't have to worry about separating backend and frontend along linguistic barriers.  Pretty freakin' cool.

I hope you've enjoyed this look at Vaadin!  Tune in for next week's Adventure, when we finish out the "How to Win with Devs" series on the topic of "Building Excitement"!