Tag: javascript

Server Side Java Script Nashorn, WildFly10, Undertow with MySQL (part-3)

Hi,

This is the third part of in the series of JavaScript in which we are going to see how to implement the Server Side Java Script inside the WildFly 10 Container. As we know that WildFly provides the “undertow” container inside it. Undertow is a flexible performant web server written in java, providing both blocking and non-blocking API’s based on NIO. Undertow has a composition based architecture that allows users to build a web server by combining small single purpose handlers. In order to know more about undertow please refer to: http://undertow.io/

WildFly 10 allows users to use the JavaScript on the server side with the help of the Nashorn JavaScript engine offered by JDK8. So far as part of our previous part-1 and part-2 articles we have learned about Nashorn javascript, jjs command line tool and the JSR-292 APIs which allows us to execute and javascript. If you have not gone through those articles then it is better to have a look at them before we start this demo:

Why Nashorn Java Scripting in Java8, Is it Poisonous for Java? (part-1)

JDK8 Based Nashorn JavaScript & Java to interact with MySQL Database. (part-2)

What this demo is about?

As part of this demo we will learn about the following things:

1. How to create a MySQL DataSource inide the WildFly 10 using jboss-cli.

2. How to include the *.js (java script files) inside the application in WildFly and what is the use of “WEB-INF/undertow-scripts.conf” file.

3. How to execute simple JavaScript inside wildfly/undertow.

4. How to execute Plain JDBC based java script inside the wildfly/undertow.

5. How to lookup the DataSource from the Nashorn java script and fetch customer table data from database.

6. We will also see how to use the “wildfly-maven-plugin” to deploy the Application on Wildfly.

Setting up MySQL Database

Start the MySQL database and then do the following steps which will basically do the following things:
A. Creating a simple Database with name “TestJavaScriptDB”
B. Creating a table with name “CUSTOMER”.
C. Insert some dummy records inside the “CUSTOMER” table.

mysql -u root -p 
password:


mysql> create database TestJavaScriptDB;
Query OK, 1 row affected (0.00 sec)


mysql> use TestJavaScriptDB;
Database changed


mysql> CREATE TABLE CUSTOMER (custId INT(10) NOT NULL, custName CHAR(20) NOT NULL);
Query OK, 0 rows affected (0.02 sec)

mysql> INSERT INTO CUSTOMER VALUES (1000, "MiddlewareMagic");
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO CUSTOMER VALUES (2000, "Customer-2");
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO CUSTOMER VALUES (3000, "Customer-3");
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM CUSTOMER;
+--------+-----------------+
| custId | custName        |
+--------+-----------------+
|   1000 | MiddlewareMagic |
|   2000 | Customer-2      |
|   3000 | Customer-3      |
+--------+-----------------+
3 rows in set (0.01 sec)

Creating DataSource on WildFly10 side.

Now lets create a simple MySQL datasource using jboss-cli.sh script provided by WildFly.

[standalone@localhost:9990 /] module add --name=com.mysql  --dependencies=javax.api,javax.transaction.api --resources=/PATH/TO/mysql-connector-java-5.1.37-bin.jar 


[standalone@localhost:9990 /] /subsystem=datasources/jdbc-driver=mysql/:add(driver-module-name=com.mysql,driver-name=mysql,jdbc-compliant=false,driver-class-name=com.mysql.jdbc.Driver) 
{"outcome" => "success"}

[standalone@localhost:9990 /] /subsystem=datasources/data-source="MySqlDS":add(jndi-name="java:jboss/MySqlDS",driver-name="mysql",connection-url="jdbc:mysql://localhost:3306/TestJavaScriptDB",user-name="root",password="testpwd")
{"outcome" => "success"}

[standalone@localhost:9990 /] :reload
{
    "outcome" => "success",
    "result" => undefined
}

[standalone@localhost:9990 /] /subsystem=datasources/data-source="MySqlDS":test-connection-in-pool()
{
    "outcome" => "success",
    "result" => [true]
}

Once the above jboss-cli commands are executed we should be able to see the following kind of DataSource created inside our wildfly profile (i am using “standalone.xml”).

        <subsystem xmlns="urn:jboss:domain:datasources:4.0">
            <datasources>
                <datasource jndi-name="java:jboss/MySqlDS" pool-name="MySqlDS">
                    <connection-url>jdbc:mysql://localhost:3306/TestJavaScriptDB</connection-url>
                    <driver>mysql</driver>
                    <security>
                        <user-name>root</user-name>
                        <password>testpwd</password>
                    </security>
                </datasource>
                <drivers>
                    <driver name="mysql" module="com.mysql">
                        <driver-class>com.mysql.jdbc.Driver</driver-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

