473,408 Members | 2,839 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,408 developers and data experts.

Scripting

11,448 Expert 8TB
Greetings,

Introduction

Java is not Javascript and most of the times when questions end up in the wrong
forum, they're moved to the other forum as soon as possible. Accidentally this
article talks about Javascript a bit but it belongs in the Java section.

Since version 1.6 of Java a script engine comes packaged with the core classes.
A script engine is an abstract little framework that offers support for other
languages, scripting languages to be exact, a.k.a. interpreters.

Java version 1.6. comes bundled with one scripting language: Javascript. The
next paragraphs decribe what you can do with this little framework and how you
can do it.

ScriptEngineManager

A ScriptEngineManager manages (sic) ScriptEngines. A ScriptEngine is Java's
interface to a scripting language. The manager doesn't know how to install,
or instantiate, an engine itself: it uses so called ScriptEngineFactories for
that purpose. So if you want to obtain a ScriptEngine you ask the manager for
it; the manager checks if one of its factories can instantiate the appropriate
engine; if so, it asks the factory to do so and the manager returns the new
ScriptEngine to the caller.

Note that in this simple case we, the programmers, didn't need to deal with the
factories ourself. Here's a simple example

Expand|Select|Wrap|Line Numbers
  1. ScriptEngineManager manager= new ScriptEngineManager();
  2. ScriptEngine engine= manager.getEngineByName("JavaScript");
  3. try {
  4.     engine.eval("print('Hello, world!')");
  5. } catch (ScriptException ex) {
  6.     ex.printStackTrace();
  7. }    
  8.  
The first line instantiates the new manager. Line two indirectly instantiates
a ScriptEngine for the Javascript language. The next lines put that ScriptEngine
to work a bit; it's the obligatory "hello world!" program written in Javascript
and executed (or "interpreted") from the Java environment.

ScriptEngineFactory

The factories are implementations of this interface. Factories can produce the
ScriptEngines (see previous paragraph). Let's see what those factories can tell
us; here's an example:

Expand|Select|Wrap|Line Numbers
  1. ScriptEngineManager manager= new ScriptEngineManager();
  2. List<ScriptEngineFactory> factories= manager.getEngineFactories();
  3.  
  4. for (ScriptEngineFactory factory: factories) {
  5.  
  6.     String name = factory.getEngineName();
  7.     String version = factory.getEngineVersion();
  8.     String language = factory.getLanguageName();
  9.  
  10.     System.out.println(name+"("+version+"): "+language);
  11.  
  12.     for(String n: factory.getNames()) 
  13.               System.out.println(n);
  14. }
  15.  
This example instantiates a ScriptEngineManager again and asks it for a List
of available ScriptEngineFactories. For every factory it's information is
retrieved and printed. Note that a language doesn't just have a name, the
language is also known by zero or more aliases; the inner loop shows the alias
names too, if available.

Read the API documentation to see what more a ScriptEngineFactory can do for you.
When I run that little snippet on my laptop this is the output:

Expand|Select|Wrap|Line Numbers
  1. Mozilla Rhino(1.6 release 2): ECMAScript
  2. js
  3. rhino
  4. JavaScript
  5. javascript
  6. ECMAScript
  7. ecmascript
  8.  
There's only one factory installed for the 'ECMAScript' language; that's the
old name of Javascript; the ScriptEngine implementation is Mozilla Rhino. The
language is also available under the alias names, "js", "rhino", "Javascript",
and a few other variations.

How does the ScriptEngineManager know which ScriptEngineFactories are available?
It uses quite a new naming convention for that: the jars that contain factories
(and the engines) must be stored in a special directory and the manager checks
that directory for the jars and dynamically figures out which factories are in
those jars. A detailed discussion of this mechanism is beyond the scope of this
article. Maybe in the near future I'll build a factory and an engine for the
little expression language presented in a previous article series.

ScriptEngine

