Sunday, December 30, 2007

3 Solutions to GNOME/VNC keyboard mapping issue

I am trying to connect to my workstation in the office via vncviewer and I got scrambled keys in GNOME before I applied one of the fixes below. This has bugged me for more than a week and Google couldn't really give me a good answer until I searched for:

asdf abfh vnc

Try.

It is a bug reported at #108928 and duplicated at #112955. Appears more like a GNOME issue than a VNC issue.

Solution #1: Use vnc4server -extension XFIXES

No, I did not try this because I simply do not want to change my client. The workaround basically requires you to remove tightvncserver and use vnc4server instead. Refer to this and this for more information.

Solution #2: Avoid executing gnome-session

Instead of running gnome-session, run the following commands in your xstartup script or manually in xterm:

gnome-wm &
gnome-panel &
gnome-cups-icon &
gnome-volume-manager &

Suggested by Randy at this link.

Solution #3: Reset the keyboard layout via gconf-editor

This solution works the best in my opinion, suggested by Will at this link. Open up gconf-editor in your X then navigate to:

desktop > gnome > peripherals > keyboard > kbd

You will probably be seeing empty value [] or [us] for the layouts. Enter anything say foo, close the application and your problem should now be fixed.

- yc, one problem in life down

Sunday, December 23, 2007

Quick Dive into CXF

REST
REST is no longer a new term, you are probably falling too far behind if you haven't yet heard of it. Daniel Diephouse, the creator of XFire (who is also now a Software Architect of MuleSource) wrote an interesting article about REST and SOA not too long ago, he sees REST as the next big trend in SOA.

If you are into this and if you are a Java guy, you may also be aware of the JSR 311 - The JavaTM API for RESTful Web Services and the Jersey (implementation). You would have also been told that Apache Axis 2.0 and Apache CXF (Celtic XFire) supports REST.

The rest of the blog entry, I will be sharing about how I toyed around with CXF, after taking a quick glance at it and learned how easy using it to write a Web-/REST- service.

Get a POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelversion>4.0.0</modelversion>
<groupId>sandbox</groupId>
<artifactId>apache-cxf</artifactId>
<version>2007.12.18</version>

<properties>
<cxf.version>2.1-incubator-SNAPSHOT</cxf.version>
<spring.version>2.0.6</spring.version>
</properties>

<repositories>
<repository>
<id>apache.incubating.releases</id>
<name>Apache Incubating Release Distribution Repository</name>
<url>http://people.apache.org/repo/m2-incubating-repository</url>
</repository>
<repository>
<id>apache.snapshot.releases</id>
<name>Apache Snapshot Release Distribution Repository</name>
<url>http://people.apache.org/repo/m2-snapshot-repository</url>
</repository>
</repositories>

<dependencies>

<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>

<!-- Depending on your requirements you may need more or less modules from cxf -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-core</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-simple</artifactId>
<version>${cxf.version}</version>
</dependency>
<!-- REST!! -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-databinding-aegis</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-local</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-jms</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-management</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-common-utilities</artifactId>
<version>${cxf.version}</version>
</dependency>
<!--dependency>
<groupId>jersey</groupId>
<artifactId>jersey</artifactId>
<version>0.4-ea</version>
</dependency-->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>0.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>

</project>


Write the Code
Once you have built the project into your favourite IDE, start writing the code:
  1. A service interface

  2. A service implementation

  3. A Java main class


package sandbox.cxf.api;
import javax.jws.WebParam;
import javax.jws.WebService;

import sandbox.cxf.resources.Author;
import sandbox.cxf.resources.Message;

@WebService(name = "sampleService")
public interface SampleService {

public Message getEcho(@WebParam(name="input") String string);
...
}

package sandbox.cxf.services;
import javax.jws.WebService;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.UriParam;
import javax.ws.rs.UriTemplate;

import sandbox.cxf.api.SampleService;
import sandbox.cxf.resources.Message;

@UriTemplate("/sampleService")
@WebService(endpointInterface="sandbox.cxf.api.SampleService", serviceName="defaultSampleService")
public class DefaultSampleService implements SampleService{

@HttpMethod("GET")
@UriTemplate("/echo/{input}")
public Message getEcho(@UriParam("input") String string){

System.out.println("Echoing message of " + string);

Message message = new Message();
message.setBody(string);

return message;
}
...
}


No *.properties or *.xml crap, this is how quickly you can configure and boot a SOAP and REST service:

SampleService sampleService = new DefaultSampleService();

JaxWsServerFactoryBean wsServerfactoryBean = new JaxWsServerFactoryBean();
wsServerfactoryBean.setServiceClass(SampleService.class);
wsServerfactoryBean.setAddress("http://localhost:8081/sampleService");
wsServerfactoryBean.setServiceBean(sampleService);
wsServerfactoryBean.create();

JAXRSServerFactoryBean restServerFactoryBean = new JAXRSServerFactoryBean();
restServerFactoryBean.setResourceClasses(Message.class);
restServerFactoryBean.setBindingId(JAXRSBindingFactory.JAXRS_BINDING_ID);
restServerFactoryBean.setServiceBeans(sampleService);
restServerFactoryBean.setAddress("http://localhost:8082/");
restServerFactoryBean.create();


Add logging interceptors if you want some logging and debugging:

wsServerfactoryBean.getInInterceptors().add(new LoggingInInterceptor());
wsServerfactoryBean.getOutInterceptors().add(new LoggingOutInterceptor());


Try Now
Once you have done the above, try to access the services via browser, e.g.

REST: http://localhost:8082/sampleService/echo/foobar
<message>  <body>foobar</body>
</message>


SOAP: http://localhost:8081/sampleService/getEcho?input=foobar
<soap:envelope soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:body>
<ns1:getechoresponse ns1="http://api.cxf.sandbox/">
<ns2:message ns2="http://api.cxf.sandbox/">
<body>foobar</body>
</ns2:Message>
</ns1:getEchoResponse>
</soap:Body>
</soap:Envelope>


Isn't that quick? ;-)

- yc

Monday, December 17, 2007

Malaysia is not much open-source penetrated

Wandering around in Google, I found this list which I actually took a look a few months back:


MAMPU, the Malaysian Administration Modernisation and Management Planning Unit, is appointed to implement the OSS initiative in the Malaysia public sector.

Of course, I am happy to see such move taken by our government, but I feel like there are still a lot of works to do.

I give my support to the folks at Open Malaysia too.

- yc

Friday, December 14, 2007

I thought I was Recharged

For a moment, I thought I was recharged after a cool holiday with some church kids in the past 4 days.. but now, being back to the real world, I feel so tired again.

One exciting news to share about is that I won a place (not the top-3 though, I heard) in the eGenting programming competition. And I'm on my way to attend the presentation night in an hour time.

Updated: I got a merit, not too bad. I believe it's the rich use of Java APIs (Pattern, Comparable, Collections) on the merge-sort question that made me one of the winners.