Developing WebApplication containing the Nashorn Script

Now lets start developing the WebApplication so in order to do that lets create some directory structure and to understand where we are going to place which file.

Step-1). Create a directory “Part-3_WildFly_ServerSide_JavaScript” some there in your filesystem.

mkdir Part-3_WildFly_ServerSide_JavaScript

mkdir -p Part-3_WildFly_ServerSide_JavaScript/src/main/webapp/WEB-INF

Step-2). Now lets write the “hello.js” simple script inside the “Part-3_WildFly_ServerSide_JavaScript/src/main/webapp/” directory as following, Where we will define the resource uri “/hello” and its actions.

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

Step-3). Similarly we will write another javascript inside the “Part-3_WildFly_ServerSide_JavaScript/src/main/webapp/” directory with name “testDB.js”. This is a simple javascript file which uses the plain JDBC approach to interact with the Database.

//  ## JDBC Based JavaScript  ##

$undertow
    .onGet("/getCustomerRecords",
        {headers: {"content-type": "text/plain"}},
        [function ($exchange) {
            var con1 = getConnection();
            var customerData = runQuery(con1, "select * from CUSTOMER");
            return "Got Customer Data: " + customerData;
        }])
        
     
     
//  Java Script Functions  //        
var getConnection = function() {
    var Properties = Java.type("java.util.Properties");
    var Driver = Java.type("com.mysql.jdbc.Driver");
    var driver = new Driver();
    var properties = new Properties();
    var conn = null;
    try {
        properties.setProperty("user", "root");
        properties.setProperty("password", "testpwd");
        conn = driver.connect("jdbc:mysql://localhost:3306/TestJavaScriptDB", properties);
        print("****** Got the JDBC Connection : " +conn);
        return conn;
    } finally {
    }
}

// Declaring runQuery function
var runQuery = function(conA, query) {
   var result = "";
   try {
       var stmt = conA.prepareStatement(query);
       var resultSet = stmt.executeQuery();
       print("      --------------------------- ");
       while (resultSet.next()) {
          result = result + " [";
          var rowData = resultSet.getString("custId") + " - " + resultSet.getString("custName");
          print("\t" + rowData);
          result = result + rowData + "], "; 
       }
       print("      --------------------------- ");
       return result;
    } finally {
      if (resultSet)
         try {
            resultSet.close();
            print("\nResultSet Closed.");
         }
         catch(e) {}
      if (stmt)
         try {
            stmt.close();
            print("Statement Closed.");            
         } catch (e) { print( e );  }
      if (conA)        
         try { 
            conA.close();
            print( "Connection Closed." );
         } catch (e) { print( e );  }          
      }  
 } 

//  Following Cals are commended else those wil be executed as soon as WildFly startes deploying this WebApplication.
//var con1 = getConnection();
//runQuery(con1, "select * from CUSTOMER");

Step-4). As above we have seen a plain JDBC interaction based javascript. However we want to use the DataSource concept as well in order to interact with the Database. So here we will be writing another simple Hava Script file “testDataSource.js” inside the directory “Part-3_WildFly_ServerSide_JavaScript/src/main/webapp/” directory with name “testDB.js” and will performa simple JNDI lookup of the DataSource. This shows that we do not need to write so lengthy java scripts as mentioned above in order to interact with the database.

$undertow
    .onGet("/getCustomersViaDataSource",
        {headers: {"content-type": "application/json"}},
        ['jndi:java:jboss/MySqlDS', function ($exchange, db) {
            return db.select("select * from CUSTOMER");
        }])

Step-5). Lets write a simple “index.jsp” page which will have the URL of the above mentioned javascript Get Resources. Lets place this index.jsp file inside the “Part-3_WildFly_ServerSide_JavaScript/src/main/webapp” directory as following:

<HTML>
  <HEAD>
     </TITLE>Nashorn Server Side Java Script Demo Undertow/WildFly</TITLE>
  </HEAD>
  <BODY>
     <Center>

<h3>This is a simple demo explaining how to use Server Side Java Script in WildFly</h3>

       <a href="hello">Click Here to execute to "/hello" resource</a>
       <BR/><BR/>
       <a href="getCustomerRecords">Click Here "/getCustomerRecords" to access customers records from Database</a>  
       <BR/><BR/>
       <a href="getCustomersViaDataSource">Click Here "/getCustomersViaDataSource" to access customers records from Database via DataSource lookup</a>         
      </Center>      
  </BODY>
