Wednesday 27 May 2009

Javascript plus and minus operator gotchas

So I am using the joy that is jquery to ajaxify our web application, and we have a calendar component.

The component has a "next" and "previous" which lets you move between weeks. So I had the following code:
/**
 * Calendar functions
 */
function addEventHandlersToCalendarComponent() {
    $('#previousWeekButton').click(function() {
        $("#calendarViewInMs").val($('#calendarViewInMs').val() - MILLISECONDS_IN_A_WEEK);
        refreshCalendar();
        return false;
    });

    $('#nextWeekButton').click(function() {
       $("#calendarViewInMs").val($('#calendarViewInMs').val() + MILLISECONDS_IN_A_WEEK);

        refreshCalendar();
        return false;
    });

    $('#calendarDateGoButton').click(function() {
        refreshCalendar();
        return false;
    });
}
The previous week worked perfectly, but clicking the next week broke with the server saying it couldn't parse the number.

Hmm.

After thinking about, and seeing the actual value being sent to the server, it was obvious: "-" operators convert both operands into a number, the "+" operator however, does no such goodness, it simple does a string concatenation. The solution was simple, to use the parseInt to coerce the result of the "val()" method into an actual int.

Friday 15 May 2009

Importing data from SQLServer 2005 into SQLServer 2000

We found ourselves in the less than ideal situation of developing against a database with a different version than the production one; we were developing against SQLServer 2005 but it was going to be deployed on SQLServer 2000.

I think this is a big no-no; the closer your development environment, the more valuable it is.

So anyways, we ended up having almost a fairly large (500+MB) SQLServer 2005 which we needed to get into SQLServer 2000 SP4. Restoring the backup didn't work, which isn't too much of a suprise. I certainly wasn't going to export each table into CSV and import it individually!

Google to the rescue. Google came up with this article which worked a treat.

I ended up creating the single SQL file which came out at 1.6GB, then compressed it down to a much more manageable 60MB, moved it across the world to the remote machine and hey bisto - it worked.

Thursday 14 May 2009

FreeMarker an iterating a map

We use FreeMarker to render our views in our web tier. It is a really powerful, fairly extensible (would love to easily add/override builtins!!!), but there are a couple of pain points.

The first is iterating maps. Without going into too much detail, you may expect to be able to do the following:
<#list map as entry>
  Hi there ${entry.key}, this is your value ${entry.value}
</#list>
but you can't.

Neither can you do:
<#list map.entrySet() as entry>
  ...
</#list>


Neither can you do:
<#list map.keySet() as key>
  ${map[key]} or ${map.key} or ${map.(key)} or ${map.[key]}
</#list>

Instead, you need to do the following:

Neither can you do:
<#list map?keys as key>
  ${map.values[key_index]}
</#list>
Nice.

Yeah.
Our latest web application can run in an environment that allows javascript, which means we can make our application much more dynamic.

Our UI consultant decided to use JSON and build up the UI dynamically. Other than the initial html page, the server doesn't return any other HTML.

This has a number of pros and cons, which I will blog about at a later date, but for now, it is off to learn the magic that is jQuery. This is almost certainly going to remind me once more why I always define myself as a "server side web developer" ;)

Groovy bug in 1.6.2 - Spring Transactions are ignored when called from groovy code

http://jira.codehaus.org/browse/GROOVY-3480
My colleague Rich Evans noticed this one. He noticed that our Spring transactional annotations were being ignored if the code invoking the proxy was groovy. Assume we have the following:
public interface MyService {
    boolean isThisWithinATransaction();
}

public final class DefaultMyService implements MyService {
    @Transactional
    public boolean isThisWithinATransaction();
         return TransactionAspectSupport.currentTransactionInfo().hasTransaction()
    }
}
If we dependency inject that service into a groovy class (using groovy 1.6.2) then the method returns false, if it dependency inject it into a Java class, then it returns true.

Note: the actual bug is not specific to Spring's Transactional annotations - it is broader than that - Spring AOP proxies just don't work as expected in groovy 1.6.2. Given how much Spring uses proxies, this is pretty painful!

I am not entirely sure what is involved in this issue - something to do with the fact that the method that the Spring proxy invokes doesn't have the Spring Transaction annotation on it, as it is actually one of Groovy's dispatching methods that gets called. The transactional interceptor is still in the call chain, as the decision to whether the method *could* be transactional is done from static analysis, the problem only exhibits itself during runtime.

I keep meaning to blog about my lessons learnt regarding testing strategies. One of those lessons is the further away your code is from the production environment, the less valuable those tests are. We were hit by this. All our production code (Controllers and services etc.) are written in groovy, but our tests are written using Java. This meant our integration tests passed but our production code failed.

Nothing beats those system level, black box tests. We use selenium for this, but just haven't got there yet.

Saturday 9 May 2009

Two good discussion tools

Nice article: two good discussion tools

I have an ongoing dilema on how to facilitate good discussion. I am opinionated and to the point, but I am also open to discussion. I have no issue stating a fact and being proven wrong. Within the right context, this can lead to some excellent discussions, but I can also feel like a great big hammer crushing other people and their opinions. Which I hate, and never, ever intend.

I am very luck to work along side two other colleagues who are like minded, but rather more polished and refined than me (they know words like Oort and latin and everything ;)).

