This article demostrates the ways of developing J2S web application using java.util.* API. In a result, this article will show you how to generate JavaScript code translating the existed Java codes by J2S.
Please read previous tutorials:
For J2S 0.5.0, as bugs mentioned in bug#1439638, you may have to download the bugs fixed and re-packed java-core-util.jz file and replace the original java-core-util.jz in folder "j2slib". And rebuilding the project are also required.
In the previous tutorials, class J2User and J2SPet are created. Now I will link these two classes together by a class Relation (Source: Relation.java):
package net.sf.j2s.hello; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Relation { private J2SUser user; private List pets; private Relation() { // prevent instantialization from Java codes } public Relation(J2SUser user) { super(); this.user = user; this.pets = new ArrayList(); } public void addPet(J2SPet pet) { pets.add(pet); } public List getPets() { return pets; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("Description of owner:\r\n"); buffer.append(user); buffer.append("\r\n"); buffer.append("About "); buffer.append(user.getAdjective()); buffer.append(' '); buffer.append(pets.size()); buffer.append(" pets:\r\n"); for (Iterator iter = pets.iterator(); iter.hasNext();) { J2SPet pet = (J2SPet) iter.next(); buffer.append(pet); buffer.append("\r\n"); } return buffer.toString(); } }
As you can see from the code, that java.lang.StringBuffer is used, and java.util.ArrayList, java.util.Iterator, java.util.List are used.
Here following the HelloUserAndPets.java:
package net.sf.j2s.hello; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; public class HelloUserAndPets { public static void main(String[] args) { // users J2SUser josson = new J2SUser("josson", null, 24, ISex.MALE); josson.setEmail("josson@smith"); J2SUser kelly = new J2SUser("kelly"); kelly.setSex(ISex.FEMALE); // pets J2SDog bb = new J2SDog("baibai", 24); bb.setColor("black"); J2SDog ww = new J2SDog("wangwang"); ww.setSex(ISex.FEMALE); J2SDog dd = new J2SDog("digdig", 24, "yellow"); dd.setSex(ISex.FEMALE); // setup relations Relation unps1 = new Relation(josson); unps1.addPet(bb); unps1.addPet(dd); System.out.println("Relationship 1:"); System.out.println(unps1); Relation unps2 = new Relation(kelly); unps2.addPet(bb); unps2.addPet(ww); System.out.println("Relationship 1:"); System.out.println(unps2); // find the common pets System.out.println("Trying to find out who is the common pet:"); List jossonPets = unps1.getPets(); List kellyPets = unps2.getPets(); for (Iterator iter = jossonPets.iterator(); iter.hasNext();) { J2SPet pet = (J2SPet) iter.next(); if (kellyPets.contains(pet)) { System.out.println("Pet " + pet.getName() + " is owned by both " + josson.getName() + " and " + kelly.getName()); } } System.out.println(); // find all pets Set petSet = new HashSet(); petSet.addAll(jossonPets); petSet.addAll(kellyPets); System.out.println("In total, there are " + petSet.size() + " pets:"); for (Iterator iter = petSet.iterator(); iter.hasNext();) { J2SPet pet = (J2SPet) iter.next(); System.out.println(pet); } } }
As from the source, some APIs of java.util.*, such as contains, addAll, size, iterator and others are used.
Now we need some other *.jz rather than the j2s-core-common.jz. Here is the j2s-core-util.jz. Once you install the bug-fixxing version 0.3.1 of J2S, you can create a NEW Java project (re-enable old J2S project won't work) and enable the J2S compiler, j2s-core-util.jz will be copied to under j2slib automatically. Or You can download it from here. You can also study the source of j2s-core-util before it's compressed from j2s-core-util.js.
And then import the j2s-core-util.jz into the folder j2slib.
Open the run configurations, make a new Java2Script Application, which points to the HelloUserAndPets. In the Classpath tab, remove the "j2s-core-common.jz" from "Boostrap Entries", and click the button "Add JARs" from the right side. Then selected the newly imported j2slib/j2s-core-util.jz. And then remove unnecessary classes in the "User Entries" category:
And the j2s-core-util.jz supports the following java.* API classes:
Now, how can we run the above codes in J2S mode. The result in J2S Console (online demo) is the same as in Java Console:
Relationship 1: Description of owner: This is user josson, he is 24 years old. He has an email josson@smith. About his 2 pets: This is pet baibai. It is 24 months old. It has black furs. This is pet digdig. It is 24 months old. It has yellow furs. Relationship 1: Description of owner: This is user kelly, her age is unkown. She has no email at this time. About her 2 pets: This is pet baibai. It is 24 months old. It has black furs. This is pet wangwang. Its age is unkown. Its fur color is not mentioned. Trying to find out who is the common pet: Pet baibai is owned by both josson and kelly In total, there are 3 pets: This is pet baibai. It is 24 months old. It has black furs. This is pet wangwang. Its age is unkown. Its fur color is not mentioned. This is pet digdig. It is 24 months old. It has yellow furs.
Now you may wonder what is inside j2s-core-util.jz. The j2s-core-util.jz is a compressed javascript file, which contains some classes in java.util.*, java.lang.* and java.io.*. The classes is actually pieces of JavaScript codes, which is generated by Java2Script.
Here is the outline project, that I generate j2s-core-util.jz.
As you can see, a lot of familiar class exist in the project. In the listed classed above, I only modified about 4 lines of the source (those append () methods in StringBuffer.java). I did not modify the others. All the source is coming from JDK 1.4.2_06's source. And what I did was enabling the Java2Script compiler and compiling them into JavaScript. And then packed all the JavaScript codes into one file and compressed them. But besides those codes, I also provide some necessary founding JavaScript codes:
My ant build script is
<target name="j2s.core.util" depends="j2s.core.compile" description="Building j2s-core-*.jz"> <concat destfile="${jz.dist.dir}/j2s-core-util.jz"> <header filtering="no" trimleading="yes">/*=j2s= #Java2Script Configuration #Sun Jan 16 00:50:30 CST 2006 j2s.resources.list=console.css,java/lang/Class.js,java/lang/Object.js,java/lang/String.js,java/lang/Runnable.js,java/lang/Cloneable.js,java/io/Serializable.js,java/lang/Comparable.js,java/lang/CharSequence.js,java/lang/StringBuffer.js,java/util/Comparator.js,java/util/Iterator.js,java/util/ListIterator.js,java/util/Enumeration.js,java/util/Collection.js,java/util/Set.js,java/util/Map.js,java/util/List.js,java/util/RandomAccess.js,java/util/AbstractCollection.js,java/util/AbstractSet.js,java/util/AbstractMap.js,java/util/AbstractList.js,java/util/ArrayList.js,java/util/HashMap.js,java/util/HashSet.js,java/util/Dictionary.js,java/util/Hashtable.js,java/util/Properties.js,java/util/Vector.js,java/util/Stack.js =*/ </header> <filelist dir="${js.src.dir}"> <file name="java/lang/Class.js"/> <file name="java/lang/NoSuchMethodException.js"/> <!-- Inner Console --> <file name="java/lang/NativeConsole.js"/> <file name="java/lang/Object.js"/> <file name="java/lang/Encoding.js"/> <file name="java/lang/String.js"/> <file name="java/lang/Runnable.js"/> <file name="java/lang/Cloneable.js"/> <file name="java/io/Serializable.js"/> <file name="java/lang/Comparable.js"/> <file name="java/lang/CharSequence.js"/> <file name="java/lang/StringBuffer.js"/> <file name="java/util/Comparator.js"/> <file name="java/util/Iterator.js"/> <file name="java/util/ListIterator.js"/> <file name="java/util/Enumeration.js"/> <file name="java/util/Collection.js"/> <file name="java/util/Set.js"/> <file name="java/util/Map.js"/> <file name="java/util/List.js"/> <file name="java/util/RandomAccess.js"/> <file name="java/util/AbstractCollection.js"/> <file name="java/util/AbstractSet.js"/> <file name="java/util/AbstractMap.js"/> <file name="java/util/AbstractList.js"/> <file name="java/util/ArrayList.js"/> <file name="java/util/HashMap.js"/> <file name="java/util/HashSet.js"/> <file name="java/util/Dictionary.js"/> <file name="java/util/Hashtable.js"/> <file name="java/util/Properties.js"/> <file name="java/util/Vector.js"/> <file name="java/util/Stack.js"/> </filelist> </concat> </target>
This ant build script will build one *.jz file. And after getting these file, I will compressed the file using Edward.Dean's packer. As lots of codes, the original *.jz is already about 180k. After I packed them, there are about 60K (30%, still huge!). If you try to zip the *.jz, you will get a file about 20K (11%, That's what I want!).
As a bug of packer, which I already notified Dean (maybe Dean will fixed that bug someday on his site), the *.jz packed by the packer won't work correctly. I fixed that bug, and *.jz works. That is the *.jz that you used in this tutorial. It's recommend you to not to compressed the *.jz, as uncompress the *.jz will require CPU times loadint the slow JavaScript codes. For the transmission optimization of huge JavaScript codes, one recommended ways is to use Apache's mod_deflate for gzip transmission. Once you can't configure the server, you can use the compressed way. But keep in mind that uncompress the script takes times.
When I was preparing this tutorial, I found that I was not sure whether my java.util.* will work or not. Everytime, I ran the J2S application, I whispered in my heart: "Just passed, just OK, just ...". Still, I was not confident about those j2s codes. I wanted a series of some tests, which will tell me that my classes int JavaScript codes is doing the same thing as specification defined. I checked some web pages about Java TCK. I found that I am not a member of Sun' TCK group so I can not access the TCK toolkit. I also visited Apache's Harmony project, which seems that it will gain the TCK access as Apache has the right. No matter what, just try to use the java.util.*. Once you find something un-expected. Try to hack and fix it.
Further, I would like to demonstrate another example for resusing the codes by J2S.
For one more example, I will should you how to re-use the JDK's Base64 encoding and decoding.
You can find the source of java.util.prefs.Base64, then copy the source and paste it as a new class net.sf.j2s.hello.MyBase64. And then you make another HelloJ2SBase64 as followed (Following codes contains some Chinese characters which may not be displayed correctly. Just ignore these characters, please. I put them here just for demostrating J2S also work for some UTF-8 encoding problems):
package net.sf.j2s.hello; import java.io.UnsupportedEncodingException; public class HelloBase64 { public static void main(String[] args) throws UnsupportedEncodingException { System.out.println("testHello"); System.out.println("==========="); testHello(); System.out.println("*"); System.out.println(); System.out.println("testLongString"); System.out.println("==========="); testLongString(); System.out.println("*"); System.out.println(); System.out.println("testChinese"); System.out.println("==========="); testChinese(); System.out.println("*"); System.out.println(); System.out.println("testChineseUTF8"); System.out.println("==========="); testChineseUTF8(); System.out.println("*"); System.out.println(); } public static void testHello() { String s = "Hello J2S World"; System.out.println(s); String b64 = MyBase64.byteArrayToBase64(s.getBytes()); System.out.println(b64); byte[] bytes = MyBase64.base64ToByteArray(b64); String ss = new String(bytes); System.out.println(ss); } public static void testLongString() { String s = "J2S provides a way of translating Java codes into JavaScript. Lots of Java codes (such as algorithms library or UI widgets library) can be reused in JavaScript through J2S."; System.out.println(s); String b64 = MyBase64.byteArrayToBase64(s.getBytes()); System.out.println(b64); byte[] bytes = MyBase64.base64ToByteArray(b64); String ss = new String(bytes); System.out.println(ss); } public static void testChinese() { String s = "J2S项目旨在复用已有的Java代码,目前提供将Java代码直接转换成可以在浏览器中运行的JavaScript。该框架提供了最基本的JavaScript模拟Java继承关系的API,同时尝试提供java.util.*和org.eclipse.swt.*的API代码转换。"; System.out.println(s); String b64 = MyBase64.byteArrayToBase64(s.getBytes()); System.out.println(b64); byte[] bytes = MyBase64.base64ToByteArray(b64); String ss = new String(bytes); System.out.println(ss); } public static void testChineseUTF8() throws UnsupportedEncodingException { String s = "J2S项目旨在复用已有的Java代码,目前提供将Java代码直接转换成可以在浏览器中运行的JavaScript。该框架提供了最基本的JavaScript模拟Java继承关系的API,同时尝试提供java.util.*和org.eclipse.swt.*的API代码转换。"; System.out.println(s); String b64 = MyBase64.byteArrayToBase64(s.getBytes("utf-8")); System.out.println(b64); byte[] bytes = MyBase64.base64ToByteArray(b64); String ss = new String(bytes, "utf-8"); System.out.println(ss); } }
Now again, you HAVE TO configure the J2S configuration to make the HelloBase64 working. You should including the j2s-core-util.jz not the j2s-core-bare.jz. As the original j2s-core-bare.jz does not provide the ability of StringBuffer.
The classpath should be like these:
And the result (online demo) is:
testHello =========== Hello J2S World SGVsbG8gSjJTIFdvcmxk Hello J2S World * testLongString =========== J2S provides a way of translating Java codes into JavaScript. Lots of Java codes (such as algorithms library or UI widgets library) can be reused in JavaScript through J2S. SjJTIHByb3ZpZGVzIGEgd2F5IG9mIHRyYW5zbGF0aW5nIEphdmEgY29kZXMgaW50byBKYXZhU2NyaXB0LiBMb3RzIG9mIEphdmEgY29kZXMgKHN1Y2ggYXMgYWxnb3JpdGhtcyBsaWJyYXJ5IG9yIFVJIHdpZGdldHMgbGlicmFyeSkgY2FuIGJlIHJldXNlZCBpbiBKYXZhU2NyaXB0IHRocm91Z2ggSjJTLg== J2S provides a way of translating Java codes into JavaScript. Lots of Java codes (such as algorithms library or UI widgets library) can be reused in JavaScript through J2S. * testChinese =========== J2S项目旨在复用已有的Java代码,目前提供将Java代码直接转换成可以在浏览器中运行的JavaScript。该框架提供了最基本的JavaScript模拟Java继承关系的API,同时尝试提供java.util.*和org.eclipse.swt.*的API代码转换。 SjJT6aG555uu5peo5Zyo5aSN55So5bey5pyJ55qESmF2YeS7o+egge+8jOebruWJjeaPkOS+m+WwhkphdmHku6PnoIHnm7TmjqXovazmjaLmiJDlj6/ku6XlnKjmtY/op4jlmajkuK3ov5DooYznmoRKYXZhU2NyaXB044CC6K+l5qGG5p625o+Q5L6b5LqG5pyA5Z+65pys55qESmF2YVNjcmlwdOaooeaLn0phdmHnu6fmib/lhbPns7vnmoRBUEnvvIzlkIzml7blsJ3or5Xmj5DkvptqYXZhLnV0aWwuKuWSjG9yZy5lY2xpcHNlLnN3dC4q55qEQVBJ5Luj56CB6L2s5o2i44CC J2S项目旨在复用已有的Java代码,目前提供将Java代码直接转换成可以在浏览器中运行的JavaScript。该框架提供了最基本的JavaScript模拟Java继承关系的API,同时尝试提供java.util.*和org.eclipse.swt.*的API代码转换。 * testChineseUTF8 =========== J2S项目旨在复用已有的Java代码,目前提供将Java代码直接转换成可以在浏览器中运行的JavaScript。该框架提供了最基本的JavaScript模拟Java继承关系的API,同时尝试提供java.util.*和org.eclipse.swt.*的API代码转换。 SjJT6aG555uu5peo5Zyo5aSN55So5bey5pyJ55qESmF2YeS7o+egge+8jOebruWJjeaPkOS+m+WwhkphdmHku6PnoIHnm7TmjqXovazmjaLmiJDlj6/ku6XlnKjmtY/op4jlmajkuK3ov5DooYznmoRKYXZhU2NyaXB044CC6K+l5qGG5p625o+Q5L6b5LqG5pyA5Z+65pys55qESmF2YVNjcmlwdOaooeaLn0phdmHnu6fmib/lhbPns7vnmoRBUEnvvIzlkIzml7blsJ3or5Xmj5DkvptqYXZhLnV0aWwuKuWSjG9yZy5lY2xpcHNlLnN3dC4q55qEQVBJ5Luj56CB6L2s5o2i44CC J2S项目旨在复用已有的Java代码,目前提供将Java代码直接转换成可以在浏览器中运行的JavaScript。该框架提供了最基本的JavaScript模拟Java继承关系的API,同时尝试提供java.util.*和org.eclipse.swt.*的API代码转换。 *
When running the above codes, you should notice that it's somewhat slow! Running slowly is a big problem for JavaScript application and for J2S project. But at this time, from the perspective of reusing codes, just think that the codes is generated without modifying a byte, it saves times and energies to develop codes. And there should be a lot of lines which can be optimized too. We are working on optimizing these running JavaScript codes' performance.
OK, in the above tutorial, we demonstrate how to re-use java.util.* classes. Besides java.util.* classes, other packages can also be re-used once it's feasible for reusing codes. Some factors should be considered before you begin to re-use your packages:
One of the J2S exporting project working on is "JavaScript version of org.eclipse.swt.*" by j2s.sourceforge.net. It's a challenging work. The source of org.eclipse.swt.* contains lots of native codes for different OSs. And in order to make the SWT widget compatiable with different browsers, it requires that the coming SWT JavaScript codes should take care of the different browsers. Currently, Mozilla/Firefox 1.0+ and Internet Explorer 6+, are the mainly considered supported browsers.
As being an open source project, anyone who is interested in this project can join us. Or you may just contact me for details of J2S. Here is the draft roadmap of Java2Script:
Tutorial of J2S in Eclipse (5): How to Use org.eclipse.swt.* -- Tour to UI
Tutorial of J2S in Eclipse (6): How to Use ajax.* -- A Simple RSS Reader
Down the net.sf.j2s.hello project files (zip) (61k)
Have problems while reading through these articles? Or find some errors between the words? Or have some ideas on the Java2Script technology? Please make comments or discussions here in the blog.
Zhou Renjian: Initial contributor of Java2Script.