</HTML>   

Step-6). If needed then we can add the “web.xml” file inside the “Part-3_WildFly_ServerSide_JavaScript/src/main/webapp/WEB-INF” as following (in my case as i do not have anything specific to be written in this file so i am keeping a dummy file here)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> 
</web-app>

Step-7). Now the Most important part. We are going to add the file “undertow-scripts.conf” inside the “Part-3_WildFly_ServerSide_JavaScript/src/main/webapp/WEB-INF”

hello.js
testDB.js
testDataSource.js

NOTE: We need to tell WildFly/Undertow container that where to find our javascript files. So in order to do this we create a file “WEB-INF/undertow-scripts.conf”. In this file we list all our server side JavaScript files one per line. See: http://undertow.io/undertow-docs/undertow-docs-1.3.0/index.html

Step-8). Now we will simply write our Maven “pom.xml” file to build the WAR file containing all the above contents in it and it will also use the “wildfly-maven-plugin<” plugin which will help us in deploying it on WildFly (running on localhost:9990). So lets create “pom.xml” file inside the “Part-3_WildFly_ServerSide_JavaScript” directory as following:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>middleware.magic</groupId>
  <artifactId>WildFlyServerSideJavaScript</artifactId>
  <version>1.0</version>
  <packaging>war</packaging>
  <name>WildFlyServerSideJavaScript</name>
  
  <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <version.wildfly.maven.plugin>1.0.2.Final</version.wildfly.maven.plugin>
        <version.wildfly.bom>10.0.0.CR2</version.wildfly.bom>
        <version.wildfly-maven-plugin>1.0.2.Final</version.wildfly-maven-plugin>
        
        <!-- Compiler Related versions -->
        <version.war.plugin>2.5</version.war.plugin>
        <version.maven.compiler.plugin>3.3</version.maven.compiler.plugin>
        <maven.compiler.target>1.7</maven.compiler.target>
        <maven.compiler.source>1.7</maven.compiler.source>
  </properties>  
  
  
  <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.wildfly.bom</groupId>
            <artifactId>jboss-javaee-7.0-wildfly</artifactId>
            <version>${version.wildfly.bom}</version>
            <scope>import</scope>
         </dependency>
      </dependencies>
  </dependencyManagement> 

  <dependencies>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-web-api</artifactId>
      <version>7.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.37</version>
   </dependency>
  </dependencies>
  
  <build>
   <finalName>WildFlyServerSideJavaScript</finalName>   <!-- WAR name -->
   <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${version.maven.compiler.plugin}</version>
        <configuration>
          <source>${maven.compiler.target}</source>
          <target>${maven.compiler.source}</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>${version.war.plugin}</version>
        <configuration>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>
        
        <!-- The WildFly Maven Plugin deploys your war to a local WildFly container -->
        <!-- To use, set the JBOSS_HOME environment variable and run: mvn package wildfly:deploy -->
      <plugin>
         <groupId>org.wildfly.plugins</groupId>
         <artifactId>wildfly-maven-plugin</artifactId>
         <version>${version.wildfly-maven-plugin}</version>
      </plugin>
   </plugins>
  </build>
  
</project>

Building and Deploying the application

Lets build and deploy this application as following , Start WildFly default profile “standalone.xml” and open a terminal to run the maven build.

Setting up the environment:
For Unix Based OS

$ export M2_HOME=/PATH/TO/apache_maven_3.2.3
$ export JAVA_HOME=/PATH/TO/jdk1.8.0_60
$ export PATH=$JAVA_HOME/bin:/PATH/TO/apache_maven_3.2.3/bin:$PATH

$ cd Part-3_WildFly_ServerSide_JavaScript
$ mvn clean install

For Windows Based OS

$ set M2_HOME=C:\PATH\TO\apache_maven_3.2.3
$ set JAVA_HOME=C:\PATH\TO\jdk1.8.0_60
$ set PATH=%JAVA_HOME%/bin;C:\PATH\TO\apache_maven_3.2.3\bin;%PATH%

$ cd C:\Part-3_WildFly_ServerSide_JavaScript
$ mvn clean install 

Now make sure that wildfly is ruinning on localhost:9990 , run the maven build as following [mvn clean install wildfly:deploy] the wildfly:deploy task will find the running wildfly instance and will automatically deploy the WAR.


