Using Antenna with Netbeans

Antenna [http://antenna.sourceforge.net]There has been a lot of buzz around Antenna, an Ant add-on for J2ME applications. Why! Can’t I use Ant for this? You very well can, but Antenna elevates many Ant tasks that are peculiar to J2ME, for instance: updating the JAD for the correct JAR size, a task that doesn’t matter as long as you are running your Midlets on the Wireless Toolkit (WTK) but is an absolute must for the Application Manager to be able to load your application on a real device.

This post doesn’t talk about why J2ME developers should go for Antenna (see links at the end for pointers on that) but on how to use Antenna with Netbeans, an IDE for Java. Suffice to mention here that Antenna has brought in many Ant tasks that perform the key functions of the WTK including compilation, preverification, class file obfuscation, updating MIDlet-Jar-Size attribute in JAD and automatic generation of Manifest file. It goes without saying that since Antenna depends on the WTK you require the latter installed on your machine.

While Eclipse supports Antenna, as of now, Netbeans does not provide Antenna module, though it has built-in support for running Ant tasks. Infact using this support we can use Antenna with the IDE very easily. The solution has been tried on Netbeans 3.5/3.6. Here are the steps involved:

  • The first step obviously would be to download Antenna JAR file. Without the worry of using Antenna with Netbeans you may have dropped it in your Ant classpath (for eg:
  • Start Netbeans. Go to Tools > Options > Building > Ant Settings > Properties. Add the following custom property (The property value will vary according to the actual Antenna JAR path on your machine):
    antenna.home=E\:\\antenna-bin-0.9.12.jar
    

    Note the special way of specifying the file path on Windows .

  • Add the following to your build file:
    <taskdef classpath"${antenna.home}" resource="antenna.properties"/>
    

    The antenna.properties file has been included in the Antenna jar and evades the worry of manually adding all the WTK tasks to your build file, such as:

    <taskdef name="wtkjad" classname="de.pleumann.antenna.WtkJad"/>
    <taskdef name="wtkbuild" classname="de.pleumann.antenna.WtkBuild"/>
    ...
    

    More details can be found at the Antenna homepage.

  • That’s all. Now you may execute the build file.

Download
Click here to get a sample Antenna build file.

You may find a sample Antenna build file here that I made to play with the application mentioned here. This assumes that you already have Proguard obfuscator downloaded and copied to bin folder of your WTK installation folder. Do note that for the wtkpackage task you should also Preverify (i.e. add attribute preverify=true) when your are Obfuscating (i.e. when obfuscate=true), this is needed because obfuscation destroys the extra information added by the preverifier. If you do not preverify you may get error similar to following when launching the application.

Running C:\J2mewtk\apps\AntDemo\final\Animation.jad in DefaultColorPhone
Error verifying method corej2me/a paint(Ljavax/microedition/lcdui/Graphics;)V
Approximate bytecode offset 6: Inconsistent or missing stackmap at target
ALERT: Error verifying class corej2me/a

Related links:

Many thanks to J Pleumann, the creator of Antenna, for answering to my many queries and for the excellent free add-on.
Disclaimer: The information provided on this page comes without any warranty whatsoever. Use it at your own risk.

The chunked problem

One of the J2ME applications I had been involved in emerged with a big problem when tested for boundary conditions. When the client was sending less than 2048 bytes, the server was able to handle it correctly. The content-length header was being set in the client correctly and was available at the server. The J2ME client uses javax.microedition.io.HttpConnection class to make HTTP connection to the application server. Here is the code snippet:

HttpConnection httpCon = (HttpConnection) Connector.open(url, Connector.READ_WRITE);
httpCon.setRequestMethod(HttpConnection.POST);
httpCon.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
//Set Headers
httpCon.setRequestProperty("Content-Language", "en-US");
httpCon.setRequestProperty("Accept-Language", "en");
//Send request
if (data != null) {
	int len = data.length();
	httpCon.setRequestProperty("Content-Length", Integer.toString(len));
	os = httpCon.openDataOutputStream();
	os.write(data.getBytes());
	os.close();
}

When the client data exceeds 2048 bytes I noticed from the Network Monitor tool of Wireless Toolkit that the content-length header would vanish and another header transfer-encoding attribute with value as “chunked” was being inserted. A little digging revealed that the problem was a known one and referred to as HTTP chunking, which means in brief that HTTP1.1 provides for chunked encoding letting large messages to be split into smaller chunks thus paving way for persistent connections. There were some previous discussion with no headway here and here. Furthermore, none discuss on how to deal with the problem on server side. Notice that the client side code handles the chunking problem as advised on the mentioned source.

I discussed this with Eric Giguere who said that

The WTK does indeed switch to chunked encoding once the data you post goes over 2K. Chunked encoding is part of the HTTP 1.1 specification and so the WTK expects the web server to deal correctly with it. However, web servers seem to vary a lot in their handling of it. There's nothing you can do about this, unfortunately, you have to use a web server that handles the chunked encoding properly.

Thing that perplexes me is the fact that my application server Websphere 4.x does support HTTP 1.1, it was even able to send data in chunks to my J2ME client, which was able to handle it nicely but the reverse was not true. In fact Network Monitor told me that as soon as data becomes even 2049 bytes the headers were sent correctly (again with no content-length and with chunked transfer-encoding) however the body was just empty. Since the body was received empty, my Servlet was unable to procure any request parameter and the request bombed.

I could have even digested that the Network Monitor tool is erroneous or the problem is only happening when tested on the emulators because the problem was detected on the actual device. Ultimately we had to curtail the amount of data we send at one go to solve the problem but as you might have guessed by the post I am looking for some sane explanation of this.