But there are more bullshit than good news, all thanks to GPRS (little Jen doesn't support 3G). See:
We have just set up a series of polls in our company (internal wiki) for the "Best of 2007". Now I wonder, what're the "Best of 2007" in Malaysia and how're you going to end yours.

- yc

Sunday, December 9, 2007

Human Rights Day

"When lawyers and the rakyat fail to march just because the police prefer to arrest people rather than protect them - the nation loses big time...

This is our right to march peacefully on the street. We can’t let them take it away from us."


10th of December is the Human Rights Day, the Malaysian government, however, hasn't been respecting it much and arresting the people happened to peacefully walk today.

The quote above is taken from Li Tsin's recent entry, do check it out. More stories in Jeff Ooi's blog.

- yc

Wednesday, December 5, 2007

A little bit of 'target jsr14'

I was taking a look at the Mule's CXF transport which requires Java 5.0. While doing that, I ranted about the annotations feature to one of my colleagues (I simply do not like the idea that having "@Override" in my code stops my 1.4 compiler, why not "// @Override").

I then read about this article -- Using Java 5 language features in earlier JDKs which mentions about the jsr14 (oh, I haven't tried it before, really). Specifying "jsr14" as your target VM version is a workaround of having 1.5 source to run on earlier JVM, however, it is not recommended by Sun, not supported, and not documented. Refer to this document for supported target values.

For that case, I wasn't too surprised that I can't read much about its details with a few Google search attempts.

These are what I have tried:

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class Source{

private List foo = null;

public List getFoo(){
return this.foo;
}

public void setFoo(List foo){
this.foo = new ArrayList(foo);
}

@Deprecated
public String toString(){
return "Foobar always!";
}

public static void main(String[] args)
throws Exception{

Method method = Source.class.getMethod("toString", new Class[]{});
if(method.isAnnotationPresent(Deprecated.class)){
System.out.println("toString is deprecated! :-|");
}

List foo = new Vector();
foo.add("Foo");
foo.add("Bar");

Source src = new Source();
src.setFoo(foo);

for(String fooElement: src.getFoo()){
System.out.println(fooElement);
}
}
}


Deprecated has a @Retention(RetentionPolicy.RUNTIME) (see An Overview of Java 5's Annotations). Then, compiled with 1.5:

/opt/java1.5/bin/javac -verbose Source.java -source 1.5 -target 1.5
[parsing started Source.java]
[parsing completed 39ms]
[search path for source files: [.]]
[search path for class files: [/usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/jsse.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/jce.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/charsets.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/ext/sunjce_provider.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/ext/localedata.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/ext/sunpkcs11.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/ext/dnsns.jar, .]]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/reflect/Method.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/ArrayList.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/List.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/Vector.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Object.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/String.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Exception.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Deprecated.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/Annotation.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/Retention.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/RetentionPolicy.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/Target.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/ElementType.class)]
[checking Source]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/Collection.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/AbstractList.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/AbstractCollection.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Iterable.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Throwable.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Class.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/NoSuchMethodException.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/SecurityException.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/reflect/AccessibleObject.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/System.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/io/PrintStream.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/io/FilterOutputStream.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/io/OutputStream.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Error.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/RuntimeException.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/Iterator.class)]
[wrote Source.class]
[total 335ms]


Running using 1.4:

/opt/j2sdk1.4/bin/java Source
Exception in thread "main" java.lang.UnsupportedClassVersionError: Source (Unsupported major.minor version 49.0)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:539)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:251)
at java.net.URLClassLoader.access$100(URLClassLoader.java:55)
at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)


Recompile with jsr14:

/opt/java1.5/bin/javac -verbose Source.java -source 1.5 -target jsr14
[parsing started Source.java]
[parsing completed 47ms]
[search path for source files: [.]]
[search path for class files: [/usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/jsse.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/jce.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/charsets.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/ext/sunjce_provider.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/ext/localedata.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/ext/sunpkcs11.jar, /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/ext/dnsns.jar, .]]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/reflect/Method.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/ArrayList.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/List.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/Vector.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Object.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/String.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Exception.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Deprecated.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/Annotation.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/Retention.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/RetentionPolicy.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/Target.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/annotation/ElementType.class)]
[checking Source]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/Collection.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/AbstractList.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/AbstractCollection.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Iterable.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Throwable.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Class.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/NoSuchMethodException.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/SecurityException.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/reflect/AccessibleObject.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/System.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/io/PrintStream.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/io/FilterOutputStream.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/io/OutputStream.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/Error.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/RuntimeException.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/NoClassDefFoundError.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/LinkageError.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/lang/ClassNotFoundException.class)]
[loading /usr/lib/jvm/java-1.5.0-sun-1.5.0.13/jre/lib/rt.jar(java/util/Iterator.class)]
[wrote Source.class]
[total 366ms]


Re-run with 1.4:

/opt/j2sdk1.4/bin/java Source Exception in thread "main" java.lang.NoClassDefFoundError
at Source.class$(Source.java:26)
at Source.main(Source.java:27)
Caused by: java.lang.ClassNotFoundException: java.lang.Deprecated
at java.net.URLClassLoader$1.run(URLClassLoader.java:199)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:141)
... 2 more


Ouchhh :(

Get rid of Deprecated.class from code, recompile and run:

/opt/j2sdk1.4/bin/java Source
Foo
Bar


Pfffft? ;)

- yc

Monday, December 3, 2007

JIRA Transport 1.0 Released

I have released my MuleForge project -- JIRA Transport yesterday. The transport enables easy integration of Mule (the leading open source ESB) with JIRA, and at this version, it has yet to support message receiving.

Click here to find out more about it.

- yc

Wednesday, November 28, 2007

For the Green

Wrote a blog entry about being puzzled by static methods and tearing down MuleManager in a failed test.

Read this link.

Wrote a ConstantsHelper class too for Constants, although it doesn't sound necessary.

- yc

Monday, November 26, 2007

One of the many problems of OpenID

I have just come back from a short trip, which has given me some space off work and had some time to start thinking about getting things done.

So, one of the very first actions is to get into Issues Done then realized I could not login as my OpenID server -- Videntity is either down or gone.

Stefan Brands wrote a good entry to discuss about the problems of and with OpenID. Do check it out.

The model of OpenID suggests a decentralized approach which arguably is its strength and at the same time its biggest weakness. The service is no longer dependent on just the service provider but also the external authentication service provided by a third party.

Ideally, if all servers are available, everything works in yours and the dreams' favor. But at this moment, I am totally prohibited to enter any of my sites registered under my OpenID. How bad it is?

- yc, pffft

Tuesday, November 13, 2007

From Nightwish to Nightmare

I had two visits to Aussie. Every time, I brought back a Nightwish album for my sister.

In year 2006, I bought Highest Hope when I was in the Melbourne city; In year 2007, I bought End of an Era from somewhere near QvB.


The departure (an expel actually) of Tarja Tarunen shocked me, it was during my Uni final semester. Early this year, Anette Olzon joined as a replacement of her, but I didn't really have the time to check her out. 'til lately, my sister dug up their new songs and videos (via YouTube) and she kept expressing her sad feeling to me.

I could understand and neither I could tolerate the way Anette screwed up the beautiful Wishmaster.

It simply doesn't work. Tarja is a talented musician and an opera performer but Anette is.. Whatever she is, I am not here to whine but to say that -- not every thing is replaceable, let's call this a new band.

- yc, missing Tarja

Sunday, November 11, 2007

Demonstation, a Display of Democracy

You could hardly see a mass peaceful demonstration in Malaysia. And it happened yesterday:

Crowd to Palace

Our government wasn't happy and this is what spoken by our deputy Prime Minister:
"If they (the Opposition during the Bersih rally on Saturday) can gather 10,000 people, the Government through Barisan Nasional can gather even more people.

"But what is the use if such demonstrations only lead to the possibility of ruining what we have built for the country?" he said.
I wasn't there because of the opposition. I was there because I could see that the country needs a change and what they have built so far are shame, corruption, stupidity, and ruining freedom and democracy.

Pictures at Flickr.

- yc, pffft

Friday, November 2, 2007

How to be successful at Integration

This whitepaper, written by the CTO of my company -- Robert Castaneda, gives a pretty clear introduction on what integration is.


You may love the pictures.

- yc

Thursday, November 1, 2007

Got my groove on IASA (Malaysia) October Chapter Meeting

I attended the IASA Malaysia October Chapter Meeting on Tuesday, it featured:

  • Business Process Management Enabled by SOA -- Kevin Khaw, Senior Technology Advisor, IBM Malaysia

  • Managing Changes & Mitigating Risk in Software Development -- Amir Gheibi, Chief Software Architect, SnT Global Sdn Bhd

Kevin is from the WebSphere group, he talked about how important business process is and it's usually overlooked as people emphasize more on the service and products. BPM is a discipline not a technology, it solves the problem of undocumented processes, inefficiency caused by bottlenecks, limited visibility into runtime performance, complex integration across multiple processes, cumbersome process changes, undefined KPIs, etc.

The slides and diagrams, however.. are not available in the repository yet, otherwise it could be easier to depict it.

I found the left-to-right business model and top-down BPEL model inspiring though, they sparked me some ideas to create some high level diagrams to describe certain processes in a support project that I'm working on, e.g. training and evaluation, daily support work, etc.