$ mvn clean install wildfly:deploy

########
OUTOUT
########
[INFO] Scanning for projects...
[WARNING] 
[WARNING] Some problems were encountered while building the effective model for middleware.magic:WildFlyServerSideJavaScript:war:1.0
[WARNING] 'dependencyManagement.dependencies.dependency.type' for org.wildfly.bom:jboss-javaee-7.0-wildfly:jar must be 'pom' to import the managed dependencies. @ line 28, column 22
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING] 
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building WildFlyServerSideJavaScript 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ WildFlyServerSideJavaScript ---
[INFO] Deleting /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ WildFlyServerSideJavaScript ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.3:compile (default-compile) @ WildFlyServerSideJavaScript ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ WildFlyServerSideJavaScript ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.3:testCompile (default-testCompile) @ WildFlyServerSideJavaScript ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ WildFlyServerSideJavaScript ---
[INFO] No tests to run.
[INFO] 
[INFO] --- maven-war-plugin:2.5:war (default-war) @ WildFlyServerSideJavaScript ---
[INFO] Packaging webapp
[INFO] Assembling webapp [WildFlyServerSideJavaScript] in [/Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/target/WildFlyServerSideJavaScript]
[INFO] Processing war project
[INFO] Copying webapp resources [/Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/src/main/webapp]
[INFO] Webapp assembled in [54 msecs]
[INFO] Building war: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/target/WildFlyServerSideJavaScript.war
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ WildFlyServerSideJavaScript ---
[INFO] Installing /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/target/WildFlyServerSideJavaScript.war to /Users/jsensharma/.m2/repository/middleware/magic/WildFlyServerSideJavaScript/1.0/WildFlyServerSideJavaScript-1.0.war
[INFO] Installing /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/pom.xml to /Users/jsensharma/.m2/repository/middleware/magic/WildFlyServerSideJavaScript/1.0/WildFlyServerSideJavaScript-1.0.pom
[INFO] 
[INFO] >>> wildfly-maven-plugin:1.0.2.Final:deploy (default-cli) > package @ WildFlyServerSideJavaScript >>>
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ WildFlyServerSideJavaScript ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.3:compile (default-compile) @ WildFlyServerSideJavaScript ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ WildFlyServerSideJavaScript ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.3:testCompile (default-testCompile) @ WildFlyServerSideJavaScript ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ WildFlyServerSideJavaScript ---
[INFO] No tests to run.
[INFO] Skipping execution of surefire because it has already been run for this configuration
[INFO] 
[INFO] --- maven-war-plugin:2.5:war (default-war) @ WildFlyServerSideJavaScript ---
[INFO] Packaging webapp
[INFO] Assembling webapp [WildFlyServerSideJavaScript] in [/Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/target/WildFlyServerSideJavaScript]
[INFO] Processing war project
[INFO] Copying webapp resources [/Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/src/main/webapp]
[INFO] Webapp assembled in [5 msecs]
[INFO] Building war: /Users/jsensharma/NotBackedUp/MM_Tests/WildFly/JavaScript/Java_8_Nashorn_WildFly/Part-3_WildFly_ServerSide_JavaScript/target/WildFlyServerSideJavaScript.war
[INFO] 
[INFO] <<< wildfly-maven-plugin:1.0.2.Final:deploy (default-cli) < package @ WildFlyServerSideJavaScript <<<
[INFO] 
[INFO] --- wildfly-maven-plugin:1.0.2.Final:deploy (default-cli) @ WildFlyServerSideJavaScript ---
Nov 27, 2015 4:18:54 PM org.xnio.Xnio <clinit>
INFO: XNIO version 3.2.2.Final
Nov 27, 2015 4:18:55 PM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.2.2.Final
Nov 27, 2015 4:18:55 PM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 4.0.3.Final
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.741 s
[INFO] Finished at: 2015-11-27T16:18:55+05:30
[INFO] Final Memory: 14M/245M
[INFO] ------------------------------------------------------------------------

Source code for this demo is present in :
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/WildFly/Java_8/ServerSideJavaScript/Part-3_WildFly_ServerSide_JavaScript
.
.
Regards
Jay SenSharma


JDK8 Based Nashorn JavaScript & Java to interact with MySQL Database. (part-2)

Hi,

