Applet Deployment Using PyJ2D

The PyJ2D module permits scripts coded in Python programming language and the Pygame module to run in the Java virtual machine (JVM) using the Jython interpreter. PyJ2D wraps several Java libraries including the Java 2D graphics library to emulate Pygame functionality. Information about PyJ2D can be obtained on the PyJ2D project page, the PyJ2D documentation, and the PyJ2D: Python-Java2D Applet post. I have used PyJ2D to create some applets of my projects, and will describe the method used to create them.

The following applet was deployed with this method:

PyJ2D Applet

Note: browser requires Java plug-in to execute

and JavaScript enabled to launch. As this is an unsigned applet, the security setting of the latest release of JVM will block your access.

My current development environment is Linux with Java Development Kit (JDK) 6 installed that includes Java Runtime and development tools such as the Java compiler, appletviewer and jar utility. Jython 2.2.1 is installed from the Linux package manager. Jython installers can be downloaded, I downloaded Jython 2.2.1 and 2.5.2 and created standalone jython.jar of these as described in the installation instructions.

The Python script can be run using the Jython installation from the command line with the command:


jython script.py

To run using a standalone jython.jar, use the command with jython.jar path if applicable:


java -jar jython.jar script.py

Alternatively, Java can run the script directly by adding jython.jar to the Java classpath with the command:


java -cp jython.jar:$CLASSPATH org.python.util.jython script.py

The Python script requires some editing to work with PyJ2D. Check out the PyJ2D documentation to see the functionality of the module. Script modifications include any Pygame statements not implemented in the PyJ2D module, and Python statement or library not supported by the Jython version used. For an example, you can download the Python code that was used to generate the applet on this page. To use the PyJ2D module, place the pyj2d folder in the script folder or on the module path, and import pyj2d. To maintain the Pygame commands, either import submodules from pyj2d or use the statement 'import pyj2d as pygame'. Run the script in the JVM, and observe the runtime errors that will assist in discovering the changes required. Once a script can run in the JVM, it can then be used to create an applet.

To create an applet, copy Applet.py from the pyj2d folder to the script folder. Applet.py contains the Applet class that subclasses japplet. Edit Applet.py to import your script, set applet size, and add code to link the applet thread to the script application, including an optional script setup along with script execution statements that will update during the applet thread loop. Alternatively, use Applet.py as a guide and edit your script accordingly, but note that Java applets do not start from main() rather launch from a japplet subclass with the same name as the script. To test, the edited Applet.py script can be run directly on the desktop JVM as described for regular scripts, for instance:


jython Applet.py

This executes the applet code using the pawt module in these statements in Applet.py:


if __name__ == '__main__':
import pawt
pawt.test(Applet(), size=_app_size)

To create an applet packaged in a JAR file that can be deployed online, the Python code needs to be compiled to Java bytecode using jythonc that calls the Java compiler to transform the code to .class files, which is currently only possible with Jython 2.2.1. The following command compiles and creates a JAR of the script, which requires a separate standalone jython.jar:


jythonc --jar Pyj2d_Applet.jar Applet.py

To compile a single JAR that includes Jython dependencies, use the command:


jythonc --core --deep --jar Pyj2d_Applet.jar Applet.py

This command packages only the necessary dependencies of Jython, that results in a reduced applet size. For my applets I used this method, but to share common components among several applets I extracted the PyJ2D and Jython components and repackaged. Commands that follow use the jar utility included with JDK, but can be done with any Zip archiver program, such as Linux File-Roller, since a JAR file is essentially a Zip file with a jar extension. From the Pyj2d_Applet.jar, extract the pyj2d and org (contains Jython dependencies) folders, then delete these from the archive. Note that since org folder contains the necessary Jython dependencies for a particular applet, if it is shared among applets, ensure to chose a Jython org folder that has a dependency set sufficient for all the shared applets. I used Linux 'diff -r' command to compare Jython org folders.

Then create JAR files of the extracted folders that contains .class files. I packaged the pyj2d folder as PyJ2D.jar and the org folder containing Jython dependencies as Jython.jar, which in this case was 0.8M vs 1.9M for the standalone jython.jar, using the following commands:


jar cvf PyJ2D.jar pyj2d
jar cvf Jython.jar org

If the applet has image files, the applet JAR can be updated with the image folder with the command:


jar uvf Pyj2d_Applet.jar image

To run the applet before deployment online, use appletviewer included with the JDK package. To use appletviewer, place an edited Applet.html, included with pyj2d module, together with the applet JAR(s) and use the command:


appletviewer Applet.html

This will test the execution and whether the applet conforms to the JVM security profile. Using this procedure, unsigned applets were created successfully, but if code is required that violates applet's security such as disk access, the applet needs to be signed for permission as done with regular Java applets.

To deploy online, place applet JAR(s) on your server, and use HTML code that launch regular Java applets. To create a launchable applet as seen on this post, you can use the following code that calls a JavaScript function that launches the applet. Within the Web page, place the following HTML code, optional putting style attributes in a css file:


<div id="Pyj2d_Applet" title="Applet: Pyj2d_Applet"
style="width:400px; height:300px; border:1px solid #333;
background-color:#000; position:relative; left:100px;">
<input type='button' value='Launch Applet'
onClick='appletLauncher("Pyj2d_Applet")'/>
<div style="position:absolute; top:138px; width:400px;
font-size:24px; color:#646464; text-align:center;"> PyJ2D
Applet </div>
</div>

Replace 'Pyj2d_Applet' of the id and the appletLauncher parameter, which should be the same and derived from the applet JAR name, in this case Pyj2d_Applet.jar. The HTML code creates a block on the Web page with a button to call the JavaScript function appletLauncher, which should be placed at the top of the Web page or included with other JavaScript used. The code for appletLauncher is presented below:


<script type="text/javascript">
function appletLauncher
(appletArchive,appletCode,appletWidth,appletHeight)
{
var appletID = appletArchive;
var appletArchive = appletArchive +
".jar,Jython.jar,PyJ2D.jar";
var appletCodebase = "http://website.com/apps/";
var appletCode = appletCode || "Applet.class";
var appletWidth = appletWidth || "400";
var appletHeight = appletHeight || "300";
document.getElementById(appletID).innerHTML =
'<applet width=' + appletWidth +
' height=' + appletHeight +
' codebase=' + appletCodebase +
' code=' + appletCode +
' archive=' + appletArchive +
' alt="Applet requires JVM to run">';
}
</script>

Essentially, appletLauncher is called with the appletArchive parameter, in this case PyJ2D_Applet that relates to PyJ2D_Applet.jar. Optional arguments include appletCode (the main java class) that defaults to Applet.class coded in Applet.py, and appletWidth/appletHeight that defaults to 400/300. The appletCodebase should be the Web address to the server folder containing the JAR files, in this case using separate JARs, PyJ2D_Applet.jar, PyJ2D.jar, and Jython.jar. When called, the JavaScript function appletLauncher will replace the HTML code that has an id set to appletID with the code that launches the applet.

Submitted by Jim on February 8, 2012 at 5:00 pm

This entry was posted in Programming and tagged , , , , . Bookmark the permalink. Both comments and trackbacks are currently closed.