Author Archives: Zhou Renjian

Compressing and Deploying JavaScript

For AJAX, deploying JavaScript files may be important for you or not. If you are professional in AJAX, you must know the details of JavaScript deployment.

First, you can compress your JavaScript files before deploying them. Common compressors may cut 50% off of file size for normal JavaScript. That is to say, if your packed *.js is about 100k, the compressed *.js may be 50k. The compressed *.js may take about 100ms to decompress, but it when comparing to 50k over 1Mb/s bandwidth ( 50k * 8 / 1M = 0.4 s = 400ms). It worths such compressing. Usually bandwidth is not quite good as 1Mb/s, it will much better for compressed JavaScript.

Some well-known JavaScript compressors are Dean Edwards’ Packer and Shrink Safe by Alex at Dojo. You may find some other compressors, like Java2Script’s LZ77 JavaScript Compressor.

Second, you can send out your JavaScript files as gzip-encoded by Apache server. For most of modern browsers, gzip-encoding can be accepted. So you should configure your Apache server to do so especially when your JavaScript is over 200k. In common cases, gzip-encoding saves over 75% of JavaScript bandwidth. That is to say, 200k JavaScript only takes up 50k transmission. What a great improvement.

But please pay attention to some defects of JavaScript gzip-encoding for some browsers, like IE. Well, Internet Explorer takes up 80%+ of browser shares. You must not ignore IE’s defects on dealing JavaScript gzip-encoding. As IE6.0 SP2 and IE7+ already fixed this bug. You should support these two browsers, as it may get more and more market share.

So when configure .htaccess file for Apache httpd server, you should ignore those buggy IE browser or non-supported browsers. Here is my .htaccess file:

<IfModule mod_deflate.c>
# Netscape 4.x or IE 5.5/6.0
BrowserMatch ^Mozilla/4 no-gzip
# IE 5.5 and IE 6.0 have bugs! Ignore them until IE 7.0+
BrowserMatch \bMSIE\s7 !no-gzip
# IE 6.0 after SP2 has no gzip bugs!
BrowserMatch \bMSIE.*SV !no-gzip
# Sometimes Opera pretends to be IE with "Mozila/4.0"
BrowserMatch \bOpera !no-gzip
AddOutputFilterByType DEFLATE text/css text/javascript application/x-javascript
Header append Vary User-Agent
</IfModule>

For more information about this gzip-encoding configuration, please google “IE gzip javascript encoding” or read Joshua Eichorn’s blog article “Compressing JavaScript and CSS”.

Third, this is still about gzip-encoding. But this method tries to include JavaScript in HTML sources directly. As IE has no bugs on decoding gzip-encoded HTML files, compress JavaScript in this way will suite for most IE6 users. As far as I know, GWT uses this way to send out their JavaScript. But loading those HTML files in an embed IFRAME may make the whole architecture a little strange or hard to understand. Few people uses this method.

Maybe there are some other ways to compress and deploy JavaScript. Please let me know or discuss with me if you have a new one.

Posted in Architecture, Hacks, JavaScript | 23 Comments

Packing in Java2Script

Usually, when you develop new features, you split functions into pieces and implement them one by one. And in Java development, there will be implemented by one *.java file and another. If you want to deploy the finished feature, you need to pack them up.

In Java development, deployment means that you need to pack compiled *.class files and other related resource files into a *.jar and place it to correct location. There are lots of tools to do this job. Or if you are using IDE, such as Eclipse, the IDE will provide a whole development life management tools for you.

In JavaScript world, tools are rare. And for the loading speed and performance considerations, packing JavaScript and deploy them need your attentions.

Small *.js file should be packed into some bigger *.js file. But each *.js file should not be too big, or each time you update only one small *.js, you have to update a big *.js file. But *.js files should not be too many. Because *.js files are downloaded from servers in some specific orders, two many *.js files may be queued, which may mean a long latency. Lots of *.js compiled from *.java by Java2Script compiler is very small. In order to get a shorter loading time, most of these *.js files are packed into a big *.z.js file. Please check out the packing ant script. But packing *.js into a big *.z.js is not a simple job in Java2Script. As there is ClassLoader inside Java2Script system. The packed *.z.js file must be dealt correctly by ClassLoader. This issue is very complicate. And I would like to talk about it in another post.