As part of out previous article “Why Nashorn Java Scripting in Java8, Is it Poisonous for Java? (part-1)”, We discussed some very basics of JDK8, Nashorn Java Script and about the “$JAVA_HOME/bin/jjs” command line tool. We also learned that how we can invoke a JavaScript snippet or script file from inside a java code and Also how to use the Java APIs inside a simple Java Script code.

So now lets move a step ahead and see how to interact with the Database using Nashorn Java Script. In this demo we will extensively focus on how to use various java APIs and java packages inside the Nashorn Script.

What this demo is about?

As part of this demo we will learn about the following things:

1. How to create a Database and some sample tables in MySQL database.

2. How to write a simple Nashorn Java Script to interact with MySQL.

3. How to execute the Nashorn Script using jjs.

4. How to Invoke the Nashorn Java Script from inside a java code.

Other Parts of this articles are:

Why Nashorn Java Scripting in Java8, Is it Poisonous for Java? (part-1)

Server Side Java Script Nashorn, WildFly10, Undertow with MySQL (part-3)

Setting up MySQL Database

Start the MySQL database and then do the following steps which will basically do the following things:
A. Creating a simple Database with name “TestJavaScriptDB”
B. Creating a table with name “CUSTOMER”.
C. Insert some dummy records inside the “CUSTOMER” table.

mysql -u root -p 
password:


mysql> create database TestJavaScriptDB;
Query OK, 1 row affected (0.00 sec)


mysql> use TestJavaScriptDB;
Database changed


mysql> CREATE TABLE CUSTOMER (custId INT(10) NOT NULL, custName CHAR(20) NOT NULL);
Query OK, 0 rows affected (0.02 sec)

mysql> INSERT INTO CUSTOMER VALUES (1000, "MiddlewareMagic");
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO CUSTOMER VALUES (2000, "Customer-2");
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO CUSTOMER VALUES (3000, "Customer-3");
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM CUSTOMER;
+--------+-----------------+
| custId | custName        |
+--------+-----------------+
|   1000 | MiddlewareMagic |
|   2000 | Customer-2      |
|   3000 | Customer-3      |
+--------+-----------------+
3 rows in set (0.01 sec)

Writing Nashorn JavaScript

Now lets start writing the Java Script to interact with the Database. So lets create a file “testDB.js” somewhere in the filesystem as following:

//  ## JDBC Based JavaScript  ##

// Declaring the getConnection function
var getConnection = function() {
    var Properties = Java.type("java.util.Properties");
    var Driver = Java.type("com.mysql.jdbc.Driver");
    var driver = new Driver();
    var properties = new Properties();
    var conn = null;
    try {
        properties.setProperty("user", "root");
        properties.setProperty("password", "testpwd");
        conn = driver.connect("jdbc:mysql://localhost:3306/TestJavaScriptDB", properties);
        return conn;
    } finally {
    
    }
}

print("****** conn : " + getConnection());

// Declaring the runQuery function
function runQuery(conA, query) {
   try {
       var stmt = conA.prepareStatement(query);
       var resultSet = stmt.executeQuery();
       print("      --------------------------- ");
       while (resultSet.next()) {
          print("\t" + resultSet.getString("custId") + " - "+ resultSet.getString("custName"))
       }
       print("      --------------------------- ");
       
    } finally {
      if (resultSet)
         try {
            resultSet.close();
            print("\nResultSet Closed.");
         }
         catch(e) {}
      if (stmt)
         try {
            stmt.close();
            print("Statement Closed.");            
         } catch (e) { print( e );  }
      if (conA)        
         try { 
            conA.close();
            print( "Connection Closed." );
         } catch (e) { print( e );  }          
      }  
 } 


// Invoking the getConnection and runQuery() functions.
var con1 = getConnection();
runQuery(con1, "select * from CUSTOMER");

Running testDB.js script using jjs

As we know that JDK8 provides the “jjs” utility as part of “$JAVA_HOME/bin” directory which is a command line utility to execute the Nashorn Java Script. Here we will be using that utility to run the testDB.js script. Open a terminal and then run the following commands in order to set the JDK8 in the path.

Unix Based OS

export JAVA_HOME=/PATH/TO/jdk1.8.0_60
export PATH=$JAVA_HOME/bin/jjs:$PATH

Windows Based OS

set JAVA_HOME=C:\jdk1.8.0_60
set PATH=%JAVA_HOME%\bin;%PATH%

After setting the path lets run the Java Script.

$ jjs -cp /PATH/TO/mysql-connector-java-5.1.37-bin.jar:.: testDB.js 