Amir shared about how changes could be introduced to a project and their impacts to it. His final slide clicked with what I kept thinking about during the presentation. Agile and TDD, as an iterative approach to cope with changes.

At the end of the presentation, I questioned about adopting Agile is more of a political issue in most of the companies in Malaysia, Amir did not deny the fact and instead he emphasized that an architect has the responsibility of being a politician to influence the management and people. He also touched a bit on the "Iron Triangle", using its factors in planning and negotiation.

It was a good night anyway. Am looking forward for other upcoming IASA events.

- yc, groovy

Monday, October 29, 2007

Cp1252 Nightmare

It was a horrible experience. Spending more than an hour to recreate workspaces and reimport projects, just to get rid of the strange Eclipse build error:

The project was not build since the source file ${path} could not be read

I did not have any problems to compile the code using Maven though.. So, why was Eclipse complaining? Some search results in Google suggested to me that it could be a file encoding issue. I was pretty sure that would be the case since the code might be checked in by someone on a Windows machine.

I switched to my Windows environment and the code could be successfully built.

Well, well.. but what's the solution? After being annoyed by the error for more than an hour, I slammed Eclipse by forcing the project to use Cp1252 encoding and dramatically the build works. Now, changing the text file encoding back to UTF-8 works too (which previously did not).

Why?

- yc, pwnz0r

Saturday, October 27, 2007

Google goes Flex

I talked about Microsoft Silverlight a month back and I always have doubt how successful it could be. I have been keeping an eye on Flex (I don't do Flex though, but my company does) and it is always interesting to discover new sites adopting to this cool technology.

Yakov Fain blogged about SearchMash, a Google operated project. Take a look at it here to find out how interactive search engine will turn to.. soon.

As a side note, my friend Chee Seng runs the Malaysian Flex User Group, please join to support the community. If you are not from Malaysia, you may want to look into this directory.

- yc, sunday arvo.. is hot!

Sunday, October 21, 2007

Ubuntu 7.10 - Gutsy Gibbon with XGL

Upgraded my Ubuntu to 7.10 yesterday, the coolest add-on to it is the support of Compiz Fusion (Compiz effects came in at 7.04 actually). Some of you might have seen the effects, which I will briefly walk through those that I have experienced later before I end this short blog entry.

A few problems that I experienced after the upgrade were:

  1. Restricted drivers manager not working. It said something like this:
    You need to install the package linux-restricted-modules-* for this program to work.
    Solution: Install the restricted module, e.g.
    apt-get install linux-restricted-modules-2.6.22-14-generic

  2. Couldn't turn on Compiz effects via System -> Preferences -> Appearance -> Visual Effects. It said something like:
    Desktop effects could not be enabled
    Solution: Turn on "Composite" in /etc/X11/xorg.conf, i.e.
    Section "Extensions"
    Option "Composite" "1"

    However, before that, you have to install the GL based X server, i.e.
    apt-get install xserver-xgl

    Then, restart your X server (ALT + CTRL + Backspace) after you have made configuration changes.

  3. IDE and Java applications such as IntelliJ and Netbeans were broken with blank swing interface. I noticed that the menus were still working when I moved my mouse over them.

    Solution: Set AWT_TOOLKIT to MToolkit, for instance, add this entry to /etc/profile:
    export AWT_TOOLKIT="MToolkit"
    Then, reload the profile (source <profile>) and restart your IDE.

To find out what can Compiz effects do, please take a look at this Youtube video. I noticed and managed to discover some newly added effects:
  1. Shadow effects
  2. Maximize and Minimize effects
  3. Blinking/fading effects caused by error/alert, e.g. backspace on an empty text box in Pidgin; filling in invalid phrase in Firefox search box;
  4. Wobbly window effects while it's dragged
  5. Transparent effects (use ALT + Wheel Scroll on a window)
  6. ALT + Tab with real-time snapshots
  7. M$ + E to choose desktops
  8. M$ + Wheel Scroll to zoom
  9. M$ + Right Click to zoom in once

Read these to discover more:
  1. Compiz documentation
  2. Novel - Xgl on Suse 10.1 (see Xgl Shortcuts section)

- yc, impressed

Friday, October 19, 2007

The Fault is On Malaysians

Read a very long ranting blog entry by Su Ann, and in response to it:

And this is my favourite part. the interviewer made a comment that if action is not taken by the government soon, then this issue would be forgotten by Malaysians. And Nazri Aziz said, “Who’s fault is that? It’s not the government’s - the fault is on Malaysians.”

No one ever likes Nazri, one who is known for having a mouth full of crap. But NOT this time.

It is the fault of Malaysians:

  • It is the fault of the people to vote for the government.
  • It is the fault of so many youngsters out there to not care about this issue and the recent issues.
  • It is the fault of the government to keep doing what they have been doing.
  • It is not just the fault.. it is a real shame that the politicians are claiming all they have been doing are for the country.
  • It is the fault of the people to believe the press and all the lies.
  • It is the fault of the people to uphold the "tidak apa", "malaysia boleh", and all other attitudes and chauvinistic beliefs.

We are f**ked up.

- yc, rant2

Every character counts

I have been fixing up some funny Spring/Acegi<->LDAP issue in the past two days. What I was trying to achieve is some AOP using BeanNameAutoProxyCreator to intercept invocations to methods of a particular interface/class, so that it authenticates against an LDAP repository and validate if a user has one of the specified roles. Something wasn't really working at the DefaultLdapAuthoritiesPopulator -- the authorities/roles list was empty.

Now, it's solved, yes it is.. with shame.

I turned on an even detailed debug logging and that's when I started to realized my.. stupidity ;-)

conn=2 op=1 SRCH base="ou=groups,dc=my,dc=com,dc=customware" scope=2 deref=3

filter="(member=uid=clim,ou=people,dc=my,dc=com,dc=customware)"
conn=2 op=1 SRCH attr=cn
bdb_idl_fetch_key: [01872a84]
bdb_idl_fetch_key: @ou=groups,dc=my,dc=com,dc=customware
<= bdb_equality_candidates: (member) index_param failed (18) => access_allowed: search access to "ou=groups,dc=my,dc=com,dc=customware" "member" requested
<= root access granted => access_allowed: search access to "cn=mule01,ou=groups,dc=my,dc=com,dc=customware" "member" requested
<= root access granted dnMatch 0 "uid=clim,ou=people,dc=my,dc=com,dc=customware" "uid=clim,ou=people,dc=my,dc=com,dc=customware" => access_allowed: read access to "cn=mule01,ou=groups,dc=my,dc=com,dc=customware" "entry" requested
<= root access granted => access_allowed: read access to "cn=mule01,ou=groups,dc=my,dc=com,dc=customware" "cn" requested
<= root access granted => access_allowed: search access to "cn=managers,ou=groups,dc=my,dc=com,dc=customware" "member" requested
<= root access granted dnMatch -1 "uid=clim,cn=people,dc=my,dc=com,dc=customware" "uid=clim,ou=people,dc=my,dc=com,dc=customware" send_ldap_result: err=0 matched="" text="" conn=2 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=

Did you see that? I will do it again:

dnMatch 0
"uid=clim,ou=people,dc=my,dc=com,dc=customware"
"uid=clim,ou=people,dc=my,dc=com,dc=customware"
...
dnMatch -1
"uid=clim,cn=people,dc=my,dc=com,dc=customware"
"uid=clim,ou=people,dc=my,dc=com,dc=customware"

cn=people and ou=people?!

dn: ou=people,dc=my,dc=com,dc=customware
...

dn: cn=managers,ou=groups,dc=my,dc=com,dc=customware
member: uid=clim,cn=people,dc=my,dc=com,dc=customware
...

dn: uid=clim,ou=people,dc=my,dc=com,dc=customware
...

WTF! Worse than failure hey! LDAP did not fail me at the time I was importing from the LDIF with invalid member attribute value. I could have saved a few hours to do something.. more significant than sitting in front of my Eclipse to figure out why wasn't DirContext.search() returning any results. In fact, I have learned a very good lesson.

- yc, rantinggggggggggg!

Thursday, October 18, 2007

Constant Interface or Constant Class?

I have been using classes to hold constants instead of interfaces (which we call the 'Constant Interface'), all these while. My colleague, Kynan, was reading my code today and questioned the reasons behind such practice.

There has always been debates on this subject, e.g.

TheServerSide.com - Use Interface for declaring Constants

I think it's good to share. I have read the following books which justify why should you avoid 'Constant Interface':

Philip Heller and Simon Roberts, "Complete Java 2 Certification Study
Guide":
"In the first place, to say that a class implements an interface
really means that the class exposes the public methods listed in the
interface. Interfaces are for defining types and should be used
exclusively for that purpose. Constant interfaces only contain data,
so they definitely don’t define types.

The second disadvantage is a bit more complicated. Suppose someone you
work with writes some code that uses an instance of Scales. This
person can legally reference that instance with a variable of type
Conversion, even though doing so would be quite inappropriate. Later,
if you wanted to eliminate the Conversion interface, you couldn’t do
so, because your misguided colleague would be relying on the existence
of the interface."

Joshua Bloch, "Effective Java - Programming Language Guide":
"The constant interface pattern is a poor use of interfaces. That a
class uses some constants internally is an implementation detail.
Implementing a constant interface causes this implementation detail to
leak into the class's exported API. It is of no consequence to the
users of a class that the class implements a constant interface. In
fact, it may even confuse them. Worse, it represents a commitment: if
in a future release the class is modified so that it no longer needs
to use the constants, it still must implement the interface to ensure
binary compatibility. If a nonfinal class implements a constant
interface, all of its subclasses will have their namespaces polluted
by the constants in the interface."

To sum it up, which are basically what I told Kynan:

  1. Interface is for defining types, and not solely for holding constants.
  2. Avoid creating coupling. e.g. introducing or removing a method from the interface will either take you time to fix all implementing classes or make things look ugly. Likely or not, I don't care.

Regards,
Yuen-Chi Lian

Tuesday, October 16, 2007

From ESB to REST, Polyglot Programming, JSON

I spent about an hour to do some blog reading. Around two weeks ago I left a comment in Patrick Logan's (an open-source developer) blog on More on the ESB. And just now, while rolling through the feeds consumed by the demon, I found a very good blog by Steve Vinoski (former chief engineer of IONA Technologies) in response to Patrick's blog -- The ESB question. His answer to the problems is REST. Steve subsequently wrote another two blog entries.

Bob Warfield of SmoothSpan summarized the discussion and stretched on multiple language approach as solution to enterprise problems, see ESB vs REST (Another Case for Multi-Language Programming).

They are very good reads which create room for me to start thinking again.

Lately, I am working on the JIRA Transport for Mule and one of the cool things about it is it reads JSON defined at the endpoint, then parses it to invoke the SOAP service of JIRA. I have never been a fan of writing SOAP client using Java and I hate the stubs, it is always Python or Perl.

- yc, reading

Wednesday, October 10, 2007

jdbcPersistenceAdapter myth of ActiveMQ solved

I faced this problem last week and I had some talks with my colleagues but there was no solution :( – jdbcPersistenceAdapter did not click well with my MySQL database.

This was what that happened if I configured ActiveMQ with JDBC persistence, a clean database (with no tables) did not stop the problem from occuring:

17:05:16.359 ERROR [org.apache.activemq.broker.BrokerService:start] Failed to start ActiveMQ JMS Message Broker. Reason: java.io.IOException: Failed to get last broker message id: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Table 'activemq.activemq_acks' doesn't exist
java.io.IOException: Failed to get last broker message id: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Table 'activemq.activemq_acks' doesn't exist
at org.apache.activemq.util.IOExceptionSupport.create(IOExceptionSupport.java:31)
at org.apache.activemq.store.jdbc.JDBCPersistenceAdapter.getLastMessageBrokerSequenceId(JDBCPersistenceAdapter.java:145)
at org.apache.activemq.broker.region.DestinationFactoryImpl.getLastMessageBrokerSequenceId(DestinationFactoryImpl.java:148)
at org.apache.activemq.broker.region.RegionBroker.(RegionBroker.java:104)
at org.apache.activemq.broker.BrokerService.createRegionBroker(BrokerService.java:1270)
at org.apache.activemq.broker.BrokerService.createBroker(BrokerService.java:1209)
at org.apache.activemq.broker.BrokerService.getBroker(BrokerService.java:508)
at org.apache.activemq.broker.BrokerService.start(BrokerService.java:394)
at org.apache.activemq.xbean.XBeanBrokerService.afterPropertiesSet(XBeanBrokerService.java:47)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1201)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1171)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:425)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:156)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:287)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:352)
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.(ResourceXmlApplicationContext.java:88)
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.(ResourceXmlApplicationContext.java:76)
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.(ResourceXmlApplicationContext.java:72)
at org.apache.xbean.spring.context.ResourceXmlApplicationContext.(ResourceXmlApplicationContext.java:68)
at org.apache.activemq.xbean.BrokerFactoryBean.afterPropertiesSet(BrokerFactoryBean.java:84)
at
...
Caused by: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Table 'activemq.activemq_acks' doesn't exist
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3256)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1313)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1448)
at org.enhydra.jdbc.core.CorePreparedStatement.executeQuery(CorePreparedStatement.java:92)
at org.apache.activemq.store.jdbc.adapter.DefaultJDBCAdapter.doGetLastMessageBrokerSequenceId(DefaultJDBCAdapter.java:148)
at org.apache.activemq.store.jdbc.JDBCPersistenceAdapter.getLastMessageBrokerSequenceId(JDBCPersistenceAdapter.java:142)
... 76 more

