5 Introduction to Nashorn JavaScript Engine
Nashorn JavaScript engine enables running JavaScript directly in the database. The ability to reuse existing client-side JavaScript in the database, and then combining it with the Java SE libraries, enables the design of rich, powerful, and versatile data-bound applications that can run directly in RDBMS sessions. This section describes the Nashorn JavaScript Engine in the following sections:
5.1 About Using Nashorn JavaScript Engine
One of the important features of Java 8 is the Nashorn JavaScript engine. Starting from Oracle Database 12c Release 2 (12.2.0.1), Oracle JVM supports Java 8, so you can execute JavaScript in the database using the Nashorn JavaScript engine, built into Oracle JVM running Java 8 codebase. Executing JavaScript directly in the database provides the following benefits:
Benefits of Running JavaScript in Oracle Database
-
Reusing existing skills and code.
-
Avoiding shipping data residing in Oracle Database. Executing JavaScript in the database enables in-place and faster processing of JSON documents inside the database. This enables avoiding shipping data to external infrastructure and improving performance as network overhead is avoided.
-
Achieving new database capabilities.
For running JavaScript code, using the Nashorn engine of 12.2 Oracle JVM in your sessions, your schema must be granted the DBJAVASCRIPT role. This role includes the permissions that are required to run Nashorn in the database. The role can be granted by your DBA and must be done only once per user.
The preferred way to maintain JavaScript sources in Oracle Database is to load them into your schema as Java resources and then run the scripts within the database.
Note:
-
The direct invocation of Nashorn classes is restricted in Oracle JVM.
-
All scripting mode extensions are disabled in Oracle JVM.
-
You can run scripts either from strings or from file streams, using standard scripting APIs, but Oracle does not recommend it. Scripts invoked in this way can run only in sandboxed mode, with the default permissions.
5.1.1 Loading JavaScript Code into a Schema
Use the loadjava
command to load your JavaScript code into your database schema. Scripts are loaded as Java resources. For example, suppose you have a JavaScript file hello.js
as follows:
function hello()
{
/*
*This is a sample Javascript file that prints "Hello World".
*/
var hellow = "Hello World";
return hellow;
}
var output = hello();
print(output);
Use the following command to load the hello.js
script file into a schema named yourschema
:
loadjava -v -u yourschema hello.js
The loadjava
command prompts you for a password and then creates a schema-local resource hello.js
with the following output:
arguments: '-u' 'yourschema/***' '-v' 'hello.js'
creating : resource hello.js
loading : resource hello.js
Classes Loaded: 0
Resources Loaded: 1
Sources Loaded: 0
Published Interfaces: 0
Classes generated: 0
Classes skipped: 0
Synonyms Created: 0
Errors: 0
You can also use the following command to verify whether you have successfully loaded the hello.js
file into the database or not:
select object_name, object_type from user_objects;
This resource can then be passed to the Nashorn engine using the ways mentioned in the following sections:
5.1.2 How to run JavaScript in Oracle JVM
After loading the scripts in the database, you can run them in the following three ways:
5.1.2.1 Using the DBMS_JAVASCRIPT.RUN PL/SQL Procedure
This approach is useful for JavaScript procedures that do not return any value. Invoke the DBMS_JAVASCRIPT.RUN
procedure for providing the resource name as the argument. Make sure that your schema is granted the DBJAVASCRIPT
role. The DBMS_JAVASCRIPT.RUN
procedure is a wrapper for the oracle.aurora.rdbms.DbmsJavaScript.run
Java method, which invokes Nashorn functionality internally.
From SQL
call dbms_javascript.run('hello.js');
If your JavaScript code returns an output value, then you must use the following instructions to display the value on the standard output device:
SQL>set serveroutput on
SQL>call dbms_java.set_output(20000);
SQL>call dbms_javascript.run("hello.js");
From PL/SQL:
dbms_javascript.run('hello.js');
If your JavaScript code returns an output value, then you must use the following instructions to display the value on the standard output device:
SQL>set serveroutput on
SQL>call dbms_java.set_output(20000);
SQL>call dbms_javascript.run("hello.js");
5.1.2.2 Using the DbmsJavaScript Java Class
This is the preferred way to invoke the scripts from Java code in Oracle JVM because it enables you to apply the schema permissions to the JavaScript code. Invoke the JavaScript that you loaded as resource hello.js
from your Java code running in the database. Invoke the method run of oracle.aurora.rdbms.DbmsJavaScript
class, passing in the resource name as the argument, as shown in the following code snippet:
Note:
Make sure that your schema is granted the DBJAVASCRIPT
role.
import oracle.aurora.rdbms.DbmsJavaScript;
…
DbmsJavaScript.run("hello.js");
5.1.2.3 Using the Standard javax.script Java Package
This approach is useful for JavaScript functions that return values. Typically, you perform the following tasks:
Note:
You must make sure that your schema is granted the DBJAVASCRIPT
role.
-
Load the JavaScript in the database as a Java resource, using the
loadjava
command. -
Use the
javax.script
package to run the JavaScript. -
Instantiate a script manager
-
Create an engine
-
Pass your resource stream reader as the argument to the
eval
method of the engine
The following code snippet shows how to use the javax.script
package to run code from resource hello.js
:
import javax.script.*;
import java.net.*;
import java.io.*;
...
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine =
factory.getEngineByName("javascript");
// create schema resource URL
URL url = Thread.currentThread()
.getContextClassLoader().getResource("hello.js");
engine.eval(new InputStreamReader(url.openStream()));
...
You can also read the JavaScript code from a String. The following code snippet shows how to read and evaluate JavaScript code from a String:
// evaluate JavaScript code from String
engine.eval(new StringReader(<script>));
Otherwise, you can also read the JavaScript code from a file. However, this involves extra privileges. The following code snippet shows how to read and evaluate JavaScript code from the script_name
file:
import javax.script.*;
...
ScriptEngine engine = new ScriptEngineManager()
.getEngineByName("JavaScript");
engine.eval(new FileReader("script_name"));
After evaluating the JacaScript code, you typically perform the following tasks for invoking JavaScript functions:
-
Cast the Nashorn engine to
Invocable
and useinvokeFunction
.For example, if the
hello.js
script defines a JavaScript function namedhello
, then you can perform these tasks as shown in the following code snippet:// create a JavaScript engine as above Invocable invocable = (Invocable) engine; Object myResult = invocable.invokeFunction("hello"); ...
Note:
An alternative way to use the
invocable.invokeFunction
is to pass the return value to a Java method invoked from inside of a script. This alternative way is preferable as it requires less boilerplate code and is compatible with theDBMSJAVASCRIPT.RUN
procedure.For example, suppose your JavaScript resource
hello.js
defines theselectQuery
function, and you want to pass the result to theprint()
Java method, which is defined in your classQueryTest
as follows:public static void print (String results) { System.out.println("my results: \n" + results); }
Then, to achieve this from JavaScript, add the following lines to the
hello.js
file:var queryTest = Java.type("QueryTest"); queryTest.print(selectQuery("all"));
Now, invoke
hellp.js
in one of the following ways:DbmsJavaScript.run("hello.js"); DBMS_JAVASCRIPT.RUN('hello.js');
-
Create a PL/SQL procedure for invoking the JavaScript application, as shown in the following example:
-- Create a procedure for select CREATE OR REPLACE PROCEDURE selectproc(id IN varchar2) IS output varchar2(10000); BEGIN SELECT invokeScriptEval(id) INTO output from dual; htp.prn(output); END; / SHOW ERRORS;
5.2 JavaScript Data Access using JDBC
Related Topics