Archive for October, 2007

Old Friends, New Opportunity

A little late (since the vast majority of readers of this blog are personally affected), but for historical purposes I’m blogging that I’m joining Appcelerator, Inc (formerly Hakano) as a software developer. I’m extremely excited about this opportunity for a few reasons. One, appcelerator is an open-source RIA platform that, of all things, uses internet technologies. You can actually run Appcelerator apps in a web-browser, no fancy plugins required. Add to that, the team’s full of people I know and respect, which is a big plus. Oh, and did I mention that I’ll get paid to work on open-source stuff?

All that said, I’m not leaving the old gig totally regret free (name withheld since I show up in a google search for it way to much already). I wish all the guys (and gal) remaining there the best of luck. I really enjoyed (most) of the time there and I’m definitely going to miss the environment that we built in the last year and a half.

So ‘Yay!’ RIA’s that work in a browser, and ‘Cheers!’ to Social Mobilization!

  • Share/Bookmark

Spring like Validation in DWR

One challenge of a hybrid AJAX and Spring MVC approach is consistent error handling. Since DWR does not have standard validation support, ad-hoc solutions tend to proliferate throughout the source code, leaving both the developer and the end-user confused. This is in contrast to Spring, which includes a validation as part of it’s form processing workflow. Our solution was to graft Spring-like validation on top of our DWR controllers. We’ve implemented this approach on DWR 2.0.

