Design and build a collaborative user experience for a chance to win cool prizes!
Blog

Calling Java from JavaScript

By  
Alejandro Duarte
Alejandro Duarte
·
On Oct 22, 2019 6:42:00 PM
·

In this step-by-step tutorial, you will learn how to use Vaadin to call server-side Java code from client-side JavaScript code. All you need to follow this tutorial is a basic understanding of the Java Programming Language, the fundamentals of JavaScript, JDK 8 or later, and a Java IDE.

Typically, applications make server-side Java methods available to the client-side by exposing them as end-points in a REST web service. Although this is a perfectly valid approach, this tutorial shows an alternative way to call Java methods on the server without having to implement web services. This is possible thanks to Vaadin, a framework that incorporates a set of Java classes that, not only allows you to build web UIs in plain Java, but also includes an automated communication mechanism that makes calling Java methods from JavaScript straightforward.

You can find the source code for this tutorial on GitHub.

Setting up the project

  1. Go to this page.

  2. You’ll see a form to generate an app. For Group ID type com.example and for App Name, calling-java-from-javascript:

Starter page
  1. Click the Download button, and extract the generated ZIP file.

  2. The ZIP contains a Maven project. Import the Maven project into your favorite IDE (see the instructions for IntelliJ IDEA, Eclipse, and NetBeans). This project is a simple starting point for developing a Java web application with Vaadin.

Don’t worry if you are not familiar with Maven. Most IDEs have excellent support for Maven, to the point you don’t need to understand all its details to use it. If you want to learn more about the key concepts in Maven, see this article.
  1. The starter creates a simple "Hello, World" application we don’t need right now. We want to keep the project as simple as possible, so go ahead and delete the MainView class and the resources, frontend/src, and frontend/styles directories (keep the frontend directory). The directory structure should look like this:

Directory structure

Now we have a clean starting point with no distracting code. Let’s start hacking!

Creating an empty web page

Java web applications are implemented through Servlets. A Servlet is a class that enhances the functionality of a web server (which usually only serves files such as HTML documents and images). This enhancement could include any kind of server-side logic, for example, dynamically creating an HTML document to include content from a database. When you include Vaadin in your project, a VaadinServlet is automatically created for you. This servlet allows us to create a web page using plain Java.

If you want to see where this auto configuration happens, take a look at the ServletContextListeners class.

To see this in action, create a new class with the name MainView inside the com.example package:

src/main/java/com/example/MainView.java
package com.example;

public class MainView {
}

We want to expose this class as a web page in the browser. Since we have Vaadin in our project and it creates a VaadinServlet all we need to do is annotate the previous class with @Route and make it extend a UI component such as Div:

MainView.java
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.router.Route;

@Route
public class MainView extends Div {
}

By default, the @Route annotation makes Vaadin map the class with the context root when the annotated class is named MainView. So when http://localhost:8080/ is requested, the MainView class will have the chance to perform any logic on the server side. If we wanted to map the class to http://localhost:8080/example, we would need to say it explicitly with @Route("example").

If you run the project at this point, you will get an empty web page. Let’s confirm this by executing the Maven Jetty Plugin. If you have Maven installed in your machine, just run mvn jetty:run in the command line. If you are using an IDE, create a run configuration for the jetty:run goal. See the detailed instructions for IntelliJ IDEA, Eclipse, and NetBeans.

The Jetty Maven Plugin is configured in the pom.xml file. This plugin allows us to easily deploy the web application to a Jetty server without having to install it manually.

Point your browser to http://localhost:8080 to see the empty web page. Nothing exciting just yet, but you have a running Java web application ready.

Calling JavaScript

Before calling Java from JavaScript, we need to set up the JavaScript file itself. Create a new file with the name script.js in the src/main/webapp/frontend/ directory and code a simple function in it:

src/main/webapp/frontend/script.js
function greet(name) {
console.log("Hi, " + name);
}

We need to import this file in the Java class. Annotate the MainView class with @JavaScript as follows:

MainView.java
@JavaScript("frontend://script.js")
@Route
public class MainView extends Div {
public MainView() {
}
}
frontend:// is used to reference the directory where static resources are. This is useful when transpiling JavaScript code to support older browsers, for example.

With the JavaScript file loaded, we can call the greet function in the constructor as follows:

MainView.java
public MainView() {
getElement().executeJavaScript("greet('client')");
}

The getElement() method returns a Java representation of the <div> element in the DOM. There a small improvement we can make to this line of code. We can separate the argument values from the function call and get the same behavior:

MainView.java
public MainView() {
getElement().executeJavaScript("greet($0)", "client");
}

Try the application now. Stop the server and rerun it (using the run configuration in your IDE or mvn jetty:run in the command line).

You should see the greeting in the browser’s console:

Greeting the client

Calling Java

Now that Java to JavaScript is working, let’s complete the circle by calling a Java method from a JavaScript function. First, we need a Java method. Let’s implement a server-side Java version of a greeting by adding the following to the MainView class:

MainView.java
public class MainView extends Div {
...

public void greet(String name) {
System.out.println("Hi, " + name);
}

}

Now we need to expose this method to the client-side by annotating the method with @ClientCallable:

MainView.java
@ClientCallable
public void greet(String name) {
System.out.println("Hi, " + name);
}

To invoke this method from the client side, we need the reference that the Java getElement() method returns. We can send it to the JavaScript function by modifying the constructor of the MainView class as follows:

MainView.java
public class MainView extends Div {

public MainView() {
getElement().executeJavaScript("greet($0, $1)", "client", getElement());
}

...
}

Notice how we added the argument to the function call ($1) and how we added the actual value as an extra argument in the call to the executeJavaScript method.

Now we can accept this value in the client side JavaScript by adding a parameter to the greet function as follows:

script.js
function greet(name, element) {
console.log("Hi, " + name);
}

The element object includes a $server member that we can use to call the server-side Java greet method. Here’s how:

function greet(name, element) {
console.log("Hi, " + name);
element.$server.greet("server");
}

Restart the Jetty server again and try the application to see the greeting in the server’s log:

Greeting the server

What’s next?

So, the circle is closed–we called JavaScript from Java and Java from JavaScript without using REST Web Services. If you followed this tutorial, you might already have ideas on what to try next. You might want to try adding some CSS (you can do it with something like @StyleSheet("frontend://styles.css")), or you might want to add your own JavaScript and Java business logic.

However, Vaadin is much more than a library to connect JavaScript with Java. As you can imagine, Vaadin’s automated communication mechanism can be used to generate powerful web user interfaces. Well, Vaadin allows you to do so in Plain Java! For example, try modifying the MainView class to the following:

@Route
public class MainView extends Div {

public MainView() {
Button button = new Button("Greet");
button.addClickListener(event -> {
LocalTime now = LocalTime.now();
Notification.show("Hi! The time in the server is " + now);
});
add(button);
}

}

Without coding any JavaScript at all you get this HTML-based web application in the browser:

Web application implemented with Vaadin

 

If you want to learn more about this, try the tutorial at https://vaadin.com/docs/latest/flow/guide/quick-start!

Alejandro Duarte
Alejandro Duarte
Software Engineer and Developer Advocate at MariaDB Corporation. Author of Practical Vaadin (Apress), Data-Centric Applications with Vaadin 8 (Packt), and Vaadin 7 UI Design by Example (Packt). Passionate about software development with Java and open-source technologies. Contact him on Twitter @alejandro_du or through his personal blog at www.programmingbrain.com.
Other posts by Alejandro Duarte