Monday, September 22, 2008

NoClassDefFound Exceptions tied to PermGen Space

Today I spent a good deal of time trying to figure out why I was getting a bunch of NoClassDefFoundErrors. The changes I made were not significant, but I did make one configuration change to JBoss. It seems the default is to compile the JSP pages with Java 1.4, so I changed it to 1.5, as a new JSP page used some Java 1.5 generics.

When I tried to bring the application back up, I got the following different errors each time I restarted JBoss.

javax.servlet.ServletException: java.lang.NoClassDefFoundError: org/eclipse/jdt/internal/compiler/problem/DefaultProblem

java.lang.NoClassDefFoundError: org/eclipse/jdt/internal/compiler/ast/Argument

NoClassDefFoundError: org/eclipse/jdt/internal/compiler/ast/SingleTypeReference

Finally, I got a PermGen space error.

A friend suggested increasing my PermGen memory in JBoss, which I did by adding the following line to the run.bat file in the JBoss bin directory:
set JAVA_OPTS=%JAVA_OPTS% -XX:PermSize=512m -XX:MaxPermSize=512m

This fixed the problem. So when having weird org/eclipse NoClassDefFoundErrors being thrown, try increasing your PermSize.

Thursday, September 4, 2008

Custom Events in ExtJS

I was kind of new to the idea of event driven applications, but after reading a little about it fell in love with it. I immediately had some applications in my work where it would solve particular problems I was having. Having never implemented this before, I didn't know where to start. Searching the ExtJS forum I uncovered some good information, but not enough to just jump right into it.

I thought I would blog about it while it was still fresh in my mind.

First you need to extend the Observable class for the class that you want to add a new custom event to. Then in a method called when the class is constructed, you need to add the new custom event. I needed to throw a custom event whenever the tab changed. As you can see from the code below, that a 'tabchange' event triggered a call to onTabChange function. This function then fires the 'myCustomEvent' event. That is all it takes to create a custom event. Of course, nothing will happen if there are not any listeners registered for that event.

Example.Events = function(config) {
this.initialize(config);
};
Ext.extend(Example.Events, Ext.util.Observable, {
initialize: function(config) {
this.addEvents('myCustomEvent');
this.panel = new Ext.TabPanel({
.....
};
this.panel.on('tabchange', this.onTabChange.createDelegate(this));

}
onTabChange : function(tabPanel, tab) {
var index = -1;
if (tab.getIndex) {
index = tab.getIndex();
}
this.fireEvent('myCustomEvent', index);
},
}

In my case, I had widgets that existed on tabs and they need to know when their tab was activated. So inside those widgets they needed to obtain a reference to the Example.Events object for our application, and then register as a listener and tell it which function to call back on. I did this in the widget constructor, as shown below.

in constructor:

var event= Example.Parent.getEvent();
event.on('myCustomEvent', this.tabSelected.createDelegate(this));
this.myTabIndex = event.getMyIndex();

The call back function:
tabSelected : function(index) {
if (index == myTabIndex) {
// Do something if your tab is activated
}
},


That's it. There is nothing more to it. And it works like a charm.

JavaScript handling of time zones

On the project I am currently working on, we had a problem to solve regarding time zones with our application. From the web interface the user was entering time for some of the fields. The time was being sent to the server and stored in a database. The problem we ran into was the client time zone was different than the server timezone. The database on the server was converting all times that were saved to the server time zone. When the data was retrieved, it was displaying the server time values and presenting it to the user as if it were client local time. Obviously we were not taking time zones into account.

Like most problems, there is usually more than one way to solve it. The way we solved it, was to make sure that all of the times that were being passed back and forth through the REST web service calls were in GMT (Zulu) time. The database can convert to local time, but before it is sent to the client, it is converted back to GMT. Likewise, in the browser, the user can enter time in local time, but before it is sent to the server it is converted to GMT time.

The rub came in finding the right java script date functions to allow for conversion to and from GMT. The GMT string representations that were being passed back and forth, needed converted to the clients local time. This was easily accomplished by using the java script Date constructor.

var localTimeZoneDate = new Date(gmtTimeZoneDateStr);

The date components the UI implemented, needed to be initialized with milliseconds from epoch time. To get that information we simply called Date.parse(localTimeZoneDate);

On the server it was equally easy to convert the value retrieved from the database to GMT.
String dateFormatStr = "EEE, dd MMM yyyy HH:mm:ss z";
SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatStr );
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date = dateFormat.parse(timeStr);

In reviewing what we did, there may have been an easier solution. Both the Java Date object and the JavaScript Date object, are able to return milliseconds from epoch. It would have been much simpler to just send that value back and forth, and not worry about the string format.