As our applications have grown, we have created one off interfaces to external systems. Each has been a carefully crafted hack. We’ve known all along that this is not sustainable in the long term; but like all shops we didn’t have the business case to spend time creating something more elegant. That changed today, the collective weight of all the interfaces finally caught up with us. So we are going to pay off our technical debt and implement an ESB.
We start looking by looking at a variety of them. Most cater to some form of web services, so they are out (most of our interfaces are not web services per se). I ran across ServiceMix from Apache and it looked promising. It is very easy to download and follow the examples and tutorial to get up and running. I really like the hotdeploy functionality. There is a lot of maven support to create projects and different configuration files for what they call a service unit.
However, once I got beyond the tutorial example, I hit a brick wall. Or more importantly ServiceMix put a smack down on me that I haven’t gotten up from yet. For my first test I wanted to create a service that took an http post file, did a transformation on it and saved the result to the filesystem. Easy enough. Turns out this is really tough to figure out. I’m sure if I was more familiar with ServiceMix this could be created in a few minutes. But after a day and a half of reading source code and googling I couldn’t figure it out. The docs on the website leave a lot to be desired – at least for new users.
So I turned my attention to other options. Next up was Mule ESB. I’m not done; however I can tell this is what we will implement. The docs are good. I was able to get the sample up and running (in Eclipse) in about 10 minutes. After taking my time and reading a lot and working through the tutorials/examples, I was able to create my first service that executed my first use case in about 4 hours. I could have done it quicker; but I wanted to take my time and understand more than just the simple items.
Mule also provides the Mule IDE which helps create new services and the icing on the cake is we can run Mule ESB services in Eclipse — which means debugging just became a whole lot easier.
Next up will be finishing (error handling, etc) my first service and then configuring Mule to run as a standalone application (not via Eclipse).
For a while, I have been looking (googling) for a way to serve up precompressed files. I have the server configured to compress files on the fly; but I knew there was a way to precompress files. Since I’m not an apache url rewriting expert, this one eluded me.
However, I just ran across a talk on MySql performance and scalability (take a read it has some good real world knowledge). The gem for me was at the end of the presentation on the last slide.
AddEncoding gzip .gzip
# If the user accepts gzip data
RewriteCond %{HTTP:Accept-Encoding} gzip
# … and we have a .gzip version of the file
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME}.gzip -f
# then serve that instead of the original file
RewriteRule ^(.*)$ $1.gzip [L]
I have googled for that for far too long. It’s simple now that I see it, I just wasn’t able to put it all together for some reason. Guess I was expecting something more complicated. Anyway, I’m jotting it down here so I don’t forget (or the link goes away for some reason). I want to implement this real soon.
For our internally developed application framework for GWT apps, we want to use RunAsync heavily. We have pushed as much common code to the framework as possible (that’s what frameworks are there for). So developing new screens is really a breeze. Anyway, we wanted to push the RunAsync into the framework so that developers don’t have to think or even now about it.
However, this doesn’t seem possible with the current implementation. Basically, the split point is where the physicaly code split occurs. Which is logical. We were hoping that a class hierarchy would be taken into account. For example:
public abstract class AbstractClass {
public abstract void doActualWork(Callback cb);
public void doAsyncCall(final Callback cb){
GWT.runAsync(new RunAsyncCallback(){
public void onFailure(Throwable err){
Window.alert("code download failure");
}
public void onSuccess(){
doActualWork(cb);
}
});
}
}
public class FirstClass extends AbstractClass{
public void doActualWork(Callback cb){
//does actually work and calls Callback
}
}
public class SecondClass extends AbstractClass{
public void doActualWork(Callback cb){
//does some other actually work and calls Callback
}
}
When I have the concrete implementation of doAsyncCall(Callback cb) in
AbstractClass, I get 1 split point. When I move the implementation to
each of the sub classes (making the method abstract in AbstractClass),
I get two split points.
Don’t get me wrong, we love the new feature. Here’s hoping for a future enhancement
So for now, I guess every developer will need to know about split points. Not a big deal, just one more thing to remember.
With the new GWT 2.0 (due to be released this year?), they have add a couple of great features. The one I’m most excited about from a users perspective is RunAsync (aka code splitting). To quickly recap, this feature will split a GWT application into multiple developer controlled (split points) downloaded files. We are reworking our internal GUI architecture and have decided to use the unreleased GWT version for development. Our largest application before compression (with obfuscation) is weighing in around 1.4MB. That’s pretty hefty for downloaded javascript files.
We have limped along waiting for GWT 2.0 and code splitting. We didn’t want to put in a temporary solution of using URL redirects and manually splitting our code into modules for a 6 month solution. We’re happy we didn’t. With our refactoring effort, we have designed it so that we can easily have split points at our “module” level (basically a group of related screens).
We don’t have hard numbers yet for an apples-apples comparison, we like our first attempt. It looks like we will have three downloads to start our application. The first bundle is about 140K, the second which is a module is about 80K and a leftover module which is 500K. The leftover module is primarly framework items (both GWT – e.g., Button, and our internal framework code).
We expect, as we work with the new functionality, to be able to get these values to go down (particularly the third – leftover download). After all, we only have one split point right now. We also are probably going to put in a new “home” page that displays when the user (same for every user) logs in so that the other download bundles can be download in the background.
The trick with RunAsync is to get the use case correct. RunAsync as it’s name implies doesn’t execute code sequentially. Therefore we had to add a callback mechanism into our code to display the GUI that was just downloaded.
For those interested it looks something like:
public void retrieveViaCallback(final OurInternalCallBackGuiObject callback){
GWT.runAsync(new RunAsyncCallback(){
public void onFailure(Throwable err){
Window.alert("code download failure");
}
public void onSuccess(){
callback.show();
}
});
}
We haven’t dealt with error handling yet (hence the call to Window.alert); but the RunAsync is pretty easy to get going if you have good modularization in your code base already.
In reality it can’t be done with the stock code. In our application we would like to be able to “stop” an event from being fired further.
One example, we have three event handlers that can be added A, B, C (validation, required check, and save rpc). We add the handlers to a button in that order when needed (sub class determine which handlers to add). We want to be able to specify in A or B handler that the event should stop propagating to other handlers.
We tried a couple of different things (including starting to add our own event handling logic) and we settled on two changes to GWT itself. We added a method to GWTEvent:
- public void stop(); /* record that the event should not be passed to more handlers */
- public void isStopped(); /* is the event stopped for further processing */
- public void unStop(); /* reset the stop flag to be false – did in case event is reused */
In our event handlers we can now call event.stop() to stop further propagation.
In HandlerManager.HandlerRegister we modified
private <H extends EventHandler> void fireEvent(GwtEvent<H> event,
boolean isReverseOrder) {
Type<H> type = event.getAssociatedType();
int count = getHandlerCount(type);
if (isReverseOrder) {
for (int i = count - 1; i >= 0; i--) {
H handler = this.<H> getHandler(type, i);
event.dispatch(handler);
if(event.isStopped()) { // CUSTOM: event stop processing
event.unStop(); // did this in case events are reused
break;
}
}
} else {
for (int i = 0; i < count; i++) {
H handler = this.<H> getHandler(type, i);
event.dispatch(handler);
if(event.isStopped()) { // CUSTOM: event stop processing
event.unStop(); // did this in case events are reused
break;
}
}
}
}
While this is a very specific use case, hopefully with enough examples, some thought will be put into an extension mechanism for HandlerManager. Until then, we get to live with our solution.
EDIT: After a post on the GWT list, it looks like this type of use case (developer extensions for the event handling) where considered but deemed too much/too varied to include anything in the GWT 2.0 timeframe. Here is the discussion.