Showing posts with label dev. Show all posts
Showing posts with label dev. Show all posts

Thursday, 6 August 2009

Hibernate - could be a bit brighter

I love Hibernate - I think it is great. I have seen, and made some hideous applications with Hibernate that run like a dog. With three legs. Two of which are broken, but in pretty much every case, the inefficiency has been down to the use of Hibernate, rather than Hibernate itself. I have no time for people who bash Hibernate because "it is slow". It isn't. It is a tool which needs to be used properly. Almost all the projects I have worked on that have used Hibernate have also included custom JDBC. Anyway, just occasionally, Hibernate wants to make me rip my hair out in frustration. The latest example... I issue the following hql:
select session.id from Session session where session.mask is null or session.mask.id=8013
and I get back no results. Strange, I look in the DB and there are plenty of Sessions with null masks. Hibernate generates the following SQL:
  select
      session0_.id as col_0_0_
 from
      t_session session0_,
      t_mask mask2_
  where
     session0_.mask_id=mask2_.id
      and (
          session0_.mask_id is null
          or mask2_.stream_id=8013
      )
  order by
      session0_.start_date
1 prize for spotting the *stupid stupid stupid* assumption that hibernate made. The solution is to issue the following hql:
select session.id from Session session left outer join session.mask sessionMask where sessionMask is null or sessionMask.id=8013
which issues:
  select
      session0_.id as col_0_0_
  from
      t_session session0_
  left outer join
      t_mask mask1_
          on session0_.mask_id=mask1_.id,
      t_resource resource2_
  where
          mask1_.id is null
          or mask1_.stream_id=8013
  order by
      session0_.start_date
I am sure the manual warns you about this, but really. Hibernate, come on.

Monday, 8 June 2009

Apache Tomcat service fails if running on a 64bit JVM

Our deployment platform is Windows 200x, 64 bit. Don't ask why - I too am a Linux fan boy. Anyway, installing tomcat as a service works, but trying to start said service fails. Turns out that unless you want to jump through a few hoops you need to install the 32bit JDK. (don't forget to update the windows environment variable and then open a new console to pick up the new environment variable ;))

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.

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.

Friday, 8 May 2009

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!

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.