Bean Scripting Framework

Bean Scripting Framework (BSF) is a set of Java classes which provides scripting language support within Java applications, and access to Java objects and methods from scripting languages.

BSF Architectural Overview

The two primary components of BSF are the BSFManager and the BSFEngine.

The BSFManager handles all scripting execution engines running under its control, and maintains the object registry that permits scripts access to Java objects. By creating an instance of the BSFManager class, a Java application can gain access to scripting services.

The BSFEngine provides an interface that must be implemented for a language to be used by BSF. This interface provides an abstraction of the scripting language's capabilities that permits generic handling of script execution and object registration within the execution context of the scripting language engine.

An application can instantiate a single BSFManager, and execute several different scripting languages identically via the BSFEngine interface. Furthermore, all of the scripting languages handled by the BSFManager are aware of the objects registered with that BSFManager, and the execution state of those scripting languages is maintained for the lifetime of the BSFManager.

Installation

BSF can be used standalone, as a class library, or as part of an application server. In order to be used as a class library or as a standalone system, you simply download a copy of the bsf.jar file from the BSF web site and include it in your classpath, along with any required classes or jar files for desired languages.

In order to use BSF as part of the Tomcat servlet engine, you must currently download patches from the BSF web site that permit Jasper to call BSF. Instructions for this will be posted on the website, and will soon be accompanied by prebuilt binaries. We hope that these changes will be merged into Tomcat in the near future.

Using BSF

BSF and JSPs

After you set up an application server that is BSF enabled, you can write JSPs using any of the supported scripting languages. JSPs using scripting languages differ only slightly from those using Java.

First, you must set the language attribute of the page directive in the JSP to the desired language. For example,

<%@ page language="javascript" %>

sets the language used for the JSP to Javascript; any scriptlets or expressions within the JSP will be handed off to BSF, which will in turn hand the code over to Rhino for execution.

The standard set of JSP implicit objects is available within BSF. These implicit objects must be used for input and output with respect to the generated page, since the scripting languages do not have any awareness of having been called within a JSP. For example, in order to print a line of text into the page generated by the JSP, one must use the println() method of the out implicit object.

Multiple languages can be supported within a given JSP; this is accomplished by using the BSF taglibs, which are available from the Jakarta Taglibs project. BSF taglib provides two tags: scriptlet and expression. Both of these have a required language attribute, which is used to specify the language used on a per scriptlet or expression basis.

Servlets and Other Applications

Using BSF in servlets or applications is also quite simple. In order to provide an application with scripting support, you need to import the BSF class hierarchy and instantiate a BSFManager object. After instantiating the BSFManager, you register or declare any Java objects to be made available within the scripting engine. Then call either one of the eval() or exec() BSFManager methods (depending on whether you want to evaluate a script and have the value of the evaluation returned, or execute a script). Alternatively, you can call the loadScriptingEngine() method in order to get an object implementing the BSFEngine interface for the desired scripting language. You can then call the exec() or eval() methods of BSFEngine to run the script.

Additionally, BSF declares an object named bsf within a scripting engine's execution context, which represents the BSFManager that is associated with the scripting engine. This object provides all of the methods and properties associated with the BSFManager to the script. However, the most used method within scripts is usually lookupBean(), which is used to access objects in BSF's object registry.

The most important methods within the BSFManager are:

  • BSFManager() - the BSFManager constructor
  • eval() - used to evaluate a script and return its value
  • exec() - used to execute a script
  • loadScriptingEngine() - used to return a BSFEngine for the desired scripting language
  • registerBean() - adds an object to BSF's object registry
  • lookupBean() - retrieves an object from BSF's object registry
  • declareBean() - creates an implicit object in the context of any loaded scripting language, which does not have to be accessed via lookupBean()

Other, less often used methods within the BSFManager are:

  • apply() - used to call anonymous functions
  • compileExpr() - used to compile an expression into a CodeBuffer object
  • compileScript() - similar to compile expression, used to compile scripts into CodeBuffer objects
  • compileApply() - similar to both of the above - used to compile anonymous functions into CodeBuffer objects

For the curious, the CodeBuffer is a class provided by BSF for storing generated Java code.

The BSFManager exec(), eval(), and apply() methods (as well as their compile counterparts) are wrappers over the equivalent methods presented by the BSFEngine interface. If the programmer explicitly loads a scripting engine via loadScriptingEngine(), they can use the exec() or eval() methods of the resulting BSFEngine as appropriate.

Adding BSF Support for a Scripting Language

In order to incorporate your own scripting language into BSF, you must first write a class implementing the BSFEngine interface for the language; examples are available in the BSF source distribution.

Usually, a scripting language author extends the BSFEngineImpl class, which implements BSFEngine, and only requires the scripting language author to implement the eval() method. However, the following methods specified by the BSFEngine interface are the most commonly implemented:

  • initialize() - used to set up the underlying scripting language engine
  • call() - used to call functions or methods within the scripting engine
  • eval() - used to evaluate a script
  • exec() - used to execute a script
  • declareBean() - used to create an implicit object within the scripting language
  • undeclareBean() - used to remove an implicit object from the scripting language

Once you have implemented the wrapper for your language engine, you instantiate a BSFManager in your application, and register your engine with it via the registerScriptingEngine() method. Afterward, you may use your language within the application through the usual BSF semantics.

Standalone Scripts

BSF provides a facility for running scripting languages itself. Simply running java org.apache.bsf.Main will produce a help message, with instructions on how to run these scripts.