Small size images can be packed into a bigger size one two. This is especially useful if there are icons for tool-bar. When a small icon needed, just display the big image with given position and size. This trick is a CSS tip. For example, create a DIV block with size 16×16, and set its style with some background image started from given position:

<div style="width:16px; height:16px; background-image:url(big.gif); background-position:16px 32px; background-repeat:no-repeat;"></div>

“background-position:16px 32px;” means the icon place at the 2nd row, the 3rd column. That is the image packing trick. Java2Script SWT implementation uses these tricks, you can check the Shell.css. In there, there are no absolute positions but relative positions, such as “center right”. This is because 9 icons are packed as 3×3 squares.

Small *.css can also be packed into a big *.css files too. But in practices of Java2Script packing, *.css files are packed into *.js files. All *.css files are only applied when necessary. For example, when a widget is loaded, the widget related *.css rules are applied to the page so that widget may be in correct style. For this trick, please check Java2Script CSS hacks.

And there are also some other packing tricks which I may introduce later. As packing is for deployment. And deployed resources are for loading. And loading will affect the whole object oriented inheritance simulator. And things are a whole integrated system.

Posted in Architecture, Hacks | 2 Comments

Asynchronous Programming

In my early Java2Script development days, I think a lot about asynchronous programming. AJAX was hot and is still hot. What is most important factor in AJAX technologies? I think it is “Asynchronous”. Without asynchronous programming, visitors still need to waste their time waiting for browser to fetch the next page. What a bad user experience.

In fact, asynchronous programming is not an easy work. Lots of callbacks, lots of threads, lots of locks or semaphores. All these stuffs may be messed up into an unmaintainable geeky thing.

Actually, if there are tools helping to design and maintain such codes, it is not a big job. If you use Java, you won’t get stuck at those threads of synchronized locks, as lots of debug tools help you figure out how those things work together at any moment you want to take a look. In fact, there are lots asynchronous programmings in Java design patterns or codes. But in Java world, asynchronous programming is not an outstanding features, and it is seldom discussed as an important issue.

But in JavaScript world, in browser world, asynchronous programming is a huge thing. In JavaScript (also known as EMCAScript)? language specification, there are no threads, no semaphores, no locks. All things are designed in synchronized mode. And before AJAX was hot, there are no robust tools for developers to write and debug JavaScript. If JavaScript sources file size exceeds 100K, it would be a hard-ass job to maintain. And if there are 3 layers of callbacks, it would drive developers crazy to develop new features. From my early experience, I designed a web form with digital signature functions, I used Java Applet in the back-end and used AJAX-style dialogs. And in oder to make a correct call from dialogs to Java Applet, its parameters may be passed through about 4-6 callback layers, because there are security issues over JavaScript calling Java Applet and Java Applet’s own sandbox mechanism. At that time, I sometimes found myself at the peak of being crazy or being collapsed.

So as I explain, asynchronous programming is not funny. And we would like to accept synchronous programming. Now let’s take a look at those Java synchronous programming which need to be JavaScript asynchronous programming:

Java snippet:

Display display = Display.getDefault();
SimpleSWTRPC shell = new SimpleSWTRPC(display, SWT.SHELL_TRIM);
shell.open();
shell.layout();
while (!shell.isDisposed()) { // waiting loop
if (!display.readAndDispatch())
display.sleep();
}
// continue other codes...

But in JavaScript, the above waiting loop will use up all CPU times and freeze browser. So such waiting loop must be avoided. And callback mechanism is used:

var display = $wt.widgets.Display.getDefault ();
var shell = new org.java2script.demo.simplerpc.SimpleSWTRPC (display, 1264);
shell.open ();
shell.layout ();
Sync2Async.block (shell, this, function () {
// continue other codes...
});