****** conn : com.mysql.jdbc.JDBC4Connection@384ad17b
      --------------------------- 
	1000 - MiddlewareMagic
	2000 - Customer-2
	3000 - Customer-3
      --------------------------- 

ResultSet Closed.
Statement Closed.
Connection Closed.

NOTICE: while running the “testDB.js” script make sure to set the Classpath using the “-cp” option provided by “jjs” utility.
Windows users need to use “;” semi colon rather than using the “:” Colon while defining the classpath. as following:
-cp C:\PATH\TO\mysql-connector-java-5.1.37-bin.jar;.;

If users will not set the classpath properly then it will throw the following kind of error because it won’t be able to find the MySQL JDBC Driver.

$ jjs testDB.js 

Exception in thread "main" java.lang.RuntimeException: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:397)
	at jdk.nashorn.tools.Shell.apply(Shell.java:397)
	at jdk.nashorn.tools.Shell.runScripts(Shell.java:326)
	at jdk.nashorn.tools.Shell.run(Shell.java:172)
	at jdk.nashorn.tools.Shell.main(Shell.java:136)
	at jdk.nashorn.tools.Shell.main(Shell.java:112)
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at jdk.nashorn.internal.runtime.Context.findClass(Context.java:1051)
	at jdk.nashorn.internal.objects.NativeJava.simpleType(NativeJava.java:493)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:322)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:314)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:310)
	at jdk.nashorn.internal.scripts.Script$Recompilation$1$65$testDB.getConnection(testDB.js:5)
	at jdk.nashorn.internal.scripts.Script$testDB.:program(testDB.js:19)
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:640)
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:228)
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
	... 5 more

Invoking testDB.js script from Java code

Just now we have seen that how we can use the “$JAVA_HOME/bin/jjs” command line utility in order to execute the Nashorn JavaScript. Now we will write a simple java code using the “javax.script.ScriptEngineManager” and “javax.script.ScriptEngine” APIs.
Hence lets write a java program “ExampleNashornJdbc.java” somewhere in the filesystem as following:

import javax.script.*;
import java.io.*;

public class ExampleNashornJdbc {
	public static void main(String ar[]) throws Exception {
		ScriptEngineManager enginManager = new ScriptEngineManager();
		ScriptEngine engine = enginManager.getEngineByName("Nashorn");
		try {
			// Executing a simple java script file
			FileReader javaScriptFileReader = new FileReader(new File("testDB.js"));
            engine.eval(javaScriptFileReader);
            
		 } catch(final ScriptException se) {
			se.printStackTrace();
		 }
	}
}

Running Java ScriptEngine to execute testDB.js

Lets run the above code which will internally evaluate the “testDB.js” script.

$ java -cp /PATH/TO/mysql-connector-java-5.1.37-bin.jar:.: ExampleNashornJdbc
****** conn : com.mysql.jdbc.JDBC4Connection@7c729a55
      --------------------------- 
	1000 - MiddlewareMagic
	2000 - Customer-2
	3000 - Customer-3
      --------------------------- 

ResultSet Closed.
Statement Closed.
Connection Closed.

Do not forget to append the “.” in the classpath “-cp” else java virtual machine will search for the ExampleNashornJdbc class also inside the same “mysql-connector-java-5.1.37-bin.jar” and it wont find that class there ;).

If the Classpath is not set properly with the JDBC driver jar included in it then you may see the following kind of exception:

$ java ExampleNashornJdbc


Exception in thread "main" java.lang.RuntimeException: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:397)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:446)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:403)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:399)
	at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:150)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:249)
	at ExampleNashornJdbc.main(ExampleNashornJdbc.java:11)
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at jdk.nashorn.internal.runtime.Context.findClass(Context.java:1051)
	at jdk.nashorn.internal.objects.NativeJava.simpleType(NativeJava.java:493)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:322)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:314)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:310)
	at jdk.nashorn.internal.scripts.Script$Recompilation$1$65$\^eval\_.getConnection(<eval>:5)
	at jdk.nashorn.internal.scripts.Script$\^eval\_.:program(<eval>:19)
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:640)
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:228)
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
	... 6 more

Source code for this demo is present in :
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/WildFly/Java_8/ServerSideJavaScript/Part-2-Jdbc

.
.
Regards
Jay SenSharma


Why Nashorn Java Scripting in Java8, Is it Poisonous for Java? (part-1)

Hi,