So I started a thread in the ActiveMQ mailing list. I have also tried doing the same thing in my Ubuntu box but faced no problem. Spent a little bit more time on it, and realized that two out of the three tables were actually created, i.e. activemq_locks and activemq_msgs. And this information managed to give someone a clue on what's going on:

I just hit the same thing as well

Specified key was too long; max key length is 1000 bytes is the error not allowing the creation of ACTIVEMQ_ACKS

You are probably using utf8/some other multibyte encoding as the collation in your database....

Switch it to latin1 or ASCII... The varchar fields that the key is composed of add up to less than 1000 characters but with a multibyte encoding the key length is over 1000 bytes.

That's the case in my mysql setup here anyway.

- Alex_ynr

Bingo!
:-)

mysql> status
--------------
...
Server characterset: utf8
Db characterset: utf8
...

mysql> drop database activemq;
Query OK, 2 rows affected (0.06 sec)

mysql> create database activemq char set latin1;
Query OK, 1 row affected (0.00 sec)

mysql> use activemq;
Database changed
mysql> status
...
Server characterset: utf8
Db characterset: latin1
...

mysql> show tables;
+--------------------+
| Tables_in_activemq |
+--------------------+
| activemq_acks |
| activemq_lock |
| activemq_msgs |
+--------------------+
3 rows in set (0.00 sec)

- yc

Malaysian Java User Group - Request for Expressions of Interest

I wrote this public email, sent it to the MyJUG mailing list and also to some local organizations. I wish to receive some responses, and of course, if you're reading it, please forward to your friends or the Java persons in your organization.

Cheers.

Hello,

I am one of exco committees of the Malaysian Java User Group (MyJUG).
A Java User Group, basically, is a non-profit organization, a group of
people who share common interest in Java and related technology.

Recently, we are trying to re-establish the group and to reaffirm its
determination to be an influential group in driving the local Java
community and technology. We had a meeting in August and our agenda
contains establishing a portal, wiki, organizing monthly events and
technical talks, etc. We will be having a meeting again within the
coming weeks to bring ideas into concrete forms.

The reason you are receiving this email is because we have very strong
faith and are true believers that the IT industry's contribution is
important to the success of this group of the Java community and its
people. I would like to encourage the you and your organization to
participate in our portal, mailing list, technical talks, events,
advertisements, etc.

I kindly request you to forward this email to the point of contact (of
Java technology or sales and marketing department) in your
organization; and reply to this email to share with me your interest
on this subject.

Cheers.

References:

