Calling Java from JavaScript
Rhino provides excellent integration with Java classes, supporting a BIRT script working seamlessly with business logic written in Java. Using a JavaScript wrapping means the developer can leverage both internal and external libraries of existing Java code. You can use static methods, non‑static methods, and static constants of a Java class.
The Packages object
The Packages object is the JavaScript gateway to the Java classes. It is a top‑level Rhino object that contains properties for every top-level Java package, such as java and com. The Packages object contains a property for every package that it finds in its classpath. Use the Packages object to access a Java class for which Packages has a property by preceding the class name with Packages, as shown in the following statement:
var nc = new Packages.javax.swing.JFrame( "MyFrame );
You can also use the Packages object to reference a Java class that is not a part of a package, as shown in the following statement:
var nc = new Packages.NumberConversion( );
For BIRT to find a custom Java class or package, the file must be in the classpath, as discussed later in this chapter.
The importPackage method
You can avoid writing a fully qualified reference to a Java class by using the top‑level Rhino method importPackage( ). The importPackage( ) method functions like a Java import statement. Use the importPackage( ) method to specify one or more Java packages that contain the Java classes that you need to access, as shown in the following statement:
importPackage( Packages.java.io, Packages.javax.swing );
You must prefix the name of each package with Packages. After the first time BIRT executes a method containing the importPackage( ) method, the specified packages are available to all succeeding scripts. For this reason, include the importPackage( ) in the ReportDesign.initialize script, which is always the first script that BIRT executes.
Java imports java.lang.* implicitly. Rhino, on the other hand, does not import java.lang.* implicitly because JavaScript has several top-level objects of the same names as some classes defined in the java.lang package. These classes include Boolean, Math, Number, Object, and String. Importing java.lang causes a name collision with the JavaScript objects of the same name. For this reason, avoid using importPackage( ) to import java.lang.
Using a Java class
To use a Java class in a BIRT script, set a JavaScript object equal to the Java object. Then, call the Java class methods on the JavaScript object. Listing 37‑28 creates a Java Swing frame and sets the JavaScript object named frame to the Java JFrame object. Then, the code calls the setBounds( ) and show( ) methods directly on the JavaScript object.
Listing 37‑28 Calling Java methods on a JavaScript object
importPackage( Packages.javax.swing );
frame = new JFrame( "My Frame" );
frame.setBounds( 300, 300, 300, 20 );
frame.show( );
The effect of this code example is to display a Java window containing the title, My Frame, on your desktop. This code example works only in BIRT Report Designer.
Placing Java classes
For BIRT Report Viewer to find Java classes, the classes must be under the following folder:
$ECLIPSE_INSTALL\plugins org.eclipse.birt.report.viewer_*\birt\WEB-INF\classes
Alternatively, package the classes as a JAR file put into:
$ECLIPSE_INSTALL\plugins org.eclipse.birt.report.viewer_*\birt\scriptlib
BIRT Report Designer also finds classes in a Java project within the same workspace as the report project. Attach additional JAR files in the resource folder to a specific report by using the resource properties tab for the report.
If you deploy the example Viewer to an application server, you must also deploy these classes or JAR files to the run-time environment, unless the JAR files already exist in the classpath of the application.
Place event handlers and Java classes in the SCRIPTLIB directory defined in the web.xml of the web viewer application. If using the SCRIPTLIB directory, the classes must be in JAR format.
If you are using the Report Engine API, the classes must be in the classpath. Alternatively, use a system variable that the report engine adds to the classpath as follows:
System.setProperty( EngineConstants.WEBAPP_CLASSPATH_KEY,
"c:/myjars/class.jar" );
If you are using the Report Engine API, you can set the parent class loader for the engine by setting the APPCONTEXT_CLASSLOADER_KEY in the application context, as shown in Listing 37‑29.
Listing 37‑29 Setting the parent class loader for the report engine
config = new EngineConfig( );
HashMap hm = config.getAppContext( );
hm.put( EngineConstants.APPCONTEXT_CLASSLOADER_KEY,
YourClass.class.getClassLoader( ) );
config.setAppContext( hm );
Setting the application context class loader supports report script accessing objects in the parent class loader.
Issues with using Java in JavaScript code
There are many nuances to writing Java code, such as how to handle overloaded methods and how to use interfaces. For more information on these topics, refer to the Rhino page on scripting Java at http://www.mozilla.org/rhino/ScriptingJava.html.