The First Server-Side JavaScript Engine

(Hint: It’s Not Node.js)

Published in
5 min readJun 8, 2016

--

Rhino was the first JavaScript engine developed to run in a non-browser environment. Introduced by NetScape in 1997, it was designed to run in a mixed-language environment where the host language is Java.

Eleven years later, how is Rhino still relevant to the enterprise world, where the mindshare is currently dominated by insert-your-favorite-new-client-side-JavaScript-library.js?

Relevance of Rhino in a AJAX/REST World

The reality is that most server-side enterprise applications are still written in Java. While the commitment to using Java on the server is still pretty strong, what we’re seeing loosen is the grip of server-side page technologies like JSP and ASP.

We are quickly moving towards a world where the server will still be in Java, but the client will be written in client-side JavaScript libraries, with REST being the preferred data exchange format.

In these kinds of architectures, Rhino provides the capacity to run the same code on both the server-side and client-side, simplifying maintenance. If your client-side JavaScript functions don’t refer to any browser objects, they are fair game to be run in Rhino.

Essence of Rhino

Rhino allows you to run JavaScript code from within Java programs, passing Java objects in to the script, manipulating them, and returning Java objects. This allows you to create JavaScript objects that can be returned back to the calling Java program, allowing your program to be much more dynamic than plain Java (since JavaScript is dynamically typed vs. Java which is more statically typed).

What Rhino is Not

Rhino is not a JavaScript engine running in a browser. This means it doesn’t know the browser world, including the objects and concepts which make up that world. No DOM, no window, and certainly no event handlers.

An Enterprise Usage Pattern of Rhino

The above architecture pattern can be used to run validations on both the server-side and client-side. A simple piece of code can be used to illustrate the Rhino invocation.

(The full project is located at https://github.com/objectsmiths/rhino )

Application Areas for Rhino

Following are two application areas where Rhino can be applied very effectively.

Rhino in Business Rules/Decision Tables Implementation

Most software systems have certain components which need to be driven by business rules. These could be date specific or geography specific or vendor specific. Further, these rules have effective start dates and end dates. It’s fairly easy to model these business rules as decision tables. These decision tables can be loaded from a database table and are executed by a Rhino script.

Customer box (has properties:’firstName’, ‘lastName’, ‘monthsSinceCustomer’, ‘points’)

Order (has properties: ‘orderId’, ‘orderDate’, ‘amount’)

Example Decision Table:

Note: Above table cust refers to the ‘Customer’ class, order refers to the ‘Order’ class.

A custom interpreter can be easily implemented in Rhino and can be used to execute any sort of decision tables, including tables such as the one above.

Rhino in Spread Sheets and Calculators

Calculators and Spreadsheets are ubiquitous and occur in various domains, especially in banking and insurance. (Think of your mortgage calculator, payment calculators, pay off calculators etc.) Frequently, calculators are exposed via UI (either web or a thick client such as .NET or Swing) and the same calculation need to be re-performed on the backend in the service layer. If these calculators are implemented such that the core calculation is modularized and has no UI dependencies, then Rhino can be used to execute the same code in the service layer while browser-based JavaScript can be used to execute the calculation on the frontend.

If the front end is a thick client, Rhino (for Swing) or Microsoft Jscript (for .NET) can be used to execute the same.

Important Pseudo-Code Snippets for Getting Started with Rhino

Following is a cheat sheet of pseudo-code snippets to help you get started with Rhino. This code should be executed once in the life cycle. If you are running in a container, it’s better to run this one per thread. Use of thread local variables or concurrent hash map would be preferred.

Pseudo-code snippet #1

Context context = org.mozilla.javascript.Context.enter() ;

*Get a reference to a context object that represents the runtime context of an executing script

*Context a thread safe object

Pseudo-code snippet #2

org.mozilla.javascript.Scriptable scope = context.initStandardObjects(null);

*Create a scope from the above context

Pseudo-code snippet #3

ScriptableObject.putProperty(scope, “SomeGlobalVariableWhichShouldBeAvailableToTheRhinoScript”, <some object> );

*The above pseudo code allows you to pass global variables which can be referred by //the Rhino Script

Pseudo-code snippet #4

String code = “ Read code from a JS file in to a single string. Make sure you retain the line breaks (\n) so that when an error occurs the proper line number will be printed by the Rhino engine “ ;

and

context.evaluateString(scope, code, “<cmd”,1,null);

* Above line will compile the JS code to the scope with the corresponding //context

* Following code will be executed one per request (say per servlet request)

Pseudo-code snippet #5

Let’s say the JavaScript code has a function called “performComplexCalculation

Function func = (Function)scope.get(“performComplexCalc”, scope);

Object[] args = …..// Initialize the object array with the arguments to the function

Object result = func.call(context, scope, args);

*The object conversion from JavaScript to Java (and vice versa) is handled transparently.

And now you’re getting started with Rhino!

Conclusion

In one popular vision of the ideal software world, all systems are built with a single programming language/system. However, in the real world, we have to deal with heterogeneous languages and systems. In the world of the web, JavaScript has acquired a singular importance thanks to the concepts of AJAX and REST services and upgraded browsers.

Using Rhino, we can harmonize the client-side JavaScript with server-side JavaScript and server-side Objects to achieve certain use cases which are very hard to achieve using any other techniques.

Of course if your project is lucky enough to use Node.js then none of this applies to you.

Further Reading:

Rhino Documentation is located at: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino#Rhino_documentation

For more on APIs, open source, community events, and developer culture at Capital One, visit DevExchange, our one-stop developer portal. https://developer.capitalone.com/

--

--