Java User Groups -- http://java.sun.com/community/usergroups/
Malaysian Java User Groups -- http://my-jug.org/ | Mailing list:
http://tech.groups.yahoo.com/group/myjug/

--

Regards,
Yuen-Chi Lian
"I do not seek. I find." - Pablo Picasso

- yc, let's rock

Sunday, October 7, 2007

China Dream.. Broken

Diving badly into the gravel, Lewis Hamilton -- the super rookie of F1, the championship leader, has ended his race prematurely and opened the title contest for Fernando Alonso and Kimi Raikkonen, heading to the last round at Interlagos, Brazil.

Dramatic. "That's motor-racing. Anything can happen before crossing the chequer flag." "That's football. Anything can happen before the stop-pitch." "That's life." No matter what you call it, expectation is simply a belief and it can be changed.

Two more weeks to wrap up the F1 2007, one is fighting to be the first rookie champion, one is fighting to be the youngest champion with three consecutive wins, one is trying to prove that he made the right decision to quit. Interlagos is always Interlagos, a track which Felipe Massa made his home dream, a track which Michael Schumacher wrapped up his career and proved himself supreme.

More news | More pictures

- yc, waiting, pacing.. patiently

Wednesday, October 3, 2007

ALL-BLOGS forum on "Blogs and Digital Democracy"

I attended the ALL-BLOGS forum just a few hours ago and managed to meet some friends, known bloggers and new faces.

I threw a question (with nested question anyway) which perhaps wasn't clearly asked and answered.

I was very much interested in knowing the principle of GVO (especially when we are talking about digital democracy) on online media rules and regulations, should or should not they ever exist. I used the Votergasm as an example of extreme exercise of freedom, may be not appropriate, but it woke some sleepy people up (that's what Nuraina said).. at least.

Many of us have had this discussion before I suppose. Call it contradiction or dilemma, rules are definitely needed, although once implemented, a lot will go against it.

Also bear in mind that, 5 years or 10 years down the road, blogging might not be in its form as we can see today. We have seen how things evolved from Usenet to BBS to IRC to online forums to social networks and to blogs/Web 2.0 and to morrow.. we use something else.

Let's not just focus on blogging towards democracy, let's start thinking about solid establishment of democracy and civilization on the cyberspace -- for the real world.

I never deny the fact that blogging (as of today) is something that works and has brought together all ages and nations to participate in discussion, unlike the early age of Internet / World Wide Web.

- yc

Sunday, September 30, 2007

Forum: From Nurin to Chief Justice

Attended a political forum on yesterday afternoon, my first time ever. Howsy has a detailed write up available here.

I made a short comment from the floor,

"I'm an IT guy, not a political guy. Am here to express a worry and an encouragement. We are all here today because of how information flows into our hands -- I am here because I received a Facebook invitation sent by Anwar office, I read about the scandal from Jeff Ooi's and Anwar's blog, I watched the video from YouTube, I also found that the BAR council has a blog to share their thoughts with the public.


Like some of the people have mentioned just now -- free media (my worry). Our government has lately been trying to control how information is shared, esp. online. However, that should not stop us from expressing ourselves. We talked about the rot of our judiciary, media and system, and we are in need of revamping them. But one of the very first things is that, we, ourselves have to start doing things, like expressing yourself, sharing your thoughts with the people.

Start blogging if you could..
(encouragement)"

If you have not been following the news, our country (Malaysia) has been in a sad state lately (in fact, all this while). Li Tsin's blog (Polytikus) sums them all up:
  • Murder.
  • Judiciary scandal.
  • Cops screwing the rakyat.
  • The forgotten East Malaysians.
  • Consumer goods price hike.
  • Potential petrol price hike.
  • Haze is back.
  • Public universities harassing students.
  • Wasting police resources over a burnt flag.
  • Maid abuse.
  • Missing children.
  • Mistreatment of foreign workers.
Or you can refer back to my past entries: Black and White March to Save Judiciary, RE: Reason Behind The Recent Condemnation Against Bloggers.

I am attending a forum on Digital Democracy on this coming Wednesday, by ALL-BLOGS. Hopefully, there are more things that I can learn and do, for the people.

- yc, whines

High School was Fun

I spent 7 years in Chong-hwa KL Independent High School at the age of 13 to 19. Found and joined its Facebook group just now. There is this discussion going on in the group: "Best & worst memories?", and I wrote these:

Causing electrical blow-off at the KH building, at form one that time. The school blacked out for an hour or so. Priceless.

Falling in love for the first time in high school at form 2. Being stupid but that's mesmerizing.

Throwing a chalk right on the arse of science teacher at form 3. Ridiculous.

Damned to retake form 3 but managed to secure form 4 after negotiating with the headmaster. Owned.

Can't remember how my time was spent and what I have really done for my SPM and UEC. Typical.

Went upper 6. It was World Cup 2002. Had a Davala[1] hairstyle for just a day. Busted.

[1]: http://images.google.com.my/images?q=davala
Everyone has been bad, I'm sure. ;-)

- yc, loves high school

Wednesday, September 26, 2007

Black and White March to Save Judiciary

It's the second time in 60 years the Malaysian Bar Council did something like that – "Walk for Justice". A recently revealed video of a senior lawyer on the phone with a Tun has led to the public disclosure of a judiciary scandal involving our Chief Justice, all thanks to Anwar Ibrahim (this link has the video).

Some of my colleagues might have noticed (and some were told by me) that I was with a black and white attire today because of this. I wasn't managed to pull off for a day-off, there wasn't enough time for it when I was informed.

To read more blog responses, click this link.

Our country has been in a pretty bad state these days with all the issues and scandals. The country needs a change. A month ago, the government and the rakyat-rakyat were celebrating the 50th anniversary of the independence day – slogan: "Jalur Gemilang" (glorious range of values).

50 years, so.. What have we achieved?

Updated: Jeff has taken/uploaded heaps of photos of the event.

- yc, sad

Monday, September 24, 2007

Definition of Web 2.0

I have this idea about Web 2.0 in my mind all these while, that I view it from three different perspectives:
  • Users'
  • Developers'
  • Technology-wise
Yes, perspectives. It's not just about the keywords that you can see from the Web 2.0 cloud at Wikipedia. It's about how the pieces giving an impact to each of the aspects above.

I have tried to put it into words today, and I did, in one of my colleagues' blog comment I wrote this:

"Web 2.0 is the revolution of user experience, which a developer should always put in mind and into practice by using today's technology."

- yc

Tuesday, September 11, 2007

Best of Open Source in..

Bunch of open source products being selected by InfoWorld for the 2007 InfoWorld Bossie Awards.

  • Mule is the top choice of ESB
  • Hyperic is one of the selected monitoring tool
  • Compiere is one of the CRM/ERP (well, I wasn't impressed by Compiere at all, 2 months ago I attended a talk about it)
  • Apache OFBiz as another
  • Asterisk beats everyone in VOIP solution
  • Azureus Vuze as best streaming media
  • Wireshark as best networking analysis tool
  • OpenVPN as best SSL/VPN

There're more products, go read them up by youself. ;-)

- yc, 911?

Sunday, September 9, 2007

A Micro-Softening Arvo - "Sembang"

Before I ran off for the "Sembang Tech.Ed" -- A sneak peak of the Microsoft Tech.Ed SEA 2007 organized by Microsoft in collaboration with Lensa Malaysia & Nuffnang Malaysia, I was having a chat with David:
(01:09:02 PM) yc - and skies..: I'm attending something M$
(01:09:09 PM) dchui: You're the dark side
(01:09:11 PM) dchui: Omg
Whether if I have turned to the dark side, that's not really important. If I'm to put a summary of this afternoon in one sentence, it would be:
"Microsoft builds software for the human beings."
The three-hour (which eventually went four) session demonstrated how nicely applications are packaged, how Web 2.0 is being implemented, and most importantly (at least, that I care of), the concern of usability/developablity for end-users, designers and application developers. An example regarding developability is, Silverlight applications can be developed using the Expression Studio and any development kits (which you should not expect designers to use) such as Visual Studio. It wasn't a concern of Macromedia (now Adobe) that the application developers struggled with Flash program until around these years that they come out with Flex. Of course, there're a lot of reasons behind such scenario, e.g. financial capability.

A brief run-down on what that had presented:
  • Silverlight - Multimedia runtime for browser-based rich internet application. Microsoft seems very confident to compete with the dominating Flash. Also worth mentioning is the cool but very slow Sun's JavaFX.

  • Popfly - Rich internet content (called the "mashup") creator. It has impressive visualization and can be easily integrated with your services such as Flickr, Facebook, etc. It comes with some cool geotagging feature too.

    I like this one.

  • Home Server - A solution for homes to centralize computers and files. Great simplicity so that your parents know how to use it.

  • Robotics Studio - Robot control and simulation tool so that your kids know how to make the legos move remotely. I'm definitely not a fan of robotics though, maybe you are, so digg or bury this -- Bill Gates' "A Robot in a Home".

I am one of the contributors to why the event ran out of time as I have been asking questions. Anyway, it was, of course, a great occasion to talk to people like Oliver, Chewy, Steven from Fortune Fountain, and some short chats with bloggers like June, Timothy, Jason, ES, Jeff, Nat, ..

P/S: Maybe you did not notice, there're some alphabets hanging on top of the ceiling of the stage, reads "Sinfully Yours". I'm sure Microsoft haters love this.

- yc, micro-softened

Friday, August 31, 2007

Who's eating all my SMSes?

This blog is for whoever that might be sending me text messages. I had a problem with my mobile (an O2 XDA II mini) before I flew off to Sydney, a sudden hang and hard reset. Ever since then, I do not receive SMSes and I actually thought it was some roaming problem.

I have tried switching SIM cards and phones and it's confirmed that something has gone haywire here. The hardware The O/S (and solved by not restoring my O/S to a previously backed up state).

Jeez. You will never like this happen, will you? Let me know if you have an idea about this problem.

P/S: I'm back to KL.

Cheers,
yc

Saturday, August 25, 2007

RE: eGENTING Programming Competition Registration

So I signed up for the eGenting Programming Competition of this year, an open-book hand written programming competition.. Now, the nature of the competition might be a big challenge to IDE guys like me. ;-)

A letter I received after the submission of my registration form:

Dear Yuen-Chi Lian,

Thank you for registering for the eGENTING Programming Competition 2007.

If you are shortlisted, we will notify you in a separate email after the registration closing date.

From,
Research & Development (Systems).
eGENTING Sdn. Bhd.
19th Floor, Wisma Genting,
Jalan Sultan Ismail,
50250 Kuala Lumpur.


Interesting, you'll have to pray for being shortlisted. Taking a look at the past questions, and you could see how Java could be incredibly written in C/C++ style. That's a crazy mix.

Good luck Yuen-Chi.

yc, praying

Friday, August 17, 2007

Introducing Jyte to fellow Malaysians - BN is going to win the coming election!

Jyte is a community-based webpage which (fundamentally) allows you to make claims and to receive opinions from the community. There are some reasons why I'm interested with it (Oh, by the way, Jyte stands for Just You Tell 'Em):

  • It is an OpenID-enabled website. OpenID, in short, is an online identity that can be used anywhere. I had a blog entry about it a few months back.
  • It is Web 2.0. If you haven't yet heard of this big name/thing (it's merely a concept anyway), see this picture.
  • It's neat, needless to say. It is not a new idea but it is easy and it beats hosting polls in an online forum.