Until Java SE 7, JDKs shipped with a JavaScript scripting engine based on Mozilla Rhino. Java SE 8 instead ship with a new engine called Oracle Nashorn, which is based on JSR 292 and invoke dynamic.

JDK 1.8 provides us the “$JAVA_HOME/bin/jjs” command-line tool as well as using Oracle Nashorn as an embedded scripting engine inside Java applications.

Many people do not like why JDK 8 is focusing more on the Java Scripting and why so much effort is being put on the JavaScript engine like Nashorn. Will it kill java? Introducing such features will harm java? Is it poisonous for java?

Other parts of this article an be found at:

JDK8 Based Nashorn JavaScript & Java to interact with MySQL Database. (part-2)

Server Side Java Script Nashorn, WildFly10, Undertow with MySQL (part-3)

Different people may have different opinion about it however here we will talk about how to use it and how to take benefit from it.

Why Nashorn? Any benefits/advantages?

Many people have a question in mind that why Nashorn has been introduced and What is important in it? What are the advantages of using it ?

1. Nashorn fully supports ECMAScript 5.1 specification along with some extensions, to 100% pure Java implementation and 100% complied to bytecode and not the interpreted mode as with Rhino. Simply Nashorn scripts do not need to be compiled.

2. Nashorn provides much better performance than Rhino engine.

2. Nashorn will support the javax.script (JSR 223) API. The javax.script (JSR 223) API is for calling back into JavaScript from Java.

2. It directly compiles the JavaScript code in-memory and passes the Java bytecode to the JVM, and uses invokedynamic which provides backward compatibility to JDK7 – See more at: http://www.nagarro.com/de/de/blog/post/33/Java-8-Nashorn-Engine-for-JavaScript-Interoperability-and-Performance

3. Nashorn provides a flexibility to the users that they can either programmatically use it from Java programs or they can utilize it from the command line tool “jjs” which is located in “$JAVA_HOME/bin” directory.

4. Unlike Rhino, which has its own JavaScript debugger, The Nashorn does not provide it’s own JavaScript debugger but it provides an ability to remotely debug applications using an IDE like IntelliJ IDEA 13.

5. It provides much faster execution and multi-threading of JavaScript while running in Java’s JRE.

6. Nashorn can be very easily integrated and used with JavaFX. Users can very easily interpret a JavaFX script application with Nashorn using the jjs command with the -fx option. See: http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html

7. Nashron can help in executing the OS level commands very easily like following:

    var lines = `ls -ls`.split("\n");
    for each (var line in lines) {
       print(line);
    } 

8. With Nashorn it will support in invoking Java code from JavaScript and for Java to invoke JavaScript code.

9. So far no security risk or exposure has been identified with Nashorm.

Some simple startup demos

Lets start writing very simple javascipts statements and then execute these statements using the Nashorn and the “jjs” jjs command-line tool.
As JDK8 is needed to be present in the PATH so lets setup the environment first. Following are the steps for setting the JDK8 installation in the PATH in order to use the “jjs” utility.

Unix Based OS

export JAVA_HOME=/PATH/TO/jdk1.8.0_60
export PATH=$JAVA_HOME/bin/jjs:$PATH

Windows Based OS

set JAVA_HOME=C:\jdk1.8.0_60
set PATH=%JAVA_HOME%\bin;%PATH%

Printing messages …

Once the environment is setup we can simply use the “print” function to display some messages on the jjs tool. Just type “jjs” in the command prompt to start this utility.

$ jjs
jjs> 
jjs> print ("What's New in MiddlewareMagic ? ");
What's New in MiddlewareMagic ? 
jjs> 

print(java.lang.System.currentTimeMillis());

Running jjs in “scripting” mode

“jjs” tool provides us an option “-scripting” using this we can run the OS specific commands as well as part of our scripts. For example listing the files or copy/moving a file or directory…etc.

$ jjs
jjs> var listing = `ls -l`
ECMAScript Exception: SyntaxError: <shell>:1:14 Expected an operand but found error
var listing = `ls -l`
              ^
jjs> 

As we did not start the jjs utility with the “-scripting” option hence it is not able to recognize those OS commands and failing as mentioned above. So not we will start it with this option.

$ jjs -scripting

jjs> 
jjs> var listing = `ls -l`
jjs> print(listing);
total 64