Our methods, exposed via DWR now look like this:

    @RemoteMethod
    @AjaxValidators(PersonalInfoValidator.class)
    public void updatePersonalInfo(PersonalInfo pi) {

Now lets look at the magic that makes this possible.

The first step is to add a filter in the allow section of the dwr.xml configuration file.

    

This line allows you to intercept a call on a dwr method and process any annotations that you might have added on the method (such as @AjaxValidators). The next step is to implement an AjaxFilter. This class has to process the annotations, find the appropriate bean, then preform the validation.

public class AjaxValidationFilter implements AjaxFilter {

    private ApplicationContext applicationContext;

    public AjaxValidationFilter() {
        applicationContext = (WebApplicationContext) ThreadContext.get(ThreadLocalSpringCreator.BEAN_FACTORY_KEY);
    }

    public Object doFilter(Object obj, Method method, Object[] params, AjaxFilterChain chain) throws Exception {
        AjaxValidators ann = method.getAnnotation(AjaxValidators.class);
        boolean throwErrors = false;
        if(ann != null) {

            int lastParamToValidate = Math.min(params.length, ann.value().length);
            BindException[] errors = new BindException[lastParamToValidate];

            for(int i = 0; i < lastParamToValidate; i++) {
                Validator validator = getValidator(ann.value()[i]);

                // allow skipping un-validated arguments by passing null
                if(null != validator) {
                    Object param = params[i];
                    errors[i] = new BindException(param, "");
                    ValidationUtils.invokeValidator(validator, param, errors[i]);

                    if(!throwErrors && errors[i].hasErrors()) {
                        throwErrors = true;
                    }
                }
            }
            if(throwErrors) {
                throw new net.vijedi.ajax.validation.AjaxValidationException(errors);
            }
        }

        // if everything went well no exceptions have been thrown,
        // and we can call the actual method
        return chain.doFilter(obj, method, params);

    }

    private Validator getValidator(Class validatorClass ) throws Exception {
        if(validatorClass == null) return null;
        String[] possibleValidators = applicationContext.getBeanNamesForType(validatorClass);
        return (Validator) applicationContext.getBean(possibleValidators[0]);
    }
}

There’s a few things of note. First is that the value of the annotation is an array. Therefore, you can have one validator per argument to your DWR method. Secondly, we need access to the context where the DWR beans are defined, so that we can find the correct instance of the validator. We use an instantiated bean so that we can inject Managers and other properties into the validator to validate business layer requirements (such as searching the database for name conflicts).

The AjaxValidationException class is a normal runtime-exception class that contains an array of org.springframework.validation.Errors objects for errors. It then internally translates this information into a list of NameValue pairs for easy access in javascript. This is our approach, but there are other ways to do this.

Now all errors will be marshaled into a class that has the property javaClassName set to net.vijedi.ajax.validation.AjaxValidationException. This allows you to do whatever you need in your error handler. The simplest thing to do is update the contents of a placeholder div by looping through the errors array. However, if your exception can give you name-value pairs, then it’s entirely possible to highlight specific form fields.

  • Share/Bookmark

WordPress comment response time

Because spammer suck, and spam assassin is a product, not a person, comments only get posted after they go through moderation. Of course, that means that I have to know someone’s posted a comment. This used to work great, but when I switched to having mail running on a separate machine, wordpress stopped telling me that a comment has been posted. Until now.

It turns out that a few months ago, no doubt in a moment of “why the fuck is this running?” I turned off the postfix service. Oops. Turned it back on and watched the stream of emails show up in my inbox. Without fail, comment response and moderation time should be a lot better now.

This is why I don’t maintain production systems.

  • Share/Bookmark

New House!

Almost two months ago, Sonali and I took the big step of buying our own place. So far, we have to say that we absolutely love it! We’re in the city, near places with great food, and with things to do. The best part: our commutes are half as long. I’ve put some pictures up in the photo gallery. We’ll have a house warming party as soon as some of those empty rooms actually have things in them or we have more than a handful of seats. Whichever comes first.

  • Share/Bookmark

The Quartz Kettle

A few posts ago, I talked about how to use Kettle to transform data from your normalized structures into something useful for data warehousing. In-order to have a near real-time data-warehouse, we need run our jobs frequently. This could have the unintended side-effect of a small hiccup causing a snowballing slowdown. Therefore, ensuring that two jobs do not run concurrently is a major concern. You could write a shell script to launch pan, record the pid, then check for the pid if cron starts the job again before the previous instance has had the opportunity to complete. Or you could just use Quartz.

If you’re familiar with Quartz, setting up a job for a Kettle transform is trivial. The key thing is to implement StatefulJob. A side-effect of persisting the state of the job across invocations has a side-effect of forcing the job to complete before it can be started again. Which means that the downwards spiral of resource consumption is not possible.

Another safe-guard is logging when the the time to execute a transformation is longer than the the time allocated. This can be calculated from properties of the JobExecutionContext (context).

long start = System.currentTimeMillis();

runJob();

long runtime = System.currentTimeMillis() - start;
long startTime = context.getFireTime().getTime();
long nextFireTime = context.getNextFireTime().getTime();

if(runtime > (nextFireTime - startTime)) {
  //log error message
}

The call context.getFireTime() returns the time the job started (when the trigger was fired). Next fire time returns the next time the job is supposed to start. If the time between these points is shorter than the time it took run, well then you’ve got a problem. Thankfully, I haven’t run into this yet, so no ideas on how to fix it!

  • Share/Bookmark

Xine screw-up

For some bizarre and unknown reason, my Xine config on the multimedia pc just completely vanished. I blame the crappier power-grid in the city. It’s nowhere near as reliable as Alpharetta.

Anyway, this event resulted in a multi-night quest to get audio working again with digital out Like most things of this nature, it wasn’t a lot of configuration, but tons of googling to find the magic settings. The first bit wasn’t too hard. Modifying the Xine config file in /home/user/.xine/config to add:

audio.output.speaker_arrangement:Pass Through
audio.device.alsa_default_device:plug:spdif:0

restored audio output for both music files (mp3,acc,etc) and movies with an AC-3 audio track. The remaining bummer was audio files stuttered like crazy. Launching xine from the command line with xine --verbose=1 audio-file.mp3 displayed a lot of this on the console:

fixing sound card drift by -1998 pts
fixing sound card drift by -2545 pts
fixing sound card drift by -2999 pts
fixing sound card drift by -3306 pts
fixing sound card drift by -3538 pts
fixing sound card drift by -3709 pts

According to the official Xine FAQ, my soundcard (an on-board VIA 8237 mustn’t be very good and is not keeping track of sampling frequencies very well. While I don’t recall ever having this problem at my previous house, I did always think that audio was playing back faster than it should be. Either way, adding

audio.synchronization.force_rate:48000

resulted in a clean audio stream that’s at the same speed as my IPod.

  • Share/Bookmark
Return top

About

This is my blog about programming. For random stuff, checkout my Twitter or Tumblr