Something quite (yes, just quite) similar to Jyte will be Digg, you might have heard about it, which comes with a set of rich features in comparison, basically, a way of bookmarking and to receive public opinions.

For the sake of promoting the use of OpenID and exercising Web 2.0, I have made such claim (that I disagreed):




Malaysia's upcoming election is recently a very hot discussion everywhere, contributed by the recent actions/reactions from our government against bloggers and the Internet users, I believe.

Let us know what you think and see you at Jyte. If you'd like to do some digging, click here.

yc, jyte-ing!

RE: Reason Behind The Recent Condemnation Against Bloggers

Note: I'm a technical blog writer and if you are reading this from a Java/IT blog-aggregator, it's probably that I labeled it incorrectly for some reasons.

This blog entry is written for the sake of being patriotic (patriotic doesn't mean that you are siding any party but you love the country for your own god's-sake reasons) and not being a quiet blogger, in response to:
If you read about one of my entries earlier ago, I attended a blogger's meeting and one of our forum discussions was about being a responsible blogger and how we should exercise the freedom of speech. That simply says that bloggers in Malaysia do meet up to talk about serious stuffs and care much about the country's future, but sadly, bloggers are wrongly labeled by the Malaysian media and government as irresponsible and culprits (citation needed).

In the discussion, we mentioned about the impact of blogs to the upcoming election in my country. (And for my dad who did not really understand what bloggers truly were but did read about some influential one being a DAP guy from the paper, I spent some time to explain to him about cyber communication, and I urge you to do the same to your parents.) And at that time, I did not really realize about how our government would react like today's, and it would have not been fun if I did realize, perhaps, would just feel a little bit more disgusted.

A few years back when it was our last election, Internet and blogs couldn't play a role in driving and educating the people, mainly because at that time Web 2.0 has not exploded yet and personal homepage could hardly be widespreaded unless you hosted interesting contents, and simply at that time, the voters preferred reading cooked-up news from the local media (citation needed), which I believe could be the matter of age. Right now, as people move with Internet daily or in another words: Internet moves and feeds people to be more intelligent, the decision of casting a vote can be more rationally made than emotionally, and surely for that, our government freaked out (did they? citation needed) and all the hypes of arresting and suppressing bloggers came out (citation needed).

To brief you, in case you do not know or read the links above, blogs make some parties unhappy and they thought of eliminating or controlling them as they could for other protocols, say, newspaper. Being a blogger and all-time geek in responsible of helping the growth of my country in terms of Information and Technology, I have a few words to say: the tool is neutral and innocent but opinions are always subjective. I would love it, if, besides of reading all other political blogs, my government and the ruling party could set up some good blogs to write about what they have done good for our country daily.

If any piece of the content above is offensive and considered breaking the laws of Malaysia, please let me know, as the content is written when I am physically in Sydney and the data is stored in Google's server which I believe do not have an immediate mirror service located at Malaysia at the point I commit this cyber crime (at the point I press the submit button).

yc, BLOGging

Saturday, August 11, 2007

MyJUG Committee Meeting, 4th Aug 2007

Malaysian Java User Group have just had a committee meeting last Saturday (4th Aug) at Secret Recipe of Mid Valley Megamall. The following is a list of the attendees:

  • Kar Seng, Loke (founder)
  • A. Faisal Shaazi
  • Desmond Lee
  • Chee Seng, Chua
  • Yuen-Chi Lian
  • Kristanto Oetomo
The meeting focused on re-establishing the group, which currently, has more than 600 members in its mailing. Agenda as followed:

  • MyJUG's background
  • Committee members and roles
  • Web-page, contents and hosting
  • Sponsorship
  • Active members and future events
Some had been addressed in this thread #6870 a month ago.

Here is a brief summary on the ongoing tasks after the meeting:

  • Working on the web hosting plan and its sponsorship (Faizal)
  • Working on a long-term strategy that increases the value of MyJUG (Faizal)
  • Promoting MyJUG to people through different communities and channels (Yuen-Chi)
  • Collecting more ideas as part of the features of the group and its website (Yuen-Chi)
  • Planning on the future events, esp. organizing tech talks (Kar Seng and Chee Seng)
Most of the plans are right now still preliminary but nevertheless a good start. Our next meeting will be held in about a month time, to follow-up some of the issues of previous meeting and to put things into concrete form.

Anyway, we love ideas, we love inputs. If you wish to be part of MyJUG, to help out, or to be one of the sponsors, feel free to talk to me.

- yc, jugging

Sunday, July 15, 2007

Procedural or Object-Oriented?