The above codes use Sync2Async technology. Such technologies have lots of defects. The biggest defect is that it can not stop browser to execute the following codes outside the method closure. For example, if the above codes are in method #openUpDialog, and in another method say #setUp call this method and then call other methods:

this.openUpDialog();
this.checkState();
this.sendOutRequest();

When the above codes are executed in Java mode, #checkState and #sendOutRequest will never be called until user closes the dialog. But in JavaScript Sync2Async mode, the callback technology can not block browser from executing #checkState and #sendOutRequest, which may result in incorrect result. This is the key defect of Sync2Async technology. Even though it has defects, such technology helps developes a lots for some simple tasks.

In order to fulfill some complicate task, designers should design the whole architecture as asynchronous programming patter from the beginning. Even in Java language, all things in asynchronous mode are still difficult.

More should be discussed for this issue.

Posted in Architecture, Hacks | 17 Comments

Tutorial of Java2Script SWT and Simple RPC Application

In this article, I will show you a simple example using Java2Script Simple RPC (For “what is Java2Script Simple RPC? “, please read this post).

Step 1. Create a Java2Script Servlet Project

Here are instructions: File -> New -> Project … -> Java2Script -> Java2Script Servlet Proejct -> Next -> Key in project name and select “Create separate folders for sources and class files” -> Next or Finish or Finish on next page

Create Java2Script Project Menu Screenshot

Create Java2Script Project Select Screenshot

Create Java2Script Project Wizard Screenshot

When finish this step, try to expand the project sources, you should get similar structures as below:

Java2Script Servlet Project Sources Structure

Later, I will explain more about every files.

Step 2. Create an SWT Application

Here are instructions: Select “src” source folder and create package named “org.java2script.demo.simplerpc”, and create a class name “SimpleSWTRPC” in that package. The class’ source is as following:

package org.java2script.demo.simplerpc;

import net.sf.j2s.ajax.SimpleRPCSWTRequest;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class SimpleSWTRPC extends Shell {

private Text responseText;
private Text requestText;
private Label statusLabel;
/**
* Launch the application
* @param args
*/

public static void main(String args[]) {
try {
Display display = Display.getDefault();
SimpleSWTRPC shell = new SimpleSWTRPC(display, SWT.SHELL_TRIM);
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* Create the shell
* @param display
* @param style
*/

public SimpleSWTRPC(Display display, int style) {
super(display, style);
createContents();
setLayout(new FillLayout());
}

/**
* Create contents of the window
*/

protected void createContents() {
setText("Hello SWT & Simple RPC");
setSize(371, 300);

final Composite composite = new Composite(this, SWT.NONE);
composite.setLayout(new GridLayout());

final Label requestLabel = new Label(composite, SWT.NONE);
final GridData gd_requestLabel = new GridData(SWT.FILL, SWT.CENTER, true, false);
requestLabel.setLayoutData(gd_requestLabel);
requestLabel.setText("Request:");

requestText = new Text(composite, SWT.MULTI | SWT.BORDER);
final GridData gd_requestText = new GridData(SWT.FILL, SWT.FILL, true, true);
gd_requestText.heightHint = 80;
gd_requestText.minimumHeight = 80;
requestText.setLayoutData(gd_requestText);

final Button sendButton = new Button(composite, SWT.NONE);
sendButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
statusLabel.setText("Sending request ...");
String text = requestText.getText();
text = "[Server echo]:" + text;
responseText.setText(text);
statusLabel.setText("Server responded.");
}
});
final GridData gd_sendButton = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
sendButton.setLayoutData(gd_sendButton);
sendButton.setText("Send Simple RPC Request");

final Label reponseLabel = new Label(composite, SWT.NONE);
reponseLabel.setText("Reponse:");

responseText = new Text(composite, SWT.MULTI | SWT.READ_ONLY | SWT.BORDER);
final GridData gd_responseText = new GridData(SWT.FILL, SWT.FILL, true, true);
gd_responseText.heightHint = 80;
responseText.setLayoutData(gd_responseText);

statusLabel = new Label(composite, SWT.BORDER);
final GridData gd_statusLabel = new GridData(SWT.FILL, SWT.CENTER, true, false);
statusLabel.setLayoutData(gd_statusLabel);
statusLabel.setText("...");
//
}

