---
title: Data Processing with Nashorn
sidebar_label: Java + Nashorn
pagination_prev: demos/bigdata/index
pagination_next: solutions/input
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
[Nashorn](https://openjdk.org/projects/nashorn/) is a JS engine for Java. It
shipped with Java distributions starting with Java 8 and was eventually removed
in Java 15. The project was spun off and a compatible standalone release is
available for Java 15+.
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
The ["Complete Example"](#complete-example) section includes a complete Java
command-line tool for reading data from spreadsheets and printing CSV rows.
## Integration Details
### Initialize Nashorn
Nashorn does not provide a `global` variable. It must be created:
```java
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
/* initialize nashorn engine */
ScriptEngine engine = (new ScriptEngineManager()).getEngineByName("javascript");
/* create global */
// highlight-next-line
engine.eval("var global = (function(){ return this; }).call(null);");
```
### Load SheetJS Scripts
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
can be parsed and evaluated in a Nashorn context.
The main library can be loaded by reading the script from the file system and
evaluating in the Nashorn context:
```java
engine.eval(new Scanner(
SheetJS.class.getResourceAsStream("/xlsx.full.min.js")
).useDelimiter("\\Z").next());
```
To confirm the library is loaded, `XLSX.version` can be printed using the
Nashorn `print` built-in:
```java
engine.eval("print('SheetJS Version ' + XLSX.version);");
```
### Reading Files
Nashorn does not properly project `byte[]` into a JS array or `Int8Array`. The
recommended workaround is to copy the data in the JS context using the JS code:
```js
function b2a(b) {
var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);
/* `b` is similar to Int8Array (values in the range -128 .. 127 ) */
for(var i = 0; i < out.length; i++) out[i] = (b[i] + 256) & 0xFF;
return out;
}
```
This function should be embedded in the Java code:
```java
/* read spreadsheet bytes */
engine.put("bytes", Files.readAllBytes(Paths.get(args[0])));
/* convert signed byte array to JS Uint8Array or unsigned byte array */
engine.eval(
"function b2a(b) {" +
"var out = typeof Uint8Array == 'function' ? new Uint8Array(b.length) : new Array(b.length);" +
"for(var i = 0; i < out.length; i++) out[i] = b[i] & 0xFF;" +
"return out;" +
"}" +
"var u8a = b2a(bytes)"
);
/* parse workbook */
engine.eval("var wb = XLSX.read(u8a, {type: 'array'})");
```
## Complete Example
:::note Tested Deployments
This demo was tested in the following deployments:
| OpenJDK | Nashorn | Date |
|:--------|:----------------|:-----------|
| 22.0.1 | 15.4 standalone | 2024-06-24 |
| 21.0.3 | 15.4 standalone | 2024-06-24 |
| 20.0.2 | 15.4 standalone | 2024-06-24 |
| 19.0.2 | 15.4 standalone | 2024-06-24 |
| 18.0.2 | 15.4 standalone | 2024-06-24 |
| 17.0.11 | 15.4 standalone | 2024-06-24 |
| 16.0.1 | 15.4 standalone | 2024-06-24 |
| 15.0.10 | 15.4 standalone | 2024-06-24 |
| 14.0.2 | Built-in | 2024-06-24 |
| 13.0.14 | Built-in | 2024-06-24 |
| 12.0.2 | Built-in | 2024-06-24 |
| 11.0.23 | Built-in | 2024-06-24 |
| 10.0.2 | Built-in | 2024-06-24 |
| 9 | Built-in | 2024-06-24 |
| 1.8.0 | Built-in | 2024-06-24 |
:::
### Compilation