The title might be misleading to some people, certainly, when you are writing Java code you are breaking things into objects. So, please let me define what they are about:
  • Procedural -- Code written in procedural and sequential style. Uses primitive types and common data structures. Multiple steps and conditions are defined in a single or few massive methods to reach program to a happy state.
  • Object-Oriented -- Code written in object-oriented style. Uses beans, DAOs, manager objects, etc. Code is constantly refactored, such as decomposing and using "extract method".
Recently, I have been working on some pieces of code and I came to a point to discuss with a friend this afternoon. He talked about the advantages of procedural style over overly-designed and object-oriented style, esp. when you are writing integration code and business process.

For example, in a procedural manner,


public MyActionClass{

public void doAction(){

Map vars = new HashMap();

if(condition1){
SomeClass.doSomething(vars);
SomeClass.doTransaction(vars.get("var1"));
}
else{
// .. Something similar
}

SomeClass.finalizeSomething(vars.get("var2"));
}
}

In an object-oriented manner,

public MyActionClass{

public void doAction(){

MyActionContext context = MyActionThreadLocal.getContext(); // Or a bean, or something similar

if(condition1){
doTransactionForCondition1(context);
}
else{
// .. Something similar
}

SomeClass.finalizeSomething(context.getVar2());
}

protected void doTransactionForCondition1(MyActionContext context){
SomeClass.doSomething(context);
SomeClass.doTransaction(context.getVar1());
}
}

Whatever above is just a very small piece of code, imagine in a class with complex business logic, how much they both can grow.

Maintainability is something subjective which I have to say. In a business world, code is subject to change as new requirements come in every day (expectedly). Procedural style coding might seem lengthy but it does not hide too much (object-oriented is a black-box). Object-oriented style coding is not unnecessary but not overly-designed and should be discouraged when you are working on something that is established or recognized by a group which you might handover stuffs to.

Your say?

- yc, fowler-ed then rob-ed

Sunday, July 8, 2007

Bloggers Buff 2007

Oh.. hi? So, I went to the Bloggers Buff 2007 held at Dewan Dato' Haji Sidek in Sunday arvo and I turned up pretty late for the forum/conference. I managed to join the session about "Responsible blogging and self censorship" by Dato Ahmad Talib, Ahirudin, and Li Tsin from MalaysiaKini.

I'm glad to be able to share a little bit about internal blogging (in a corporate), wiki and some Web 2.0 features.

Anyway, I'm sorry that I am bad in remembering names but I have to thank Rames as it was because of his blog that I discovered this event and some people who I had a chance to chit-chat with. I'd like to highlight the Think Rich Enterprise as well, although I am not a fan of blogging for $, it is interesting to see such company which helps driving the local people into the trend.

So, you might be interested with what I'm actually doing. I am employed by a Sydney based company CustomWare Asia Pacific as a developer and support engineer. Part of my job is to provide support to various Atlassian products. I love technology and technology makes our today.

There's one thing that I care much about is the growth of Web 2.0 in Malaysia. It does seem like a lot of its features haven't yet become widely spread and integrated into our daily practice.

It's time to back to Silverstone anyway ;-) (Massa is doing a good overtaking job). I'd love to see each other again soon.

- yc, silverstoned

Monday, July 2, 2007

Son oh son.. JSON

Learning a new techy stuff every weekend of mine seems to have turned into a real habit. JSON (or you can call it Jason ;-)), not something entirely new but it has been really hot these days. It stands for "JavaScript Object Notation" and it exists today is to make the AJAX programmers life easier.

I will briefly show you how you can get a hang of it using a simple JSP file and a small piece of JavaScript (YUI). If you do not have an idea about AJAX yet, you'd probably want to read about it first before going beyond this paragraph.

An AJAX response in XML format requires writing client code to parse it into DOM model, for instance:


<bean>
<name>foo</name>
<description>foobar</description>
<id>10000</id>
</bean>


Then some annoying JSDom bits to extract the data, which I'm not going to write. As I could recall, my last time of writing AJAX and DOM stuffs was a year ago for a Java webapp which requires validating the form fields by sending synchronous request to webMethods endpoints.

This might just be another article about JSON which you have read before from other sites, yes, it is. Anyway, a response can also be sent in JSON (which is basically string then be evaluated using JavaScript eval() method), e.g.

{"name": "foo",
"description": "foobar",
"id": "10000"}



Data can then be extracted easily unlike DOM, e.g.

var jsonObj = eval("(" + responseText + ")");
var name = jsonObj.name;


Before I end this blog so that you can find out more by yourself ;-), this is the JSP used to generate the response:

<%@ page
language="java" contentType="text/json; charset=utf-8"
import="org.json.simple.JSONObject"
%>
<% response.setContentType("text/json; charset=utf-8"); %>
<%
JSONObject jsonObj = new JSONObject();
jsonObj.put("name", request.getParameter("name"));
jsonObj.put("description", request.getParameter("description"));
jsonObj.put("id", new Long(request.getParameter("id")));
out.print(jsonObj);
out.flush();
%>
And this is the HTML used to send the request and receive the response:

<html>
<head>
<title>Test AJAX</title>
<script type="text/javascript" src="js/yui-2.2.2/yahoo/yahoo-min.js"></script>
<script type="text/javascript" src="js/yui-2.2.2/connection/connection-min.js"></script>
<script type="text/javascript">
function getAjaxRequest(url, callback){
return YAHOO.util.Connect.asyncRequest('POST', url, callback, "name=foo&description=foobar&amp;amp;id=10000");
}
</script>
</head>
<body>
<script type="text/javascript">
var callback = {

success: function(o){ alert("Successful: \n" + o.responseText + "\n" + o.getAllResponseHeaders)

var jsonObj = eval("(" + o.responseText + ")");

// Some reflection here
var jsonDump = "";
for(key in jsonObj){
jsonDump += key + ": " + jsonObj[key] + "\n";
}
alert(jsonDump);

},
failure: function(o){ alert("Failed: \n" + o) },
argument: []

}

getAjaxRequest("testJsonResponse.jsp", callback);
</script>
</body>
</html>

One final and common note though, if you ever come across designing a webapp with AJAX functionality, do keep the response format consistent, i.e. use application/xml OR text/json NOT both, so that you will not confuse the developers at another end of which they should expect.

- yc, raining

Thursday, June 28, 2007

On Optimization and Tuning

I came across reading the basic principles of optimization and performance tuning from two books, and I actually thought of sharing it here:

Chapter 1 of Java Performance Tuning:

Don't Tune What You Don't Need to Tune

The most efficient tuning you can do is not to alter what works well. As they say, "If it ain't broke, don't fix it." This may seem obvious, but the temptation to tweak something just because you have thought of an improvement has a tendency to override this obvious statement.

Item 37 of Effective Java Programming:

More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason—including blind stupidity.

– William A. Wulf

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

– Donald E. Knuth

We follow two rules in the matter of optimization:

Rule 1. Don't do it.
Rule 2 (for experts only). Don't do it yet—that is, not until you have a perfectly clear and unoptimized solution.

– M. A. Jackson

As mentioned in the book above, performance issues should be thought of while the application is being designed. Therefore,

  • A good design is very important. Spend more time on the design or spend even more time to get things really working happily one day
  • Don't do optimization if:
    • You have not gotten something working yet
    • The measurable gain is insignificant

- yc, reading

Sunday, June 24, 2007

Troubleshooting JVM, Part I

Part of my job is to provide support for the famous issue tracker JIRA. Sometimes, we will have to look into client's stack traces and thread dumps to troubleshoot some memory or locking issues which usually caused by third-party plug-ins, Lucene, etc.

One of the excellent articles I came across is "Of Thread dumps and stack traces" written by Rajiv Shivane. There are also some people who have given me some good pointers, like, Jed (one of my co-workers, the memory guy) who pointed me to "JDK 1.5 - Trouble-shooting and Diagnostic Guide" and Rob who lent me the book "Inside the Java 2 Virtual Machine". Some other good reads that you shouldn't miss are:
Anyway, I spent some time in the weekend to play around with java, jmap and jhat.

Note: jhat 1.1 doesn't recognize 64-bit dump, simply download JDK 1.6 and use the jhat 2.0 which shipped together with it.

I will go through an java.lang.OutOfMemoryError: Java heap space test I have done and give as detailed information as I can. I have demonstrated this to some people earlier on at work using one of the classic examples: String vs. StringBuffer.


