The JVM Fanboy Blog 

Entries tagged [nashorn]

WildFly & Nashorn part 1: Hello world!

by vincent


Posted on Thursday Sep 15, 2016 at 12:46AM in Nashorn


Red-Hat released version 10.1 of their WildFly application server recently.

WildFly is Red-Hat's open-source Java Enterprise Edition application server, which implements the Java EE 7 Full and Web Profile standards. This is a huge difference with the popular Apache TomCat server, which only implements the Servlet Container part of the Java EE specs (but, note that there's also the TomEE project, which makes TomCat a full Java EE application server. Likewise, I should also mention that there's a distribution of WildFly available that only implements the Servlet Container standard!)

As far as I can tell, version 10 of WildFly is not yet Java EE certified by Oracle. The last certified version seems to be WildFly 8. Still, it's definitely one of the more interesting application servers on the market, though.

Introducing Undertow and Undertow.js

Undertow is the name of the HTTP server that powers WildFly. It is a separate project written in Java and Java applications can embed it themselves. Noteworthy is that Undertow is implemented using NIO , the high-performance non-blocking I/O API that was introduced back in Java 7.

On top of Undertow runs Undertow.js, also a seperate project, which we will concentrate on in this article. Undertow.js makes many WildFly capabilities available to server-side JavaScript scripts that run on Oracle Nashorn.

Since WildFly is implemented using Undertow and comes with Undertow.js, getting server-side Nashorn server-side JavaScript scripts to work is a relatively easy process. Undertow.js offers some convenient wrappers around Java objects and therefore, sharing and using DataSource objects to query databases, retrieving and using Java objects, etc. couldn't be much easier. Also, since WildFly, in its developer-friendly standalone mode, automatically reloads modified Nashorn scripts, changes to scripts are active immediately.

WildFly 10.1 comes with undertow-js version 1.0.2.Final, released in February 2016, which is the version I will concentrate on. Note, there's a newer Beta version on GitHub though.

Let's do the Hello World example

I plan to do more parts in this series, where we will examine more exciting Undertow.js features and will write my own tutorial code. But for now, let's get started by creating the Hello World example that I "borrowed" from the Undertow.js docs.

Download and configure WildFly 10.1

I'll assume you will run WildFly for development purposes only, on the same machine as your Java development environment. As WildFly is complex software, I'll not describe configuring WildFly with security in mind. Do not run WildFly on a server without studying the Administrator Guide.

While WildFly has extended run modes, we will concentrate on the easy-to-use and developer-friendly Standalone-mode. In this mode we have just one instance of WidFly, that runs both the administration module and the applications.

  • From the official website download page, download the latest Java EE7 Full & Web Distribution.
  • Unzip the ZIP or TGZ file to a convenient location
  • Navigate to the "bin" subdirectory.
    On Windows machines, run "standalone.bat". On Linux, run "./standalone.sh"
    Windows screenshot of WildFly that is starting
  • If everything goes as planned, you'll see messages printed to the console with the URLs of the HTTP management interface and Administration Console.

    On my machine the Administration Console URL is http://127.0.0.1:9990.

    You should also see a message that the WildFly has been started.

  • Before you can access the Administration Console, we will have to create a user that can access it.
    • In a new terminal window (or Command Window on Windows), from the same "bin" subdirectory, run the add-user.bat (Windows) or ./add-user.sh (Linux) script.
    • When prompted, type "a" (Management User) and press enter
    • Enter your username you wish to use as login and press enter
    • Enter a password and press enter, try to follow the recommendations. If you don't, you will be reminded and asked if you are really sure to continue (don't blame them when your password is hacked!)
    • Re-enter password and press enter
    • Leave the groups list empty, just press enter
    • If you made no mistakes, answer "yes" and press enter when asked if entered info is correct
    • When asked if user is going to be used to connect to another process, enter "no" and press enter
    • Then press any key to continue. A user that can login to the Administrator panel will now have been created.
  • Now you should be able to log in to the Administrator console
    • In your favorite browser, enter the URL that is shown in the terminal window (the one that runs WildFly). This is probably "http://127.0.0.1:9990"
    • When prompted enter the username and password you chose in the previous step.
    • The Management page of the Administration Console should now appear.