@Override
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}

}

Use Instantiations’ WindowBuilder Pro to Design SWT Application

I used Instantiations’ WindowBuilder Pro (also known as SWT Designer) to generate the above codes. I only wrote a few lines as:

sendButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
statusLabel.setText("Sending request ...");
String text = requestText.getText();
text = "[Server echo]:" + text;
responseText.setText(text);
statusLabel.setText("Server responded.");
}
});

Step 3. Run as Java Application and Java2Script.

Use context menu to “Run as” -> Java Application, and “Run as” -> Java2Script Application. You should get things work.

Java2Script Example Run as Native SWT Desktop Application

Java2Script Example Run as Java2Script Application Inside Browser

Step 4. Add Simple RPC into Example

Now it is time to move

text = "[Server echo]:" + text;

to the server side.

First, create a new EchoRunnable class extending net.sf.j2s.ajax.SimpleRPCRunnable as follow:

package org.java2script.demo.simplerpc;

import net.sf.j2s.ajax.SimpleRPCRunnable;

public class EchoRPCRunnable extends SimpleRPCRunnable {

public String text;

public void ajaxRun() {
text = "[Server echo]:" + text;
}

}

Then modify button’s event handler as follow:

sendButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
statusLabel.setText("Sending request ...");
SimpleRPCSWTRequest.swtRequest(new EchoRPCRunnable() {

public void ajaxIn() {
text = requestText.getText();;
}

public void ajaxOut() {
responseText.setText(text);
statusLabel.setText("Server responded.");
}

public void ajaxFail() {
statusLabel.setText("Request failed.");
}

});
}
});

Re-test the application in native Java SWT application mode. It should work as expected.

Step 5.? Deploy Java2Script Simple RPC Application

Open WEB-INF/web.xml and add org.java2script.demo.simplerpc.EchoRunnable to simple.rpc.runnables list. Here is the web.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Java2Script</display-name>
<description>Java2Script application</description>
<servlet>
<servlet-name>simplerpc</servlet-name>
<servlet-class>net.sf.j2s.ajax.SimpleRPCHttpServlet</servlet-class>
<init-param>
<param-name>simple.rpc.runnables</param-name>
<!--
Qualified names of inherited net.sf.j2s.ajax.SimpleRPCRunnable
classes, seperated by ";".
-->
<param-value>
org.java2script.demo.simplerpc.EchoRPCRunnable
</param-value>
</init-param>
<init-param>
<param-name>simple.rpc.xss.support</param-name>
<param-value>true</param-value>
</init-param>
<!--
<init-param>
<param-name>simple.rpc.post.limit</param-name>
<param-value>16777216</param-value>
</init-param>
<init-param>
<param-name>simple.rpc.xss.max.parts</param-name>
<param-value>8</param-value>
</init-param>
<init-param>
<param-name>simple.rpc.xss.max.latency</param-name>
<param-value>6000</param-value>
</init-param>
-->
</servlet>
<servlet-mapping>
<servlet-name>simplerpc</servlet-name>
<url-pattern>/simplerpc</url-pattern>
</servlet-mapping>
</web-app>

Select build.xml file, right click to bring up context-menu and “Run as” -> Ant Build, and then select the project and right click and select “Refresh” to refresh the project files, you will see a “org.java2script.demo.simplerpc.war” file. Now try to deploy this war file to a Java servlet container, such as Tomcat server.

If your Tomcat? server is installed in localhost, try url:

http://localhost:8080/manager/html

to deploy the above mentioned war file.

Deploy Java2Script Simple RPC Application *.war Package

But you haven’t finish deployment yet, because you still need to deploy Java2Script’s core *.js library files to the server.

Add the following to build.xml:

