Develop powerful Serverside Javascript with UndertowJS

Today I’m going to write about Undertow.js which provides Server Side Javascript to WildFly application server.

Nowadays many Javascript Frameworks like AngularJS and BackboneJS make it easier to create a single page web application. They structure the JavaScript code and offer a toolset of important functions to boost the development of applications. Rendering the application on the client side can be cumbersome however and, most important, its performance is dependent on the device you are using for rendering the page. A huge benefit of server side rendering is that you have full control over the server and the hardware used to produce the response.

So come the project Undertow.js which proposes to serve server side Javascript thanks to its Nashorn JavaScript engine built into the JDK. Undertow.js is not intended to full replace the Server Side API but to reduce the complexity of it by wrapping some techologies such as Servlets or REST Services in a few lines of Javascript code. Undertow.js ships with WildFly 10 and it consists of a tiny JAR file packaged under modules/system/layers/base/io/undertow/js/main/undertow-js-1.0.1.Final.jar

Let’s try it.

1) Download and install WildFly 10 (A Beta1 release is the minimal requirement)

2) Next create a Web project

3) Within this project, you will need to declare your Undertow.js resources in a file named undertow-script.conf under WEB-INF

Our first example will be named hello.js therefore include in the file undertow-script.conf the following text:

hello.js

Now create the file hello.js in the webcontent folder of your application. We will add the following Hello World code:

$undertow
          .onGet("/hello",
              {headers: {"content-type": "text/plain"}},
              [function ($exchange) {
                  return "Hello World UndertowJS";
              }])

$undertow is the entry point for this library: it contains methods to register HTTP handlers, as well as some other utility methods. In our example, the onGet method registers a handler for GET requests.

Here is a snapshot of your project:

undertow tutorial

Deploy the Web application on WildFly and test it. If you have chosen the “web” context for your application you should see an “Hello World Undertowjs” at the following URL: http://localhost:8080/web/hello

Ok, so far we have just scratched the surface of the Undertow.js. A more complex example shows how to interact with a resource available in the JNDI tree, such as the ExampleDS Datasource and use it to perform a Query on the Database.

$undertow
          .onGet("/rest/db",
              {headers: {"content-type": "application/json"}},
              ['jndi:java:jboss/datasources/ExampleDS', function ($exchange, db) {
                  return db.select("SELECT * FROM INFORMATION_SCHEMA.TABLES");
              }])

In this case, the jndi prefix retrieves the Datasource mapping it as a “db” object which is returned as a JSON string.

The jndi is not the only object which is available in the context of Undertowjs, as a matter of fact you can also use:

The cdi object to inject your CDI Beans in the Undertow Handler as a parameter

The entity object to inject your entity as parameter of the function

The following example shows how you can use CDI objects produced on the Server side. Let’s say you are producing the EntityManager named as “em” on the backend:

import javax.enterprise.inject.Produces;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class Resources {

    @Produces
    @PersistenceContext
    private EntityManager em;

    @Produces
    @Named("em")
    public Object getEntityManager(EntityManager em) {
        return em;
    }
 

}

Now you can reuse it to perform a NativeQuery on a table as follows:

$undertow

.onGet("/rest/members", {headers: {"content-type": "application/json"}}, ['cdi:em', function ($exchange, em) {

return JSON.stringify(em.createNativeQuery(" select name from table").getResultList());

}])

So far we have gathered get request; we can obviously use the other HTTP method like in the following example, which overrides the function with the form element that will contain the post parameters:

$undertow
 .onPost("/insert", ['db', '$entity:form', function($exchange, db, form) {
       try {
         var name = form['name'];
         var surname = form['surname'];
         var email = form['email'];

         db.query("insert into users (name, surname, email) values (?,?,?)", name, surname, email);

        } catch (e) {
            alert(e);
             
        }

Autodeploy of resources using Undertow.js

The last feature we will explore is the autodeploy of resources which enables autoreloading of Web contexts (including both Undertow.js pages but also any web content such as HTML, CSS, Javascript) from a path on your file system.

The hot deploy of web resources is also available in an exploded WildFly development, however it is limited just to standalone mode.

In order to achieve it, create a file named undertow-external-mounts.conf where you will state the mount point for your web context. Here is the new project structure:

undertow tutorial

And include the path in undertow-external-mounts.conf:

/home/jboss/undertowjs/web/src/main/webapp

Within this path, we will create a resource named local.js:

$undertow

.onGet("/myfs/local", {headers: {"content-type": "text/plain"}},
     [function ($exchange) {
          return "Hello World from my filesystem";
}])

As this is an Undertow.js resource, remember to include it in your undertow-script.conf. Not needed for other HTML components.

Et voilà! Now your Undertow.js resource is available at the root context of the server at http://localhost:8080/myfs/local

If you want to learn more about Undertow.js I suggest having a look at the Kitchensink project rewritten to use Undertow.js:

https://github.com/undertow-io/undertow.js-examples/tree/master/angular

I wanted to thank you Stuart Douglas for the hard work done on the Undertow project and for his collaboration in writing this article.

Found the article helpful? if so please follow us on Socials