A ScriptEngine is Java's gateway to a particular script interpreter. But where
does that script come from? There are two ways to feed a script to the engine:
pass it a Reader or pass it a String. When reading from the Reader the script
is supposed to be read. The Reader can be any Reader: wrapped around a socket
InputStream, or maybe just a FileReader. The script can come from anywhere.
The alternative is just to pass the entire script text as a String.

A script maintains 'bindings'. A binding is nothing more than a Map<String, Object>,
i.e. it associated Strings with objects. The engine uses those bindings for its
scripts. Here's a small example:

Expand|Select|Wrap|Line Numbers
  1. ScriptEngineManager manager = new ScriptEngineManager();
  2. ScriptEngine engine = manager.getEngineByName("JavaScript");
  3.  
  4. try {
  5.     String expression = "a+b";
  6.     engine.put("a", 41);
  7.     engine.put("b", 1);
  8.     Object result = engine.eval(expression);
  9.     System.out.println(expression+"= "+result);
  10.     System.out.println("type: "+result.getClass().getCanonicalName());
  11. } catch(ScriptException se) {
  12.     se.printStackTrace();
  13. }
  14.  
Both 'engine.put()' method calls put a new binding in the engine's bindings:
a=41 and b=1. When I run this code snippet on my laptop I see this:

Expand|Select|Wrap|Line Numbers
  1. a+b= 42.0
  2. type: java.lang.Double
  3.  
That ScriptEngine was smart enough to convert a Javascript '42' to a Java Double
object. It was also smart enough to convert Java's ints '41' and '1' to the
correct objects for Javascript so that it can evaluate 'a+b'. That's cute.

As a matter of fact, a ScriptEngine can convert all sorts of Java objects to
the script's representation thereof and back again to Java's representation.

The Javascript engine can even directly use Java objects; I bluntly 'borrowed'
the following example from a piece of Sun's text on the same topic:

Expand|Select|Wrap|Line Numbers
  1. ScriptEngineManager manager = new ScriptEngineManager();
  2. ScriptEngine engine = manager.getEngineByName("JavaScript");
  3.  
  4. try {
  5.     engine.eval(
  6.         "importPackage(javax.swing);" +
  7.         "var pane = " +
  8.         "JOptionPane.showMessageDialog(null, 'Hello, world!');");
  9. } catch (ScriptException ex) {
  10.     ex.printStackTrace();
  11. }
  12.  
Invocable

Script engines don't just read, parse and interpret source text; they compile
the script text to their internal form. Such engines implement another interface,
the Invocable interface.

Here's an example showing how this interface can be used:

Expand|Select|Wrap|Line Numbers
  1. ScriptEngineManager manager = new ScriptEngineManager();
  2. ScriptEngine engine = manager.getEngineByName("JavaScript");
  3.  
  4. try {
  5.     String expression = "function add(x, y) { return x+y; }";
  6.     engine.eval(expression);
  7.  
  8.     engine.put("a", 41);
  9.     engine.put("b", 1);
  10.  
  11.     Invocable invocable= (Invocable)engine;
  12.  
  13.     System.out.println("add(1, 41)= "+invocable.invokeFunction("add", 1, 41));
  14.     System.out.println("add(a, b)= "+invocable.invokeFunction("add", "a", "b"));
  15.     System.out.println("add(a, b)= "+engine.eval("add(a, b)"));
  16.  
  17. } catch(ScriptException se) {
  18.     se.printStackTrace();
  19. } catch (NoSuchMethodException nsme) {
  20.     nsme.printStackTrace();
  21. }
  22.  