<target name="pack.plugins.j2slib.war">
<delete file="${basedir}/../plugins.war" quiet="true"/>
<zip destfile="${basedir}/../plugins.war">
<fileset dir="${basedir}/../../../plugins/">
<include name="net.sf.j2s.lib_1.0.0/**"/>
<exclude name="net.sf.j2s.lib_1.0.0/library.jar"/>
<exclude name="net.sf.j2s.lib_1.0.0/plugin.xml"/>
<exclude name="net.sf.j2s.lib_1.0.0/META-INF/**"/>
</fileset>
</zip>
</target>

And “Run as” -> “Ant Build …”, select “pack.plugins.j2slib.war” in the “Targets” tab and “Run”. Then refresh the project, and deploy the “plugins.war” to Tomcat server.

And after all things deployed, please visit:

http://localhost:8080/org.java2script.demo.simplerpc/org.java2script.demo.simplerpc.SimpleSWTRPC.html

Here is the online demo of this Simple RPC example.

(To be continued)

Posted in Tutorials | 598 Comments

JavaScript ClassLoader and Hotspot

If you are familiar with Java debugging, you must know there is a technology called “Hotspot“. One feature of Hotspot is to replace old classes bytecodes with a new ones that are generated by dynamic compilers. This feature helps developers a lot in debugging. That is to say, when a developer load a very complex application in debugging mode, he want to modify the sources a little, he can just do it, the compiler will compile those related classes and notify classloader to load those affected classes bytecodes. And the modified codes are on effects. It saves lots of time by avoiding closing, reopening and waiting big applications again and again. This is very convenient when comparing to those static compiled applications written by C or C++ languages.

OK, now comes to JavaScript classloader and Hotspot technologies. JavaScript classloader technology are already proved by Java2Script. You can load JavaScript classes on demands, and using SCRIPT in asynchronous mode or XMLHttpRequest (XHR) in synchronous or asynchronous modes. And these days, Java2Script is also implementing JavaScript’s Hotspot technology (Not released publicly at the time of this writing, but you can check Java2Script out from SVN repository right now using its 3.3 compiler branch.). Such JavaScript Hotspot technology is not complicate, because JavaScript is already a very robust and convenient language to do so. All Java2Script implementation is to clean those classes’ declaration inside JavaScript class inheritance system simulator. And then reload the *.js using Java2Script’s classloader. In the implementation, classloader does not change class or object’s prototype when a reloaded class is redefined, it’s possible to keep all classes relationships without breaking those already instantiated instances.

To trigger Java2Script class simulator to Hotspot swapping, there is a thread trying to load an updating JavaScript classes list from Java2Script compiler in Eclipse. Its work is simple, just trying to load http://127.0.0.1:1725/<session>.js. And the server listening on default port 1725 is started by Java2Script compiler, called “Java2Script Inner Hotspot Server (J2SIHS)”. When a compiling occurs, compiler will notify this server that a class is updated, and the server will add the information to the list. Once a JavaScript request arrives, it will send out the list according to the request session id. And when the JavaScript client thread gets the updated classes list, it will try to unload related classes and reload them. That is the rough procedure of Java2Script Hotspot technology.

By using Hotspot, I think it is much more convenient for me to develop JavaScript RIA in Java codes than before, especially in developing SWT applications.

Posted in Architecture | 26 Comments

What is Java2Script’s SimpleRPC

By using Java2Script’s SimpleRPC, there are no needs to know RPC (Remote Procedure Call) and no needs to know Java Servlet or J2EE! Only knowing developing Java desktop application is enough for developers. Here is magic.

Java2Script recommends writing applications in desktop ways. This means that all logics are developed in one container. But when you want to deploy the applications in a Browser/Server mode, you have to tear your applications into server logics and client logics. And to integrate logics between server and client, you need to transfer the datum, which you may be required to know how to wrap and unwrap data. This transformation and wrapping is the essence of RPC.

Java2Script also does the above wrapping for you, so you have no needs to know RPC wrapping. And Java2Script uses threads to simulate the remote J2EE server in local mode, so you can see no remote server and you can debug your logics smoothly as Eclipse JDT provide a very smoothly debugging experience for threads. As in normal J2EE server, each request is stateless. In such a way, Java2Script’s SimpleRPCRunnable instance (for Java local Thread) should be designed as a stateless instance.