Develop the server-side JavaScript code

  • I'll be using Oracle NetBeans to create a new Java Web > Web Application project called "undertowjs_test".

  • We won't be deploying to WildFly using NetBeans IDE (the reason will be explained later), so I just accepted my default TomCat server.
  • On the last screen, do not choose any framework and finish the wizard.
  • In your project's "Web Pages" folder, add a new JavaScript file "main.js"
  • Enter the following code:

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

  • Some notes:

    • It creates the "/hello" endpoint and responds with a hardcoded plain text response when a HTTP GET request is received.
    • The "$undertow" object instance is created and made globally available automatically by undertow.js
    • The "$exchange" variable is not used in this example, but can be used to communicate with the server (do things like redirect, set HTTP response codes, retrieve cookies, read query parameters, etc. ). In the next part of this series I will more throughly describe it. For now take a look at the documentation if you want more information.
    • Like normal Java EE applications, endpoints are created relative to the application's context path. So in this case the endpoint will actually be "/undertowjs_test/hello"
  • Since WildFly can also serve JavaScript files for the browser, it can not know which JavaScript files are meant for the server-side Nashorn interpreter and which scripts will be served to the front-end. Therefore, you'll need to create a text file with a fixed filename to tell undertow.js which JavaScript files it should start server-side on server startup. To do this, in the Web Page's WEB-INF directory, create a new empty file and call it "undertow-scripts.conf"

  • Call the file "undertow-scripts.conf" and enter the following single line and save the file:

    
    main.js
    
    

    • Note: Since we stored main.js in the Web Pages directory, you do not need to add any path to the filename. Also note that scripts mentioned in this file are considered server-only JavaScript files. Download requests for these files will be refused.
  • Now let's build the WAR file

Deploy the WAR file to WildFly

  • Return to the browser, and in the WildFly Management start screen, click on the "Deployments" tab at the top of the screen. Then click the "Add" button.

  • In the dialog that appears, select "Upload new deployment" and click Next

  • A new dialog appears to select the WAR file. Click on "Choose File" and navigate to your NetBeans IDE "undertowjs_test" project' folder. In this directory, a "dist" subdirectory should exist where the "undertowjs_test.war" WAR file is stored. Select that file and click Next.

  • On the final screen, check the settings and click Finish. I'd recommend to keep the "Runtime name" the same as "Name".

  • If everything went well, a popup should appear for a short time telling the deployment was successful.
  • WildFly's http interface runs on 8080 at default. Now you should be able to visit the endpoint created by your Nashorn script. Visit "http://localhost:8080/undertowjs_test/hello"
  • Hopefully you'll get the "Hello World" message now

  • If you get a "Not Found" message instead, double-check you stored "undertow-scripts.conf" in the WEB-INF directory and that the file contains one line with " main.js". I've noticed WildFly will not produce errors when there are errros in undertow-scripts.conf file. If you detect an error, correct it, rebuild the project, on the WildFly Deployments tab, click "undertowjs_test" project and click on the arrow next to the name and choose "Replace", then try the URL again in the browser.

Override the server-side script directory

An interesting feature of WildFly, that I believe is only available when the server is running on Standalone mode, is that you can override the path where Undertow looks for the server-side script files.

This is very handy when developing the scripts. Since you can point WildFly to your project's workspace directory, you can immediately check changes after saving the file in NetBeans IDE (or any other editor). On each request, Undertow.js checks if the file has changed. If this is the case, the JavaScript file is automatically re-compiled by Nashorn and re-run immediately.

  • Create a new Empty File in the Web Pages' WEB-INF directory and call it "undertow-external-mounts.conf"
  • Enter the full path to your NetBeans project's "web" subdirectory of your project's source directory (the directory containing the "main.js" file.

    In my case on my Windows machine, it contains this:

    C:\Users\Vincent\Documents\NetBeansProjects\undertowjs_test\web
  • Re-build the WAR file and replace the deployment, see above for instructions on how to replace the previous deployment.
  • Now in NetBeans IDE, change the code a little bit and save the file. For instance, I've changed the message to a random quote from one of my all-time favorite B-movies:

    
    $undertow
        .onGet("/hello",
            {headers: {"content-type": "text/plain"}},
            [function ($exchange) {
                return "I am Torgo. I take care of the place while the Master is away.";
            }])
    

  • When refreshing the page in the browser, you should immediately see this change, without doing any re-deployment.

For the next part I will try to come up with more interesting examples that really demonstrate the power of undertow.js. I hope you agree WildFly is a very interesting server and its undertow.js component deserves much more attention.


Running Nashorn scripts in Ant build scripts: The basics

by vincent


Posted on Tuesday Dec 01, 2015 at 09:01AM in Build Tools


When I start a Java project that I think can confirm to the rules of Apache Maven, I use Maven to create build scripts. Nowadays this is in the majority of my web projects.

Occasionally though, there are cases where I want full control of every step and/or want to do a lot of exotic steps. In those (rare) cases, I still manually create Apache Ant XML build scripts. It has so many built-in type of tasks, most of which are easy to use. Unlike many other developers I know, I quite like Ant, especially when also using Apache Ivy for dependency management.

Checking out the new popular choice for building JVM projects, Gradle By Gradle, Inc., is another high entry on my ever -growing to-do list. Gotta love a tool that has a cursing elephant as a mascot, to illustrate the usual building frustrations ;-) . I will definitely check Gradle out soon.