public class TestStringBuffer{

public static void main(String[] args)
throws Exception{

StringBuffer sb = new StringBuffer();
String s = "foobar";
String which = args[1];

for(int i = 0; i < Integer.parseInt(args[0]); i++){
if(which.equals("sb"))
sb.append(s);
else
s += s;

System.out.println(System.currentTimeMillis() + ": " + i);
Thread.currentThread().sleep(500);
}
}
}

Using the StringBuffer way, the program remains alright even after 10K of iterations. However, it dies immediately with String concatenation around 23th iteration. Before we look deeper into this, here are two interesting JVM startup parameters that you would like to know:
  • -XX:+HeapDumpOnOutOfMemoryError, requests HotSpot to generate a binary dump when it runs out of memory.
  • -Xmx1024m, allocates 1GB of heap space
The jmap utility can be used to produce snapshot of the currently running JVM process. The jhat utility does something similar however in a post-mortem manner.

For instance, running jmap on the StringBuffer case:

yclian@kate:~/devels/test/java$ $JAVA_HOME/bin/jmap -histo 29237
Attaching to process ID 29237, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.5.0_09-b03
Iterating over heap. This may take a while...
Unknown oop at 0x00002b7df8296da0
Oop's klass is null
Object Histogram:

Size Count Class description
-------------------------------------------------------
500112 4121 * ConstMethodKlass
433192 4121 * MethodKlass
303824 283 * ConstantPoolKlass
269816 6117 * SymbolKlass
214688 265 * ConstantPoolCacheKlass
183776 283 * InstanceKlassKlass
108768 1044 char[]
83368 455 byte[]
61248 348 java.lang.Class
52096 462 java.lang.Object[]
31400 785 java.lang.String
29168 413 short[]
19584 295 int[]
18720 36 * ObjArrayKlassKlass
15048 213 java.lang.Object[]
7616 136 java.nio.HeapCharBuffer
4592 82 java.nio.HeapByteBuffer
4160 8 * TypeArrayKlassKlass
2784 58 java.util.Hashtable$Entry
2248 31 java.lang.String[]
2128 14 java.util.HashMap$Entry[]
2080 65 java.lang.StringBuilder
2064 10 java.util.Hashtable$Entry[]
2000 10 * KlassKlass
1792 14 java.lang.reflect.Field
1320 11 java.lang.reflect.Constructor
1056 22 java.util.Locale
1040 2 * ArrayKlassKlass
936 9 java.net.URL
864 6 java.lang.Thread
768 12 java.util.HashMap
736 23 java.io.File
696 21 java.lang.Class[]
672 12 java.io.ObjectStreamField
672 21 java.lang.StringBuffer
...
Heap traversal took 2.054 seconds.

And for the String case:
yclian@kate:~/devels/test/java$ $JAVA_HOME/bin/jmap -histo 29336
Attaching to process ID 29336, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.5.0_09-b03
Iterating over heap. This may take a while...
Object Histogram:

Size Count Class description
-------------------------------------------------------
906039672 578 char[]
501216 4132 * ConstMethodKlass
434336 4132 * MethodKlass
304728 284 * ConstantPoolKlass
270328 6127 * SymbolKlass
214688 265 * ConstantPoolCacheKlass
184336 284 * InstanceKlassKlass
71072 351 byte[]
61424 349 java.lang.Class
51216 446 java.lang.Object[]
28960 411 short[]
22520 563 java.lang.String
19088 291 int[]
18720 36 * ObjArrayKlassKlass
13784 202 java.lang.Object[]
4160 8 * TypeArrayKlassKlass
2736 57 java.util.Hashtable$Entry
2128 14 java.util.HashMap$Entry[]
2000 10 * KlassKlass
1936 27 java.lang.String[]
1536 12 java.lang.reflect.Field
1344 7 java.util.Hashtable$Entry[]
1320 11 java.lang.reflect.Constructor
1056 22 java.util.Locale
1040 2 * ArrayKlassKlass
864 6 java.lang.Thread
768 12 java.util.HashMap
728 7 java.net.URL
672 12 java.io.ObjectStreamField
640 10 java.util.LinkedHashMap$Entry
448 8 java.lang.ref.SoftReference
448 7 java.lang.ref.Finalizer
432 9 java.util.HashMap$Entry
384 6 java.util.Hashtable
360 9 java.util.Vector
352 10 java.lang.Class[]
288 3 java.util.jar.JarFile
272 17 java.lang.Object
264 7 java.io.ObjectStreamField[]
256 8 java.io.ExpiringCache$Entry
240 3 sun.nio.cs.UTF_8$Encoder
240 3 java.nio.DirectByteBuffer
216 3 sun.misc.Cleaner
208 2 sun.nio.cs.StreamEncoder$CharsetSE
200 5 java.util.ArrayList
192 3 sun.misc.URLClassPath$JarLoader
176 2 java.io.ExpiringCache$1
160 4 sun.reflect.NativeConstructorAccessorImpl
152 4 java.lang.reflect.Constructor[]
152 1 java.lang.ThreadLocal$ThreadLocalMap$Entry[]
152 1 java.lang.reflect.Method
144 3 java.lang.OutOfMemoryError
...
Heap traversal took 1.323 seconds.

char[], 108768 vs. 906039672. Clear example why String concatenation should be discouraged ;-). The histogram is very useful in identifying memory leakage as it shows you the size and number of instances created for a specific object type. jhat also allows you to generate some other information such as heap summary and permgen statistics, run it with the -h parameter for more information.

Let's examine the binary heap dump produced by the OutOfMemoryError using jhat.

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid29613.hprof ...
Heap dump file created [403190555 bytes in 31.321 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

jhat is one of the best tools comes together with JVM. It starts a HTTP server and provides you a simple interface which enables you to inspect the heap dump with your favorite browser.


Since we were talking about histogram, we will look into histogram again using the jhat interface.

Class Instance Count Total Size
class [C 564 402716036
class [B 350 67135
class java.lang.Class 336 48384
class [S 411 25126
class [I 291 16760
class [Ljava.lang.Object; 202 12168
class java.lang.String 552 11040
class [Ljava.util.HashMap$Entry; 14 2016
class [Ljava.lang.String; 27 1720
class java.util.Hashtable$Entry 57 1596
class [Ljava.util.Hashtable$Entry; 7 1288
class java.lang.reflect.Constructor 8 776
class java.lang.Thread 6 744
class java.util.Locale 22 704
class java.net.URL 7 616
class java.util.HashMap 12 576
class java.io.ObjectStreamField 12 444
class java.util.LinkedHashMap$Entry 10 440
class java.lang.ref.Finalizer 7 336
class java.lang.ref.SoftReference 8 320
class java.util.Hashtable 6 288
class java.util.HashMap$Entry 9 252
class java.util.jar.JarFile 3 222
class [Ljava.io.ObjectStreamField; 7 208
class java.util.Vector 9 180
class java.nio.DirectByteBuffer 3 168
class sun.misc.Cleaner 3 168
class [Ljava.lang.Class; 7 152

So, it actually produces something similar with what we have seen earlier. Except the slightly different use of notation, e.g. class [C, class [B, etc. Just if you are unsure:
  • class [C is char[]
  • class [B is byte[]
  • class [Z is boolean[]
  • class [S is short[]
  • class [I is int[]
  • class [J is long[]
  • class [D is double[]
  • class [Lpackage.ClassName is package.ClassName[]
  • class [[Lpackage.ClassName is package.ClassName[][]
And therefore, don't be panicked when you see ([[ID[Ljava/lang/String)Z in the stack trace next time. It is simply just boolean foo(int[][], double, String[]).

Clicking into one of the hyper-links (of course, it works just on my machine), for instance, class [C will bring me to a page as captured in the screenshot below:


The page gives you more details of the class, such as: loader, subclasses, static/instance data members, instances, references, etc.

I will end this blog entry at this point and I would expect you to spend some time to do some research on it too :-). When I start writing again for Part II, I will be sharing some thread dump tips that I have collected.

- yc, dumped