First the small script "function add(x, y) { return x+y; }' is compiled and two
bindings are added. Next the ScriptEngine is cast to an Invocable. If the cast
fails (it doesn't in this example), an exception is thrown indicating that the
particular script cannot compile the script and keep it for later use.

When I run this little code snippet, this is the output:

Expand|Select|Wrap|Line Numbers
  1. add(1, 41)= 42.0
  2. add(a, b)= ab
  3. add(a, b)= 42.0
  4.  
Note that the second invocation tried to add the String values "a" and "b", not
the values present in the bindings. The result is the String "ab" showing that
Javascript concatenates strings when the '+' operator is applied to them.

The third call properly uses the bound values for a and b again.

Concluding remarks

There's much more that can be done with this quite new little framework. The
framework is the result of all the work done by JSR 223 and at this very moment
they're working on implementations for the Ruby language, the BeanShell interpreter
and other languages as well. This article showed the basic usage and the structure
of the ScriptEngine framework. Have fun with it. I hope to see you all again
next week and

kind regards,

Jos
Sep 23 '07 #1
2 6477
Hi! Well this article result really useful, I'm a total beginner in Java and I'm trying to import a .js file into a java code. I was wondering if you could tell me how can I do that. I found this code but I don't know if it is correct to put that:
Expand|Select|Wrap|Line Numbers
  1. ScriptEngineManager engineMgr = new ScriptEngineManager();
  2.             ScriptEngine engine = engineMgr.getEngineByName("ECMAScript");
  3. //joscript is my .js file
  4.           InputStream is = this.getClass().getResourceAsStream("/joscript.js");
  5.                   try {
  6.                 Reader reader = new InputStreamReader(is);
  7.                 engine.eval(reader);
  8.             }
  9.                   catch (ScriptException ex) {
  10.                 ex.printStackTrace();
  11.                 }
I don't know if I need to import a class too. I put this:
Expand|Select|Wrap|Line Numbers
  1. import java.ScriptEngineManager.*;
is it correct?
Thanks and good job for the article.
Nov 29 '07 #2
hsn
237 100+
great article Jos, i had no idea about the ScripEngine stuff.
keep it up

Kind regards
hsn
Oct 21 '08 #3

Sign in to post your reply or Sign up for a free account.

Similar topics

4
by: The_Incubator | last post by:
As the subject suggests, I am interested in using Python as a scripting language for a game that is primarily implemented in C++, and I am also interested in using generators in those scripts... ...
41
by: Richard James | last post by:
Are we looking at the scripting world through Python colored glasses? Has Python development been sleeping while the world of scripting languages has passed us Pythonista's by? On Saturday...
33
by: Quest Master | last post by:
I am interested in developing an application where the user has an ample amount of power to customize the application to their needs, and I feel this would best be accomplished if a scripting...
9
by: What-a-Tool | last post by:
Dim MyMsg Set MyMsg = server.createObject("Scripting.Dictionary") MyMsg.Add "KeyVal1", "My Message1" MyMsg.Add "KeyVal2", "My Message2" MyMsg.Add "KeyVal3", "My Message3" for i = 1 To...
0
by: fiona | last post by:
Catalyst Releases Scripting Editions of SocketTools Client and server-side development for Active Server Pages and PHP. Yucca Valley, CA, May 25, 2005 - Catalyst Development Corp...
8
by: rmacias | last post by:
I am maintaining an application that was writting in VB6 and has VBA 6.2 integrated into it. The VBA SDK allows the users of the application to generate VBA projects and scripts to gain access to...
6
by: Wolfgang Keller | last post by:
Hello, I'm looking for a spreadsheet application (MacOS X prefered, but Windows, Linux ar available as well) with support for Python scripting (third-party "plug-ins" are ok) and a database...
1
by: andrewcw | last post by:
I have used System.Management in the past to extract and walk thru drives & check their type. I can also do it with COM's FileSystemObject. Here I am trying to just use the Management Object...
2
by: James | last post by:
Are there any classes in c# for this or am I left to use the com interface, which I'm not sure how. And if I have this will it work on a machine that someone has disabled scripting? Finally,...
7
ADezii
by: ADezii | last post by:
The next series of Tips will involve the Microsoft Scripting Runtime Library (Scrrun.dll). This Library is, in my humble opinion, one of the most useful and practical Libraries ever created. With the...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.