As probably well known by now, I am a huge Oracle Nashorn fan. When I started working on my latest project, I figured it could be handy to run Nashorn scripts inside Ant scripts and found multiple solutions that I'd like to discuss. For now let's start with the most simple method.

Script Task

Nashorn is fully compatible with the JSR-223 (aka "Scripting for the Java Platform" standard), which Ant supports. Several enhancements were done in Ant 1.7 to this task, so I assume you use a somewhat recent Ant version.

To simply run Nashorn scripts as part of a Ant target, you can use the <script> task. You can embed the script directly in the build.xml file (yuck!) or point it to an external file containing the script.

A simple build.xml example that embeds the script in the XML file (something that I'd never do in production!)

<?xml version="1.0" encoding="utf-8"?>
<project name="VincentsProject" basedir="." default="main">

	<property name="message" value="Hello!"/>
	
	<target name="main">
		<script language="nashorn" > <![CDATA[
			print(message);
			print(project.getProperty("message"));
			print;
			print(project.name);
			print(VincentsProject.name);
			print;
			project.log("Logged from script", project.MSG_INFO);			
		]]></script>
	</target>
</project>
    

You can run the script by saving above's text in a "build.xml" file, switch to a terminal window (Command Prompt on Windows) and run "ant". The output should be something like:

Console output example

Consult Ant's Script task documentation and note some things here:

  • It would have been much, much better to store the script in an external file in a subdirectory and add a src="./build_scripts/script1.js" alike attribute to your <script> attribute.

  • Ant makes available all defined properties to the external script. That's why
    print(message), print(project.getProperty("message")) and print(VincentsProject.name)
    lines all work. You can disable this behavior by adding the setbeans=false attribute to the <script> element, in that case only the "project" and " self" variables would have been passed to the script and "VincentsProject" and "message" would not have been available.

  • You could use the language="javascript" attribute in the <script> element, but this would run Rhino on Java versions 1.6 and 1.7. It is very likely your Nashorn JavaScript script will not be compatible with Rhino, so I'd recommend to use language="nashorn" attribute, unless you are sure your script is compatible with both, or your project requires Java 1.8 or later anyway.

  • Don't worry about the "manager" attribute. Its default value "auto" should be fine. Or set it to "javax" if you're a purist. From what I understand, Apache BSF was an older scripting standard that predates and inspired the JavaX JSR-223 specification that Nashorn implements.

  • When your Nashorn script uses external Java libraries, you can add a "<classpath>" element to the <script> element, like: <classpath><fileset dir="lib" includes="*.jar" /></classpath>

  • You can also add a classpath by defining a "<path>" element in your build file under "<project>" element; and refer to this inside your script element by using the "classref" attribute. See Ant documentation for more help. Use this construction if you need the same classpath specification for multiple tasks.

  • One thing that not seems possible is to add parameters to the ScriptFactory. AFAIK it's therefore not possible to use Nashorn's shell scripting capabilities when using this Script task.

Note that you can do some funky stuff. You can implement a full Ant task that takes file sets as a parameter. I'll rewrite one of the examples from the Ant documentation in Nashorn and post it here.

In a next post about this subject, I will post about the Scriptdef task, that adds some interesting features.


Use QUnit to unit-test stand-alone Nashorn scripts

by vincent


Posted on Sunday Nov 01, 2015 at 05:09PM in Nashorn


I've been writing a lot of standalone Oracle Nashorn scripts lately. I'm just so productive when writing server-side JavaScript code, especially when I have the versatility of the Java run-time class library at my fingertips at the same time as well!

As I said in my previous post, currently IDE and tools integration leaves something to be desired for developers creating standalone Nashorn scripts . I had a small Twitter conversation that seemed to confirm this. NetBeans IDE can run Nashorn scripts when not using projects, but there is no dedicated project type for standalone Nashorn project yet.

As things stand, I currently write my Nashorn scripts still in a text editor and do not use the Java tools that I usually would have (auto-complete, integrated debugger, unit test integration, running project inside IDE...). I've learned since that other people write Java code to start and debug stand-alone Nashorn scripts (NetBeans IDE has this awesome feature where it can seamlessly debug JavaScript code when invoked from Java code) and write wrappers around their JS unit-tests so that Java code invokes it. I would do this too on bigger projects, but as my current Nashorn projects are relatively small, I chose not to follow that route just yet.

Using QUnit with Nashorn

I am a supporter of TDD (test-driven development), so I was looking for an easy-to-use JavaScript-based unit testing library that is compatible with Nashorn.

After some Googling, I found some blog posts talking about Nashorn and unit-testing. Most of them talked about what I just mentioned: wrapping Nashorn scripts in Java code. I found one interesting StackOverflow post where Christian Michon asked exactly what I was looking for. In this post, Sirko responded by suggesting using QUnit (by the JQuery Foundation team), since it can use callbacks and therefore work in any JavaScript environment.

I could not get the posted code to work with the latest release versions of Nashorn and QUnit. After some modifications I got it working and decided to post it here, perhaps it is useful for someone else.

I will evaluate other JavaScript unit-tests frameworks later, especially Jasmine caught my eye, but for now QUnit seems to work fine with my test scripts.

QUnit callbacks

QUnit has an API where callbacks can be registered for reporting single test and/or complete test suites results. Using these callbacks, it's very easy to let QUnit make use of Nashorn's print() function to print to the console. For my projects, that is currently sufficient, as I do not use CI (Continuous Integration) servers for my Nashorn projects at this time and manually run the tests from the command-line (I'd not recommend this work-flow for bigger projects, of course)

Example

Here's how I got QUnit working with Nashorn:

I could only get it to work when using the JVM-NPM project. It implements the well-known require() function from Node.js on JVM JavaScript engines (Nashorn, Rhino and the sadly seemingly inactive open-source DynJS effort)

  • In your project directory, create a "tests" directory and a tests/include directory.
  • Download the latest version of QUnit at qunitjs.com (qunit-1.20.0.js at the time of this writing). Only the .js file is needed, the .css will not be used. Place the JavaScript file in the tests/include/ directory.
  • From a command-ine window, navigate to a temporary downloads directory and type "git clone https://github.com/nodyn/jvm-npm" (requires Git, but I'm betting pretty much all developers have installed this on their system these days).
  • Copy the jvm-npm/src/main/javascript/jvm-npm.js file to your tests/include directory
  • Create a Nashorn javascript library that loads and sets up QUnit to work with Nashorn. This code has been largely based on the mentioned StackOverflow post.
load("include/jvm-npm.js");
var QUnitModule = require("include/qunit-1.20.0.js");

QUnit = QUnitModule.QUnit


QUnit.log(function(details) {
    if (!details.result) {
      var message = details.name + "\tFAIL" + details.source;
      message += " actual: " + details.actual + " <> expected: " + details.expected;
      print(message);
    }		
})


QUnit.done(function(details) {
    print("time:\t",details.runtime,"ms");
    print("total:\t",details.total);
    print("passed:\t",details.passed);
    print("failed:\t",details.failed);
})
    

Store this file in your tests/includes directory and call it "qunit-nashorn.js". It's a bit hackish, but it loads and sets up the QUnit callbacks and makes available the QUnit as a global object.

Now creating test scripts is the relatively easy part. Some dummy code that you could place in the test directory and call "dummytest.js":

load("include/qunit_nashorn.js");

var testMethod = function(b) {
    return b;
}

QUnit.test("testOK1", function(a) {
    var res = testMethod(true);
    a.equal(res, true);
})


QUnit.test("testOK2", function(a) {
    var res = testMethod(false);
    a.equal(res, false);
})


QUnit.test("testFails1", function(a) {
    var res = testMethod(false);
    a.equal(res, true);
})


QUnit.test("testFails2", function(a) {
    var res = testMethod(true);
    a.equal(res, false);
})


QUnit.load();
    

When running jjs dummytest.js from your tests directory, should result in output like:

Nashorn console output example


Oracle Nashorn + Oracle NoSQL: First steps

by vincent


Posted on Tuesday Oct 20, 2015 at 11:12PM in NoSQL Database


Learning to work with Oracle NoSQL was a high entry on my to-do list. I always figured Oracle Nashorn (the new JavaScript engine that runs on JVM and is shipped for the first time with Java 8) is an ideal language to learn and try JVM-based APIs, mainly because of the interactivity of the JavaScript language. So, I thought this would be a cool opportunity to test the Oracle NoSQL API with Nashorn.

I was absolutely not disappointed. Nashorn is, in my opinion, an excellent tool for learning new APIs

About Oracle Nashorn

First of all, I am a huge Nashorn fan. Although not as fast as Node.js (which is powered by Google's mighty V8 engine), bringing the flexibility of a modern JavaScript implementation to the JVM world was a very good idea. I love that it is part of Java 8 SE, so every Java developer that uses Oracle-based JREs or JDKs has full access to it.

The Nashorn team added extensions to the JavaScript language so that JavaScript code can make full use of existing JVM classes. Also, Nashorn is compatible with the existing JSR-223 "Scripting for Java Platform" standard, which means that the Nashorn engine can be embedded into any JVM program. Using this technique, you can embed JavaScript code in your Java 8 (and up) projects, that communicate with your objects while Nashorn executes the JavaScript code dynamically. Mind blowing IMO... :-)

Read the full article for much more background information and sample code

Read More