Anyway, the above article has two simple, and I think very effective tools that I will start adopting.

Hopefully this will be an end to my wife's (who I love dearly) "It isn't what you say, it is the way that you say it" record. If they could manage to use the material that record is made of in engineering, things would last for ever - I know that particular record has ;) :)

Friday 8 May 2009

Leopard TimeMachine saved my bacon

Had to hard boot my leopard MacBook Pro 17".  When it came back, everything was wrong - loads of corrupted files etc.

Time for reboot I thought - I had everything backed up using Time Machine and spideroak.  Or so I thought :)

So an hour (ish) later I had a fresh virgin installation.  I could have chosen to restore from Time Machine during the update, but I wanted a bit more control (:)) than that, so I didn't.

I created the exact same username/password (not sure if that is relevant), and logged in.  Clicked on the Time Machine icon and there it was - a beauty to behold - restoring was slightly unintuitive - I expected to be able to right click and restore, but no, I needed to select the ones and then click the Restore icon.

So, no more than 3 hours and I am back up and running.

(yeah yeah, I know, if I had done an entire system image it would have been even quicker).

Didn't have to use spideroak this time, but I will be using it to synchronise mine, and my wife's photo galleries.  Rock on.

Logback defaults to DEBUG level

In our project we are using logback for our logging. One really nice feature is that you don't need to do the whole
if (logger.isDebugEnabled()) {
  logger.debug("hi there " + person + ".");
}
You can simply do:
logger.debug("Hi there {}.", person);
A nice, and obvious use of variable argument lists (introduced in JDK 5.0). OK, arguably publicising logback is reason enough for a post, but the real reason I am posting is to point out something that might catch other developers who don't have time to read the entire manual :) Logback has it's own configuration, but if you manage to get it wrong, and it cannot find that configuration it uses it's own default. This default configuration (from the manual):
is hardwired to attaching a ConsoleAppender to the root logger. The output is formatted using a PatternLayout set to the pattern %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n. Moreover, by default the root logger is assigned to the DEBUG level.
So, if you start using it and wonder why you get a whole load of debug, now you know. In fact, you know at least two things:
  1. Logback isn't picking up your configuration (which you might not have)
  2. You need to read the manual, in particular the section on configuration
Go on, be honest, how many people are going to simply read the configuration section and skip the rest, or even better - how many are going to google-paste (google for a configuration and copy and paste it into your own code :)). You know who you are!

ScribeFire and Blogspot and Token Invalid 401

This is my first post from scribefire, which seems to work quite nicely.

To get it to work, I did the following:

  • Install the firefox plugin 
  • Start it up (I configure it to open in a new window)
  • Click on the "Blogs" tab at the top right
  • Click on the Wizard button
  • Enter the URL (colin.yates.blogspot.com)
  • Click Next
  • Enter my username/password (username is your full gmail email account!)
  • Click Next
and that was it!

Do note, however, sometimes it didn't recognise the blogging platform and asked me to choose one.  Unfortunately, blogger wasn't in the drop down, so I cancelled and restarted the wizard.  It took maybe 3 or 4 attempts before it work.  Now it works fantastically - must do, otherwise you wouldn't be reading this.

Thursday 7 May 2009

Convenient directive for iterating lists in freemarker

We are seeing the same pattern of iterating lists within freemarker appearing:
<#list items as item>
  <#if item_has_next>,</#if>
<#list>

this is quite verbose, and error prone so I have added a new directive called 'iterate', which automatically appends a separator (default is comma) if required.
<@iterate items ; item>
  whatever I want to do with the ${item}.
<@iterate>

The directive:
<#macro iterate items separator=','>
<#list items as item>
  <#nested item/>
  <#if item_has_next>${separator}<!--#if-->
<#list>
<#macro>

To use, this you need to put it into a file (i.e. mystuff.ftl) and then include it within all the templates from which you want to use the new directive (i.e. all of them ;)).
My freemarker fu sucks a bit at this point. We have a web app so I included it in /WEB-INF/views/includes/mystuff.ftl (of course I didn't call it that!). Unfortunately I needed to specify the relative path as I couldn't figure out the fully qualified one - /WEB-INF/views/includes/mystuff.ftl and /views/includes/mystuff.ftl don't work.
So, if my template is /WEB-INF/views/people/list.ftl then I need to do the following:
<#include ../includes/mystuff.ftl>

<@iterate people ; person> Person ${person_index}: ${person.name} <@iterate>

We are using Spring to configure Freemarker, which means using FreeMarkerConfigurer. Unfortunately, I don't think this supports the ability to specify automatic includes (similar to JSP preludes and codas), so I might need to write my own. No biggies.
Hi, world,

My name is Colin Yates and I am a Software Engineer. I am primarily interested in doing software engineering better. Why do we have such a dismal success rate. Successes are more often than not accidents, or at least unexpected ;) Why is that? Why is software so hard to do well? Technologies/processes I am interested in: spring, gradle, groovy, pragmatic development, testing and so on.

This blog will be a dumping ground for pretty much anything I think about that might be worth sharing. Or not.

One warning - I sometimes talk utter tosh, but just occasionally there are little nuggets in there as well. Good luck finding them! To be fair, I will try and separate my posts with a consistent set of tags.