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, the Bean Scripting Framework (BSF) aims to provide a way to allow all of them 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 JPython, a pure-Java (certified) implementation of the scripting language Python (see http://www.python.org or the O’Reilly book Learning Python).

While it is convenient (and efficient) to run JPython 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. In fact, BSF currently supports the languages listed in Table 26-1.

Table 26-1. Languages supported by BSF

Language

Description

JPython

Java implementation of Python

Jacl

Java implementation/interface for Tcl

Bean Markup Language (BML)

Related language, from IBM

LotusXSL

XML stylesheets (see Section 21.2)

NetRexx

REXX variant

Netscape Rhino

JavaScript implementation

Pnuts

Scripting language for accessing Java APIs

Microsoft Active Scripting Format (MASF)

Microsoft analog of BSF

BSF could also support MacOS Apple Scripting or almost any other language, though I don’t know of an implementation at present.

Example 26-5 uses JPython to evaluate and print the value of 22/7, a crude approximation of Math.PI, using the management API’s eval( ) function.

Example 26-5. BSFSample.java

import com.ibm.cs.util.*;
import com.ibm.bsf.*;
import java.io.*;

/** Sample of using Bean Scripting Framework with JPython */
public class BSFSample {
    public static void main(String[] args) {
        BSFManager manager = new BSFManager(  );

        // register scripting language
        String[] fntypes = { ".py" };
        manager.registerScriptingEngine("jpython",
            "com.ibm.bsf.engines.jpython.JPythonEngine", fntypes);

        try {
            BSFEngine jpythonengine = manager.loadScriptingEngine("jpython");

            // try an expression 
            Object r = manager.eval("jpython", "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 JPython in a non-standard location and not setting the environment variable(s) needed to find it. Further, the first time you run it, JPython 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 JPython 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 Section 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.
BSFSample in action

Figure 26-2. BSFSample in action

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 com.ibm.cs.util.*;
import com.ibm.bsf.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;

/** Longer sample of using Bean Scripting Framework with JPython */
public class BSFAction {
    protected String FILENAME = "buttonhandler.py";
    protected BSFManager manager;
    protected BSFEngine jpythonengine;
    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("jpython",
              "com.ibm.bsf.engines.jpython.JPythonEngine", fntypes);
            jpythonengine = manager.loadScriptingEngine("jpython");

            // 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 currently located on IBM’s alphaWorks web site, under http://oss.software.ibm.com/developerworks/projects/bsf/.

JPython has been taken under a new umbrella and renamed Jython; see http://www.jython.org.

There are many other projects that aim to blend Java with other languages. As a single example, check out the OmegaHat project’s interface at http://www.omegahat.org/RSJava/. R, itself a clone of S (http://cm.bell-labs.com/cm/ms/departments/sia/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 also to call R or S from Java code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.15.43