In simple, Java2Script wraps and unwraps data between server (J2EE basing on Java) and client (Browser basing on JavaScript). And in local Java mode, Java threads are performing as J2EE server, which is much easier to be understood and to be debugged.

For more details about SimpleRPC, such as why not using Java’s RMI,? Java’s serializations, or JSON’s RPC, please keep tuned for the later articles.

Posted in Architecture | 91 Comments

Clarify Goal of Java2Script

Java2Script is not providing a JavaScript library for AJAX developers. Java2Script is providing tools to convert Java desktop applications into web applications.

By reading comments about Java2Script online, I found that someone treat Java2Script as a JavaScript library such as Prototype. In early stage of Java2Script development, “J2SClazz” is separated from Java2Script’s Class Inheritance Simulator to provide a better acceptance of Java2Script Pacemaker, but as later developer prove that “J2SClazz” is just too simple to prove the power of Java2Script technology, I did not update it afterwards.

You can write your JavaScript using “J2SClazz” library actually. But I don’t think it is convenient to do so. And if you also use Java2Script’s SWT library, you may find it very hard to use up all power of Java2Script. Only in Eclipse’s Java editor, you can create lots of anonymous event listeners (also anonymous inner class) for those UI components. And only in Eclipse, you can create a Dialog by dragging and dropping. If you write all your codes from scratch, you need lots of work. And you can not debug those JavaScript codes, which is always buggy!

I know that there are lots of differences between normal web applications and desktop applications. But developing desktop applications is a lot faster than web applications, there is no needs to care about HTML, CSS, or HTTP server and database server. So developing desktop applications is much easy for most of developers. And it will also increase the speed of new products. You know speed is one of the most important factor of new web applications. So desktop applications to web applications converting is an acceptable way for web applications.

And Java2Script is originally designed for such a developing ways. Java2Script is not aiming to provide a JavaScript library so that you can write your JavaScript codes much easier. What Java2Script is trying to provide is a tool help developers to develop web applications in a Java way, or in a desktop way. If this way is not a 100% pure way, we do want it to be 90% pure, which may help developers to write and debug their codes in a their much more familiar way.

In simple, Java2Script is providing tools not libraries.

Posted in Architecture | 1 Comment

ClassLoader Summary

Here is ClassLoader summary inside ClassLoader.js, for more information, please also read the ClassLoader source.

ClassLoader creates SCRIPT elements and setup class path and onload callback to continue class loading.

In the onload callbacks, ClazzLoader will try to calculate the next-to-be-load *.js and load it. In *.js, it will contains some codes like
Clazz.load (…, “$wt.widgets.Control”, …);
to provide information to build up the class dependency tree.

Some known problems of different browsers:

  1. In IE, loading *.js through SCRIPT will first triggers onreadstatechange event, and then executes inner *.js source.
  2. In Firefox, loading *.js will first executes *.js source and then triggers onload event.
  3. In Opera, similar to IE, but trigger onload event. (TODO: More details should be studied. Currently, Opera supports no multiple-thread-loading)

For class dependency tree, actually, it is not a tree. It is a reference net with nodes have n parents and n children. There is a root, which ClassLoader knows where to start searching and loading classes, for such a net. Each node is a class. Each class may require a set of must-classes, which must be loaded before itself getting initialized, and also need a set
of optional classes, which also be loaded before being called.