drwx------+ 27 jsensharma  XXXX\Domain Users   918 Nov 24 15:19 Desktop
drwx------+ 41 jsensharma  XXXX\Domain Users  1394 Nov 19 16:24 Documents
drwx------+ 31 jsensharma  XXXX\Domain Users  1054 Nov 26 17:01 Downloads
drwx------@ 57 jsensharma  XXXX\Domain Users  1938 Nov 26 16:36 Library
drwxr-xr-x   7 jsensharma  XXXX\Domain Users   238 Nov  3 18:38 MiddlewareMagicDemos

jjs>
jjs>
jjs> print(`date`);
Fri Nov 27 11:11:23 IST 2015
jjs>

Running a Nashorn script

It is also possible that we can combine the different functions as part of a java script file and then execute it by passing the file to the “jjs” command line tool as following:
Suppose we created a file with name “test.js” in the current directory as following:

//###### Simple JavaScript with some functions. ##
// Declaring a simple function.
function sayHello(a) { 
		return "Hello, "  + a; 
	}

//###### Invoking the function sayHelo()   ##
var result = sayHello('MiddlewareMagic');
print("\n\t\t sayHello returned: " + result + "\n"); 

Once the above file is saved then we can execute it simply by passing the file to the “jjs” utility as an argument:

$ jjs /PATH/TO/test.js 

		 sayHello returned: Hello, MiddlewareMagic

Using Java API inside the JavaScript

Now lets read a file using the script and display it’s content in the jjs terminal. Suppose we want to read a file “/PATH/TO/module.xml” and then we also want to print its content in the jjs terminal.

$ jjs

jjs> var moduleFile = "/PATH/TO/module.xml";

jjs> var fileData = new java.lang.String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(moduleFile)));

jjs> print(fileData)

Similarly we can also use some other Java APIs while using the above script like if we want to display the current date/time using the “java.util.Calendar” API then we can do the same as following:

jjs> print(java.util.Calendar.getInstance().getTime());

Fri Nov 27 11:08:32 IST 2015

Using JavaScript inside the Java code

In the above sample we have seen how to use the Java APIs inside the javascript , Now we will see how we can invoke a Java Script snippet or the java script functions inside a java code. The Java8 introduced us few new APIs which we need to use in order to achieve the same.
We will be using the “javax.script.ScriptEngineManager” and “javax.script.ScriptEngine” APIs here to invoke/execute javascript functions in java.

Lets create a simple Java Code “ExampleNashorn.java” in some directory as following:

import javax.script.*;
import java.io.*;

public class ExampleNashorn {
	public static void main(String ar[]) throws Exception {
		ScriptEngineManager enginManager = new ScriptEngineManager();
        // This method takes one String argument with the name of the script engine. 
        // To get an instance of the Nashorn engine, pass in "nashorn". 
        // Alternatively, you can use any of the following: 
        // "Nashorn", "javascript", "JavaScript", "js", "JS", "ecmascript", "ECMAScript".
        
        // Creating a Java Script Engine
		ScriptEngine engine = enginManager.getEngineByName("Nashorn");
		
		try {
            //// Directly executing JavaScript snippet: ////
		    final String rawJavaScript =  "print(java.lang.System.getProperty(\"java.home\"));" +
                                          "var Date = Java.type(\"java.util.Date\");" +
                                          "var dt = new Date(); " +
                                          "print('dt = ' + dt);";
			engine.eval(rawJavaScript);

		
		    //// Mixing Java and JavaScript  ////
			engine.put("a", new Integer(ar[0]));
			engine.put("b", new Integer(ar[1]));
			engine.eval("var c = (a+b);");
			System.out.println("Sum : " + ((Number)engine.get("c")).intValue());


			//// Executing a simple java script file ////
			FileReader javaScriptFileReader = new FileReader(new File("test.js"));
            engine.eval(javaScriptFileReader);

		} catch(final ScriptException se) {
			se.printStackTrace();
		}
	}
}

In the above sample java code we have seen the following things:
1. Directly executing JavaScript snippet form Java code.
2. Mixing Java and JavaScript
3. Executing a simple java script file using java “engine.eval” API.

Now lets run the above code simply by passing the two arguments so that it can add those numbers.

$ javac ExampleNashorn.java 

$ java ExampleNashorn 100 200

/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre

dt = Fri Nov 27 11:26:32 IST 2015

Sum : 300

		 sayHello returned: Hello, MiddlewareMagic

The Source code of this demo can be found in the following repository.
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/WildFly/Java_8/ServerSideJavaScript/Part-1
.
.
Enjoy MiddlewareMagic
Jay SenSharma


Copyright © 2010-2012 Middleware Magic. All rights reserved. |