<$BlogRSDURL$>

Sunday, March 14, 2004

My First Try at Fedora Core 1 as a Desktop
I'm a bit slow at doing this but I just tried Fedora Core 1 as the first time as a Desktop. Lots of review has been done so I won't bother doing another. As an Asian user, I'd like to point out something really noteworthy for me. Simplified Chinese support under Redhat 9 was kind of flaky (at least it was with the out of the box configuration), with many Chinese characters somewhat undisplayable on the shell (and in file selection dialogs).

In Fedora Core 1, Chinese characters displayed perfectly, out of the box. The Chinese fonts loaded into the system looks much nicer than the ones Redhat 9 had. That's really cool!

Saturday, March 13, 2004

Becoming a Coffee Aficionado :P

Well all my life I've been a non-discerning coffee drinker. Being the lazy person I am, I settled for instant coffee most of the time. And seriously, coffee shop coffee (a "coffee shop" in Singapore really means a place where a lot of local food is served, rather like a cafe) and Starbucks coffee were pretty much the same thing to me.

Well, some things changed recently and I began to realize the subtle differences between these coffees. I guess it first started when I began to find that "coffee shop" coffee are way too sweet and heavy (as in I don't seem to digest them very well), and just don't go down well anymore. That's because they add a lot of sweetened condensed milk into the coffee.

Some time has passed and I'm finding self-brewed Latte to be the healthiest choice. I'm beginning to love the natural sweetness of natural (not condensed) milk. For Singaporeans, most packaged milk here sucks for making coffee, but I found Marigold pretty good.

As for coffee beans, I've been getting them from a wholesale shop near my office. I must say that these guys trade a lot of coffee beans but don't know much about coffee. I was left to do a a lot of research on my own. The first few packets of ground beans I bought from them were arabica/robusta blends that were mostly robusta (based on their recommendation). They sell some pretty good robusta beans there, even though robusta beans were thought to be inferior. Well the coffee tasted fine and I began to be a little more adventurous and went for an 80% arabica and 20% robusta blend instead. That worked out much better, and my Latte tasted much more like the stuff we buy from Starbucks. And since SGD20 fetches you 1kg of coffee powder, that's a lot of coffee as compared to 4-6 cups of Starbucks coffee that would've bought you.

I'm still far away from being a coffee expert, but it's all been pretty fun.
Using Ant to build executable Jar files

Having built apps that run on the application server most of the time, this is my first shot at building my own server program that runs outside of the application server. Obviously, for ease of deployment reasons, I have chosen to deploy it in the form of an executable Jar, so that you can run it with a command like:

java -jar foobar.jar

In order for the JVM to know which class from which to run the main method inside the Jar file, the Manifest File has to have an entry that says something like:

Main-Class: com.company.main.MainClass

The JVM will then execute the public static void main method found in com.company.main.MainClass

What I did, like most people, was to create the Manifest file by hand and then have Ant run the Jar task to create the archive. However, this doesn't work. The Manifest file created by hand will be replaced by a Manifest file that Ant has created. Ant's Jar task will create it's own Manifest file and therefore, you need to use Ant's Jar task to create the Manifest file instead of creating the Manifest file by hand.

This Ant task worked.

<target name="jar" description="Make Archive" depends="compile">
<jar destfile="${deploy}/theJarFile.jar">
<fileset dir="${bin}">
<include name="${theClassFiles}/**"/>
</fileset>
<metainf dir="${src}/${metainf}">
<include name="*.xml"/>
</metainf>
<manifest>
<attribute name="Built-By" value="Me"/>
<attribute name="Main-Class" value="com.company.main.MainClass"/>
<attribute name="Class-Path" value="log4j-1.2.7.jar jboss-j2ee.jar"/>
</manifest>
</jar>
</target>


The Ant manual page can be found here
http://ant.apache.org/manual/CoreTasks/jar.html

Getting into socket programming again
Low level programming work has never been my forte. Having worked with mostly web-apps (PHP,Perl) and now J2EE apps, the binary stuff that of C and TCP/IP programming has always been daunting for me.

This is my second attempt at any kind of socket work. The first attempt was a bunch of Perl client/server pairs that was pretty simple because the roles of the client and the server were very well demarcated. In other words, blocking I/O could be used. Blocking I/O is simple to implement, if your app only functions as a client or as a server, but never both at the same time. All the server does is to wait for requests, and the client simply resides in a method that's called whenever the program needs to send something to the server.

For simple client/server pairs using blocking I/O, you can read a Sun tutorial here

The second attempt, however, made me push my limits in this area again. Thankfully, however, I decided to do it in Java. The specs required me to write a server program that maintains a persistent connection with the other end. Both ends function as server and client simultaneously. Blocking I/O won't work because the same channel is used for reading and writing. It could only mean one thing, non-blocking I/O.

I don't really intend to explain in detail the difference between blocking and non-blocking I/O, as there are already a lot of resources explaining it. This is an excellent example

Most of the materials out there still use dedicated servers or clients as examples, and doesn't really talk about what happens if you program functions both as a client and as a server, and with a persistant connection. Most examples suggest the use of a selector so that the program blocks until a read takes place. But if your program doesn't just wait for reads but could also initiate writes, it isn't clear what happens.

Well, if your selector is tuned to monitor for both reads and writes, what happens is that you will know when a read needs to be attended to, but when there's no reads, the selector will return the write all the time. In other words, the selector will not block. This method still offers an advantage because I don't have to write code to check if there's a read, when there is a read, the selector will let me know. Otherwise, the channel is always open for writing, and therefore code to throttle the infinite loop is still necessary (i.e. Thread.sleep()).

Thursday, March 04, 2004

2 weeks passed and still not Googled :-(

Anyway, I've been real busy at work and haven't had the time to blog some things that I'm dying to write about. There's really been a lot of talk these days about Open Source Java but I think most of the discussion lacks direction because it fails to make a distinction between:

a. Open Source implementation of Java
b. Open Specs as in Sun relinquishes its final say on spec matters (if it still has that right under JCP)
c. Implement the specs without having to pay royalty or to ask Sun for permission

Also, I've been doing a bit of socket programming on Java these days, and using non-blocking I/O for the first time. You need it when a persistent connection is used to send requests to the other end, and to receive requests from the other end, at the same time.

This page is powered by Blogger. Isn't yours?Weblog Commenting and Trackback by HaloScan.com