The class loading status will be in 6 stages.

  1. Unknown, the class is newly introduced by other class.
  2. Known, the class is already mentioned by other class.
  3. Loaded, *.js source is in memory, but may not be initialized yet. It requires all its must-classes be intiailized, which is in the next stage.
  4. Musts loaded, all must classes is already loaded and declared.
  5. Declared, the class is already declared (ClazzLoader#isClassDefined).
  6. Optionals loaded, all optional classes is loaded and declared.

The ClassLoader tries to load all necessary classes in order, and intialize them in order. For such job, it will traverse the dependency tree, and try to next class to-be-loaded. Sometime, the class dependencies may be in one or more cycles, which must be broken down so classes is loaded in correct order.

Loading order and intializing order is very important for the ClassLoader. The following technical options are considered:

  1. SCRIPT is loading asynchronously, which means controling order must use callback methods to continue.
  2. Multiple loading threads are later introduced, which requires the ClassLoader should use variables to record the class status.
  3. Different browsers have different loading orders, which means extra tests should be tested to make sure loading order won’t be broken.
  4. Java2Script simulator itself have some loading orders that must be honored, which means it should be integrated seamlessly to Clazz system.
  5. Packed *.z.js is introduced to avoid lots of small *.js which requires lots of HTTP connections, which means that packed *.z.js should be treated specially (There will be mappings for such packed classes).
  6. *.js or *.css loading may fail according to network status, which means another loading try should be performed, so ClazzLoader is more robust.
  7. SWT lazy loading is later introduced, which means that class loading process may be paused and should be resumed later.
Posted in Architecture | 11 Comments

Content of Inside Java2Script

Here is a rough content list of the book “Inside Java2Script”:

  1. Overview of Java2Script
  2. Tutorial of Java2Script: Core, SWT, AJAX
  3. JavaScript Class Inheritance Simulator
  4. HTML +CSS Widgets and SWT
  5. AJAX and SimpleRPC
  6. Inside ClassLoader
  7. More about Asynchronous Programming
  8. Plugin and Mixture of OtherLibraries

If you are familiar with or experienced in writing a book, please share your thoughts with me. Thanks.

Posted in Uncategorized | Leave a comment

JDT Compiling and Java2Script Compiling

One feature that I like Java2Script is its full integration with Eclipse JDT’s incremental building.

Java2Script reuses Eclipse JDT to compile *.java into *.js. As Eclipse JDT supports incremental building, so Java2Script also supports this feature. The magic is that when a *.java file is passed into JDT’s ImageCompiler, it is also passed through Java2ScriptImageCompiler.

To understand JDT’s incremental building, when a *.java is modified and compiled, this file will be compiled, and as always, this modification may affect other *.java files, that is to say, some other classes may need recompiling. JDT uses some algorithms to figure out those delta *.java and compile it, and compiling continues until there is no affected files that need to be compiled.

As compiling has its entry, Java2Script just install an extra compiler at the entry so that a *.java file is compiled into *.class, it also be compiled into *.js. This is? the whole magic of Java2Script builder.

But to inject a Java2Script compiler into existed JDT plugin requires some works. First JDT’s compiler is not designed to be injected. Modified the JDT sources and recompiling the plugin do works. But it’s not quite suitable for public, as it need to overwrite original JDT plugin jars. There is another factor that make a little difficult in implementing Java2Script compiler based JDT. A lot of classes in JDT are package accessible or their methods are not public. It need a lot of works to do so that those restricts can be avoided. And besides, Java2Script compiler codes must be maintainable, or when a new Eclipse version is released, all those hard works need to re-do.

In current Java2Script compiler, it reuses codes in package org.eclipse.jdt.internal.core.builder. All it need is to move all the sources into a new package named net.sf.j2s.core.builder. And some new proxy classes or new inherited classes are added so it is possible to access inner data structure. And Java2ScriptImageCompiler is injected into those JDT normal compiling process. And there are some tricks here. To convert some instances between two different classes without trigger ClassClastError, one instance (e.g. net.sf.j2s.core.builder.State instance) is serialized into DataInputStream first, and then it will be de-serialized into another instance (org.eclipse.jdt.internal.core.builder.State.). In all, in implementing Java2Script compiler, it use all kinds of tricks to expose JDT’s inner data structures to outside compilers.

For more details, please compare the Java2Script sources (net.sf.j2s.core.builder, net.sf.j2s.core.compiler) with sources in JDT (org.eclipse.jdt.internal.core.builder, org.eclipse.jdt.core.compiler)

Posted in Hacks | 2 Comments