Recipe 26.3 Mixing Java and Scripts with BSF


Problem

You want to interface Java components to an existing scripting language.

Solution

Use the Bean Scripting Framework (BSF).

Discussion

Many scripting languages are used in the computing field today: VB, Perl, Python, JavaScript, Tcl/TK, REXX, and others. A project that originated at IBM but has now been taken over by the Apache Foundation, the Bean Scripting Framework (BSF), aims to provide a way to allow a number of scripting languages to interoperate with Java.

The BSF consists of a management API, an engine API for driving different scripting languages, and a series of plug-ins for different scripting languages. The management API lets you either evaluate an expression in the given scripting language, such as "2+2" (which is so simple as to be valid in most supported languages), or run a script stored in a script file. In this example, I'll use Jython, a pure-Java (certified) implementation of the scripting language Python (see http://www.python.org and http://www.jython.org or the O'Reilly book Learning Python).

While it is convenient (and efficient) to run Jython in the same JVM as the calling program, this is not by any means a requirement; for example, it is possible to use BSF with scripting languages written in some native language. BSF and the scripting plug-in are responsible for dealing with whatever "plumbing" external connections or processes this requires. Among others, BSF currently supports the languages listed in Table 26-1.

Table 26-1. Some languages supported by BSF

Language

Description

Jython

Java implementation of Python

Jacl

Java implementation/interface for Tcl

Xalan (LotusXSL)

XML stylesheets (see Recipe 21.2)

NetRexx

REXX variant

Mozilla

JavaScript implementation

Pnuts

Scripting language for accessing Java APIs

JScript, VBScript, PerlScript

Windows scripting languages


BSF could also support Mac OS Apple Scripting or almost any other language, although I don't know of an implementation at present.

Example 26-5 uses Jython to evaluate and print the value of 22/7, a crude but time-honored approximation of Math.PI, using the management API's eval( ) function. The imports assume you are using BSF 2.3; prior to this, the namespace of com.ibm was used instead of org.apache.

Example 26-5. BSFSample.java
import org.apache.bsf.util.*; import org.apache.bsf.*; import java.io.*; /** Sample of using Bean Scripting Framework with Jython */ public class BSFSample {     public static void main(String[] args) {         BSFManager manager = new BSFManager( );         // register scripting language         String[] fntypes = { ".py" };         manager.registerScriptingEngine("jython",             "com.ibm.bsf.engines.jython.JythonEngine", fntypes);         try {             // try an expression              Object r = manager.eval("jython", "testString", 0, 0, "22.0/7");             System.out.println("Result type is " + r.getClass( ).getName( ));             System.out.println("Result value is " + r);         } catch (Exception ex) {             System.err.println(ex.toString( ));         }         System.out.println("Scripting demo done.");         return;     } }

This program prints the following output:

$ java BSFSample 'import exceptions' failed; using string-based exceptions Result type is org.python.core.PyFloat Result value is 3.142857142857143 Scripting demo done. $

The exceptions failure is probably due to my having installed Jython in a nonstandard location and not setting the environment variable(s) needed to find it. Further, the first time you run it, Jython spits out a bunch of nattering about your CLASSPATH, one line for each JAR file that it finds. These can be a bit surprising when they pop up from a script, but Jython doesn't seem to know or care whether it's being run interactively or dynamically:

packageManager: processing new jar, "/usr/local/java/swingall.jar"

The following longer example uses the LabelText bean from Recipe Recipe 23.8 and a push button to run a Python script that collects the text from the LabelText instance and displays it on the standard output. Here is the little script, buttonhandler.py:

print "Hello"; print bean.getText( );

When I ran this, I typed the famous words that Alexander Graham Bell apparently sent to his assistant Watson and had the Java program send them to the Python script.

Sure enough, when I clicked on the button, I got this on the standard output (as shown in Figure 26-2):

Script output: --> Hello Mr. Watson, come here <-- End of Script output.

Figure 26-2. BSFSample in action
figs/jcb2_2602.gif


Nothing you couldn't do in Java, of course, but in this example, the LabelText bean is registered with the BSF as a bean, and the JButton 's action handler runs a script that gets that text and displays it. Example 26-6 shows the source code for the script-using program.

Example 26-6. BSFAction.java
import org.apache.bsf.util.*; import org.apache.bsf.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; /** Longer sample of using Bean Scripting Framework with Jython */ public class BSFAction {     protected String FILENAME = "buttonhandler.py";     protected BSFManager manager;     protected BSFEngine jythonengine;     protected String language;     protected String script;     public static void main(String[] args) {         new BSFAction( );     }     BSFAction( ) {         // Construct the Bean instance         LabelText bean = new LabelText("Message to Python script");         try {             manager = new BSFManager( );             // register scripting language             String[] fntypes = { ".py" };             manager.registerScriptingEngine("jython",               "com.ibm.bsf.engines.jython.JythonEngine", fntypes);             jythonengine = manager.loadScriptingEngine("jython");             // Tell BSF about the bean.             manager.declareBean("bean", bean, LabelText.class);             // Read the script file into BSF             language = manager.getLangFromFilename(FILENAME);             script = IOUtils.getStringFromReader(                 new FileReader(FILENAME));         } catch (Exception ex) {             System.err.println(ex.toString( ));             System.exit(0);         }         System.out.println("Scripting setup done, building GUI.");         final JFrame jf = new JFrame(getClass( ).getName( ));         Container cp = jf.getContentPane( );         cp.setLayout(new FlowLayout( ));         cp.add(bean);            // add the LabelText         JButton b = new JButton("Click me!");         cp.add(b);                // and the button under it.         b.addActionListener(new ActionListener( ) {             public void actionPerformed(ActionEvent evt) {                 try {                     // When the button is pressed, run the script.                     System.out.println("Script output: -->");                     manager.exec(language, FILENAME, 0, 0, script);                     System.out.println("<-- End of Script output.");                 } catch (BSFException bse) {                     JOptionPane.showMessageDialog(jf,                         "ERROR: " + bse, "Script Error",                         JOptionPane.ERROR_MESSAGE);                 }             }         });         // A Quit button at the bottom         JButton qb = new JButton("Quit");         cp.add(qb);         qb.addActionListener(new ActionListener( ) {             public void actionPerformed(ActionEvent evt) {                 System.exit(0);             }         });         // Routine JFrame setup         jf.pack( );         jf.setVisible(true);     } }

See Also

Information on the Bean Scripting Framework is located at the Jakarta Project's web site at http://jakarta.apache.org/bsf/.

Many other projects aim to blend Java with other languages. As a single example, check out the Omega Project's interface at http://www.omegahat.org/RSJava/. R, itself a clone of S, is the statistical package used to produce the charts back in Figure 5-1. This interface lets you use Java inside R or S and to call R or S from Java code.



Java Cookbook
Java Cookbook, Second Edition
ISBN: 0596007019
EAN: 2147483647
Year: 2003
Pages: 409
Authors: Ian F Darwin

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net