October 20, 2009

Log4j SMTPAppender

Our current project is due for another release to production very soon. Last week Tom added another appender into our log4j configuration for our UAT enviroment. This appender is an SMTPAppender and it sends emails to a group list for our project team. This new appender is set to the ERROR severity. The configuration for this appender looks like this:

log4j.appender.email=org.apache.log4j.net.SMTPAppender
log4j.appender.email.From=me@email
log4j.appender.email.To=us@email
log4j.appender.email.Subject=[AppName] UAT Exception
log4j.appender.email.SMTPHost=host
log4j.appender.email.SMTPUsername=user
log4j.appender.email.SMTPPassword=pass
log4j.appender.email.layout=org.apache.log4j.PatternLayout
log4j.appender.email.layout.ConversionPattern=%d{ISO8601} %-5p [%t %x] [%c{1}] – %m%n
log4j.appender.email.Threshold=ERROR

As of this morning we had recevied 17 emails from UAT. There were 8 types of errors and  the most occurrences of any one type of error was 6. We always had access to this information in the log files of course, but getting the emails has had several advantages:

  • The emails draw your attention – the visibility of problems in UAT has been increase.
  • We’re more inclined to investigate the cause of the error/exception earlier. Previously the devs would generally only become aware of exceptions in UAT when one of our QAs asked one of us to take a look. Having the email going to all the devs also means that more people look at the exception and we are able to troubleshoot it more easily.
  • It’s easier to group exception types – we can collect data about the exceptions more easily.

The plan is to include an SMTPAppender in the log4j configuration for our production environment. I think this is a very good idea and would recommend doing it.

September 13, 2009

iBATIS

We are using iBATIS on my current project for XML-based object relational mapping. I downloaded the developer guide recently because I was interested to learn about the tool and how this part of our code works. This is what I found out:

1. Repositories
We have ten or so repositories in our code base that all look something like this:

import my.common.util.Maps;
import my.domain.Account;
import my.domain.OrderInfo;
import my.domain.OrderInfoState;
import org.springframework.orm.ibatis.SqlMapClientOperations;

import java.util.List;
import java.util.Map;

public class OrderRepository {

    private final SqlMapClientOperations template;

    public OrderRepository(SqlMapClientOperations template) {
        this.template = template;
    }

    public void insert(OrderInfo orderInfo) {
        template.insert("insertOrder", orderInfo);
    }

    @SuppressWarnings({"unchecked"})
    public List findOtherPendingOrdersForAccount(Account account, String orderIdToExclude) {
        Map params = Maps.create();
        params.put("accountNumber", account.getNumber());
        params.put("orderIdToExclude", orderIdToExclude);
        params.put("orderRequestPendingStates", OrderInfoState.PENDINGSTATES);

        return template.queryForList("findPendingOrdersForAccount", params);
    }

    public void setCompletedNotificationSent(String orderId) {
        template.update("setOrderAccountType", orderId);
    }
}

Each repository has a dependency on SqlMapClientTemplate which according to the Spring API is a “helper class that simplifies data access via the iBATIS SqlMapClient API, converting checked SQLExceptions into unchecked DataAccessExceptions”. We use the template to execute SQL statements that are defined in XML SQL Map files – but let’s get back to that in a moment.

2. Next let’s have a look at how this is all wired together in Spring:

<bean id="OrderRepository">
 <constructor-arg ref="sqlMapClientTemplateForApp"/>
</bean>

<bean id="sqlMapClientTemplateForApp">
 <property name="sqlMapClient" ref="sqlMapClientForApp"/>
</bean>

<bean id="sqlMapClientForApp">
 <property name="configLocation" value="classpath:/sqlmap.xml"/>
 <property name="dataSource" ref="appDataSource"/>
</bean>

<bean id="appDataSource" destroy-method="close">
 <property name="driverClassName" value="${my.datasource.driver}"/>
 <property name="url" value="${my.datasource.url}"/>
 <property name="username" value="${my.datasource.username}"/>
 <property name="password" value="${my.datasource.password}"/>
</bean>

Bean sqlMapClientForApp has a property configLocation which has been set to "classpath:/sqlmap.xml". Inside sqlmap.xml we have a few custom handlers (more on that later too) as well as a list of XML SQL Map files (one for each repository):

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//batis.apache.org/DTD SQL Map Config 2.0//EN"
 "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
 <typeHandler javaType="my.domain.Money"
 callback="my.domain.MoneyTypeHandlerCallback"/>

 <sqlMap resource="sqlmaps/orderinfo.xml"/>

</sqlMapConfig>

4. The juicy bit – the SQL Map files

These are XML descriptor files that are used by the iBATIS Data Mapper to map JavaBeans to SQL prepared statements. As explained in the developer guide, iBATIS accepts parameters as input into prepared statements and builds result objects from the ResultSet returned. Below is a cut down version of a typical iBATIS SQL Map configuration file from our code. It has three statements defined – each corresponding to the methods in the repository class above. I have annotated the file with comments explaining the iBATIS syntax:

<sqlMap namespace="orderInfo">

 <!-- Type aliases for fully qualified class names. -->
 <typeAlias alias="orderInfo" type="my.domain.OrderInfo"/>
 <typeAlias alias="account" type="my.domain.Account"/>

 <resultMap id="orderInfoResult" class="orderInfo"> <!-- This class will be instantiated and populated from the data in the ResultSet -->
 <!-- This controls that data that is taken from the ResultSet and how it maps to columns -->
 <result property="orderId" column="order_id"/>
 <result property="orderDate" column="order_date"/>
 <result property="userId" column="user_id"/>
 <result property="account.number" column="account_id"/>
 <result property="account.type" column="account_type"/>
 <result property="account.name" column="account_name"/>
 </resultMap>

 <sql id="order_info_attributes"> <!-- This fragment can be included in the SQL statements. See below -->
 order_info.id,
 order_info.order_id,
 order_info.order_date,
 order_info.user_id,
 order_info.account_id,
 order_info.account_type,
 order_info.account_name
 </sql>

 <!-- This select query uses the resultMap declared above-->
 <!-- This is a mapped statement. These can have param maps as input and result maps as output -->
 <select id="findPendingOrdersForAccount"
 parameterClass="map"
 resultMap="orderInfoResult"> <!--The parameterClass "map" is an alias for a java.util.Map -->
 <!--The SQL can be anything that is valid for the JDBC driver -->
 SELECT DISTINCT
 <include refid="order_info_attributes"/> <!-- This includes the order_info_attributes fragment above -->
 FROM order_info INNER JOIN order_request ON order_info.order_id = order_request.order_id
 WHERE order_info.account_id = #accountNumber#  <!-- This is an inline parameter map reference-->
 AND order_info.order_id != #orderIdToExclude#
 AND (
 order_request.state IN (
 <iterate property="orderRequestPendingStates" conjunction=",">
 #orderRequestPendingStates[]#
 </iterate> <!-- This is an iterate dynamic element. The property attribute defines the array or java.util.Collection or java.util.Iterator type to be iterated over -->
 )
 </select>

 <insert id="insertOrder"
 parameterClass="orderInfo">  <!-- The parameterClass is used to restrict the objects that can be passed as an input parameter -->
 INSERT INTO order_info(order_id, order_date, user_id, account_id, account_type, account_name)
 VALUES(#orderId#, #orderDate#, #userId#, #account.number#, #account.type#, #account.name#)
 <selectKey resultClass="int" keyProperty="id">  <!-- iBATIS supports auto-generated keys -->
 SELECT LAST_INSERT_ID() AS id
 </selectKey>
 </insert>

 <update id="setOrderAccountType" parameterClass="string">
 UPDATE order_info SET account_type = blah WHERE order_id = #value#
 </update>

</sqlMap>

5. Custom type handlers

Some of our repositories use the iBATIS custom type handlers declared in the sqlmap.xml file (above) to map columns to specific types in our domain. For example the sellPrice field on Product is Money type:

<resultMap id="productMapping">
 <result property="sellPrice" column="sell_price"/>
 <result property="status" column="status"/>
</resultMap>

iBATIS will use the MoneyTypeHandler below to create a Money instance from the sell_price value. Each one of these handlers implements the TypeHandlerCallback interface.

import my.domain.Money;
import com.ibatis.sqlmap.client.extensions.ParameterSetter;
import com.ibatis.sqlmap.client.extensions.ResultGetter;
import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Types;

public class MoneyTypeHandler implements TypeHandlerCallback {

    public void setParameter(ParameterSetter parameterSetter, Object obj) throws SQLException {
        if (obj == null) {
            parameterSetter.setNull(Types.DECIMAL);
        } else {
            Money money = (Money) obj;
            parameterSetter.setBigDecimal(money.toBigDecimal());
        }
    }

    public Object getResult(ResultGetter resultGetter) throws SQLException {
        BigDecimal value = resultGetter.getBigDecimal();
        return (value != null) ? new Money(value) : Money.ZERO;
    }

    public Object valueOf(String value) {
        return value;
    }
}

September 7, 2009

Lists, maps etc

On our project we are using some utility/toolbox Java classes that Tom, Alex and others on our project have made.  You can find versions of them similar to the ones we are using on our project in Tom’s example J2EE web application. There is also a slightly different flavour of them available here. Most of the classes help you to manage and mutate collections.  We have found them to be very useful on our project. In fact, we currently have 152 uses of the create method from the Lists class (see below) in our code base (which works out to be about one in every three classes).

We use the Lists the most overall. Tom and I used it a couple of weeks ago to get some data from a repository. This was based on what we’d grabbed in another repository and then narrowed the result further using a select statement. All this in only three quickly assembled lines of Java:

Listfoos=fooRepository.findBySomeCriteria();
Listbars=Lists.map(foos,new BarMapper(barRepository));
bar=Lists.select(bars,new CompletedBarsMatcher());

Here is the code in the Lists class:

import org.hamcrest.Matcher;
import org.hamcrestcollections.Function;
import org.hamcrestcollections.FunctionMapper;
import org.hamcrestcollections.RejectMatcher;
import org.hamcrestcollections.Selector;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class Lists {

    public static  List create() {
        return new ArrayList();
    }

    public static  List create(Collection instances) {
        return new ArrayList(instances);
    }

    public static  List create(T... instances) {
        List list = create();
        Collections.addAll(list, instances);
        return list;
    }

    public static  T first(List list) {
        return first(list, null);
    }

    public static  T first(List list, T defaultValue) {
        return isEmpty(list) ? defaultValue : list.get(0);
    }

    public static  T last(List list) {
        return last(list, null);
    }

    public static  T last(List list, T defaultValue) {
        return isEmpty(list) ? defaultValue : list.get(list.size() - 1);
    }

    public static  boolean isEmpty(List list) {
        return (list == null) || list.isEmpty();
    }

    public static  boolean isNotEmpty(List list) {
        return !isEmpty(list);
    }

    public static  boolean contains(List list, Matcher matcher) {
        for (T item : list) {
            if (matcher.matches(item)) {
                return true;
            }
        }
        return false;
    }

    public static  T findFirst(List list, Matcher matcher) {
        for (T item : list) {
            if (matcher.matches(item)) {
                return item;
            }
        }
        return null;
    }

    public static  int count(List list, Matcher matcher) {
        int count = 0;
        for (T item : list) {
            if (matcher.matches(item)) {
                count++;
            }
        }
        return count;
    }

    public static  List select(List list, Matcher matcher) {
        return (List) Selector.select(list, matcher);
    }

    public static  List reject(List list, Matcher matcher) {
        return (List) RejectMatcher.reject(list, matcher);
    }

    public static  List map(List list, Function function) {
        return (List) FunctionMapper.map(list, function);
    }

    public static  U reduce(List list, U initialValue, Reducer reducer) {
        U result = initialValue;
        for (T item : list) {
            result = reducer.reduce(item, result);
        }
        return result;
    }
}

You can see that several of the methods call functions in the hamcrest-collections library in this version of Lists. Tom was saying that he doesn’t like that they return an Iterable that then needs to be cast to a List (in this case). Note also the implementation of the reduce function that Tom and Alex wrote. It is actually mapping and reducing – but I’ll let Alex give all the details about that one in his promised blog post :-)

August 20, 2009

Seeing the real thing

About three weeks ago I moved onto a new project that has already been going for several months. My arrival on the team coincided with the team also physically moving into a bigger space in a different building about 10 minutes walk from where they were previously. However the users of one of the systems that we integrate with remained in the original location.

Last week Nick and I were pairing on two defects that were raised in QA in our application. Both of these were indirectly caused by some data coming from our fake test implementation of one of our integration points. Our aim was not to make our fake any more capable or complicated than we possibly needed it to be. However, we did need to modify our fake, both to avoid raising bugs, or fix them where they occurred.

A question arose about how the real implementation of the system that we are faking works. Nick called up the users of the real system and within 15 minutes we were back at the old building chatting with them.

The ability to quickly get in touch with real users and see exactly how they do their jobs is extremely beneficial for a project team. There is no description or diagram that can replace the context and ‘ah ha’ kind of understanding that you get when you see the real thing. I remember having the same kinds of experiences in past jobs that I’ve had when I was an aerospace engineer. Going down and seeing the relevant parts (or even similar parts) on the production line gives you tangible knowledge and recognition that no detailed “fancy” CAD simulation, or description, can.

Not being able to access real systems and users is one of the biggest challenges  facing any deivery team. Where you are not working in the same immediate space as the people involved (either directly or indirectly) with the team, you are immediately at a disadvantage. Lucky for us, our recent move was only a small one, and direct contact can still be maintained.

This need for ongoing contact is something that ThoughtWorks is very aware of when doing distributed agile projects – now I know why.

August 20, 2009

On mocking and Spring

Two weeks ago I was pairing with Alex on some Java integration tests for an application that uses Spring for dependency injection. Whilst writing one of the tests we realised that we needed to mock some behaviour on one of our Spring configured classes. Instinctively the simplest way to do this would be to replace the bean in our application context with another one, but alas after some brief investigation we discovered this is not an option.We ended up using the same pattern that was already in use in our code base, and I’m sure it’s one that some people will be familiar with:

First up we extracted an interface from the class that whose behaviour we wanted to mock:

public interface FooRepository {
    Foo loadFor(XYZ xyz);
}

Next we created a new Application Context XML configuration file to use for the test and included the ‘real’ one from our application. We also defined a stub class that implemented our new interface. It also had the same id as the class that we wanted to mock behaviour for meaning that the pre-existing definition would be overridden:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd">
 <bean id="FooRepository" class="FooRepositoryStub"/>
 <import resource="applicationContext.xml"/>
</beans>

Now for the behaviour that we want in the test…. Singleton scoped Spring beans are loaded at start-up (unless you have lazy loading which we do not). Hence if we want to be able to define specific behaviour inside a test we can’t use on our stub implementation alone – rather we need to use the stub as a wrapper for a delegate:

public class FooRepositoryStub implements FooRepository {

    private FooRepository delegate;

    public Foo loadFor(XYZ xyz) {
        return delegate.loadFor(xyz);
    }

    public void setDelegate(FooRepository delegate) {
        this.delegate = delegate;
    }
}

The delegate can then be used to provide the mocking that we wanted all along:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")

public class ValidationIntegrationTest {

    @Autowired
    private FooRepository FooRepository;
    private FooRepository FooRepositoryDelegate = mock(FooRepository.class);

    @Before
    public void initializeRepositoryDelegates() {
        ((FooRepositoryStub) FooRepository).setDelegate(FooRepositoryDelegate);
    }

    @Test
    public void shouldInvalidateXYZWhenTheABCRuleIsViolated() {
        XYZ xyz = givenSomeContext();
        andTheUserHoldsFoo(xyz);
        whenSomethingHappends(xyz);
        thenItShouldFailWithReasons(xyz, "XYZ failed because of the ABC rule was violated");
    }

    private void andTheUserHoldsFoo(XYZ xyz) {
        Foo foo = mock(Foo.class);
        when(FooRepositoryDelegate.loadFor(xyz)).thenReturn(foo);
    }
    ....
}

So, with only an interface, another ApplicationContext XML file, a stub and a mock, we can define the behaviour in the test that we wanted (phew)! I’ve used PicoContainer before and only just now realise how easy with had it in setting up tests. Of course there may be an easier way to do all this – and if you have one then I’d love to hear from you.

May 3, 2009

Melbourne Scala Users Group

On Monday night I braved a blustery wet Melbourne night to go to the first Scala Melbourne Users Group meeting at IBS.

The first speaker was Ben Hutchison. Ben presented Combining Object-Oriented and Functional programming, focusing on the features of the language that stand out for him. Ben said that he has really enjoyed what he’s been doing in Scala although he admits it has been a bit of a steep learning curve.
Here’s some things that Ben mentioned that I learnt from the presentation:

  • Functions are first class objects in Scala. From the example Ben showed it appears that you do have to know a little about the syntax in order to understand what the arguments to a method are and what its return type is.
  • You can override methods with fields and all operators are just methods.
  • You can declare a variable as mutable or immutable using the keyword var (mutable) or val (immutable).
  • Ben spent quite a bit of time on traits, which I basically understand from him to be not unlike modules in Ruby. It is possible for a class to inherit multiple traits, and traits can even inherit from other traits (and even classes in unusual circumstances!).The traits concept seems very powerful – for example Ben mentioned one trait called Ordered that when applied to a class effectively gives your class a group of methods like < (less than) and > (greater than) and all you have to do is implement the compare method.
  • Ben talked about mixing OO and functional programming – something that Nick taught me on my last project. In particular Ben spoke about how functions should be side effect free – an idea that Eric Evans talks about in Chapter 10 in Domain Driven Design.

Mark Ryall was the next presenter and he spoke about Scala’s XML support as well as a bit about using Lift on the Google App Engine. From Mark’s presentation I learnt:

  • It is possible to assign some XML to a variable in Scala
  • You can do either DOM or SAX style parsing of XML, and if your not happy with those options there are some pretty cool extraction operators, that look a bit like XPath when they’re used as Mark pointed out.
  • There’s also XML pattern matchers that can match on XML nodes, but will not work on element attributes at the moment at least.
  • You can generate an XML document by calling savefull. It’s also possible to insert Scala code into an XML document and then write that out.
  • Mark has got a Lift application working on the Google App Engine although apparently it was tricky to get going. One of the really impressive things about what he showed was the really concise user authentication that used the Google Accounts.

Jeremy Mawson was the third speaker for the evening and he focused on testing and more specifically on using specs, which I’d not heard of before. In a lot of ways the tests that he showed us looked like RSpec tests but the syntax does not read quite as nicely as RSpec does.

  • Jeremy showed us how you can nest expectations in specs.
  • Apparently there are over 100 matchers already in specs – and if that’s not enough you can write your own
  • spec makes use of implicit function definition to write the tests
  • specs is one of a handful of Scala testing frameworks 
  • You can use JMock and Mockito in Scala

Overall I’d say it was a really successful meeting. I certainly learnt a lot from the three speakers. I would recommend getting along to the next meeting if you’re in Melbourne. Ben did mention that he was thinking of making the next meeting a practical one. Perhaps he can check out Mark’s blog entries about the TW Sydney Wednesday Night Dojo for some ideas.

April 19, 2009

Testing database naming conventions in Java

I was recently reminded about some tests that we ran as part of the continuous integration build on my last project – tests that made sure that the database table, column and constraint names adhered to the client’s standards. The idea is quite simple and did on a number of occasions during development prove to be very useful. These tests certainly avoided any last-minute pre-release manual testing.

The tests were all contained in a single class and ran from a Buildr project (below). The tests use JUnit and Hamcrest along with Java SQL:

public class DatabaseNamingStandardsTest {

    private static Set tableNames;
    private static Connection connection;

    @BeforeClass
    public static void connectToOracle() throws SQLException,
                                                ClassNotFoundException,
                                                IOException {

        String configFileName = System.getProperty("config_file");

        Properties properties = new Properties();
        properties.load(new FileInputStream(configFileName));

        String url = properties.getProperty("database.url");
        String driver = properties.getProperty("database.driver");
        String username = properties.getProperty("database.username");
        String password = properties.getProperty("database.password");

        Class.forName(driver);

        connection = null;
        connection = DriverManager.getConnection(url, username, password);

        tableNames = listOfTableNames();
    }

    @AfterClass
    public static void tearDownConnections() throws SQLException {
        connection.close();
    }

    private static Set listOfTableNames() throws SQLException {
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(
                "SELECT table_name\n" +
                "FROM user_tables");
        Set result = new HashSet();
        while (resultSet.next()) {
            String tableName = resultSet.getString("TABLE_NAME");
            result.add(tableName);
        }
        return result;
    }

    @Test
    public void tableNamesShouldBeOfMaximum25CharactersInLength() {
        for (String tableName : tableNames) {
            assertThat(tableName.length(), lessThan(26));
        }
    }

    @Test
    public void ColumnNamesShouldBeOfMaximum30CharactersInLength() throws SQLException {
        Statement statement = connection.createStatement();
        for (String tableName : tableNames) {
            ResultSet resultSet = statement.executeQuery(
                    "SELECT * \n"
                    +"FROM user_tab_columns \n"
                    +"WHERE table_name='" + tableName + "'");
            while (resultSet.next()) {
                String columnName = resultSet.getString("Column_Name");
                assertThat(columnName.length(), lessThan(31));
            }
        }
    }
....
}

And here is the Buildr project definition…

define 'database-naming-standards' do
  test.with LIQUIBASE_JAR, JUNIT_JAR, HAMCREST_JAR, ORACLE_CLIENT_JAR
  test.using :properties => { :config_file => ("../../#{$oracle_properties_file}")}
  test.setup(
    ORACLE_DB_SCHEMA.rollback_all,
    ORACLE_DB_SCHEMA.update
  )
  package(:jar)
end

February 1, 2009

LiquiBase: Inserting data from a CSV file

BA couple of weeks ago Nick pointed out to me that it was possible to insert data into a LiquiBase change set from a CSV file. This Load Data feature was added in version 1.7.0 of LiquiBase and is particularly useful for two reasons:

  1. It keeps the length of the changelog file down
  2. It’s easier to edit a CSV file than it is an XML file, especially when you’re adding a large amount of data to a table

While this is a great option there are a couple of things worth keeping an eye out for if you go down this path…

First, dates:
As I’ve written about before, we are using HSQLDB for development but need to support Oracle. We’ve had relatively few problems in working with both, except for the date compatibility issue.

When inserting XML date data into table entries we were using SYSDATE as the value. This works fine in XML, but does not work when loading data from a CSV file. In the CSV case LiquiBase attempts to create a formatted timestamp from the ‘SYSDATE’ string. We tried a number of ways to enter dates that were compatible in both HSQLDB and Oracle, including adding extra columns in the CSV to cater for the different databases (see below). We also tried updating the table date columns after inserting the entries using the CSV file, but this was messy because those columns have not-null constraints.

The solution to the date compatibility problem turns out is very simple (drumroll) – just define the date in one of the date formats in the Liquibase.util.ISODateFormat class (below) and LiquiBase will generate a database specific date for you!

yyyy-MM-dd'T'HH:mm:ss
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd'T'HH:mm:ss.S

Second, columns:

The documentation for the CSV load data feature gives the impression that you need to map each column in the CSV to one in the table. In fact LiquiBase will map the CSV file column headings to table column headings automatically. You only need to map the columns that have a different heading in the CSV to that in the table. Note however that we found it was necessary to map the columns containing date data, even if the headings were the same:

    <loadData tableName="My_Table" file="My_File.csv">
        <column name="CREATED_DATE" header="CREATED_DATE" type="DATE"/>
    </loadData>

Unfortunately the automatic mapping also means that you cannot have extra columns in the CSV.

January 21, 2009

Encountering JavaScript

As of April last year I’d never done any web development at all. Nada. No HTML even. I’ve learnt a lot in the last few months and have been very impressed by the languages and tools that I have used since then. One language that I had heard of but not ever encountered until recently is JavaScript. Until a couple of weeks ago, I knew only two things about it: 1) don’t be fooled into thinking it’s Java, 2) people seem to find it tricky to use.

A few weeks ago I was working on a story that used Thickbox, which is written in JavaScript, and found a sticking point that we only really understood from reading the code (a story for another day perhaps). My colleague, Adam, kindly lent me his copy of JavaScript: The Good Parts and I have to say it certainly helped me understand the Thickbox code (which was my initial reason for reading it). It also showed me some impressive (and/or quirky) features. Here is some of what I found out (drumroll):

Objects:

Everything in JavaScript is an object if it’s not either a number, string, boolean, null, or undefined. Functions, arrays and everything else you can think of are objects – or keyed collections. Objects have prototypes that they can inherit properties from. These prototypes can have prototypes of their own and so on. When we ask for a property on an object, if the object is missing that property then it will delegate to the prototype, then it’s prototype etcetera.

Functions:

Crockford emphasises that functions are “The best thing about JavaScript” (pg 26). Functions in JavaScript are first class objects and it’s for this reason that they can be stored in variables, arrays and other objects. Functions are “used for code reuse, information hiding, and composition.” (pg 26). What is most interesting for me about these is what Crockford describes as the four function invocation patterns, which differ in how the this parameter is initialised:

1. The Method Invocation Pattern: The function is a property of an object. The this parameter gives access to the object that the function belongs to, for example:

var calendar = {
    monthsPerYear: 12,
    currentDate: new Date(),
    currentMonth: function () {
       return this.currentDate.getMonth() + 1;
    },
    monthsToYearEnd: function () {
       return this.monthsPerYear - this.currentMonth()
    }
};

2. The Function Invocation Pattern: If object X has a function which in turn has an inner function, the inner function will have a this parameter that is bound to the global object (yikes). We can give the inner function access to object X by using another variable called that:

calendar.daysToYearEnd = function() {
    var that = this;
    var daysToYearEnd = 0;

    var daysToMonthEnd = function(startDay, month) {
        switch (month) {
        case (9):
        case (4):
        case (6):
        case (11): //Note that Crockford does put switch fall throughs in the JavaScript 'bad' category
            return 30 - startDay;
        case (2):
            return 28 - startDay;
        default:
            return 31 - startDay;
        }
    };

    var daysToEndofCurrentMonth = function() {
        return daysToMonthEnd(that.currentDate.getDate(), that.currentMonth());
    };

    daysToYearEnd += daysToEndofCurrentMonth();
    for (i = 1; i < this.monthsToYearEnd() + 1; i += 1) {
        daysToYearEnd += daysToMonthEnd(0, this.currentMonth() + i);
    }
    return daysToYearEnd;
};

3. The Construction Invocation Pattern: The function is invoked using the new prefix and actually creates a new object. The this parameter is set to the new object. The constructor function has a prototype. The created object (in this case myCalendar) will have its prototype set as the prototype of the constructor function (PersonalisedCalendar.prototype).

var PersonalisedCalendar = function(name) {
    this.name = name;
};

var myCalendar = new PersonalisedCalendar('Liz');

PersonalisedCalendar.prototype.OwnersName = function() {
    return this.name;
};
document.writeln(myCalendar.name)

4. The Apply Invocation Pattern: The apply method lets us decide on the value that should be bound to the this parameter, as well as letting us define an array of parameters:

var today = function() {
    return this.currentDate;
}
var dateToday = today.apply(calendar, null);

More functions… closures and memoization

JavaScript variables have function scope (as opposed to block scope in Java for example). In the earlier example we saw that it was possible for an inner function to access to the variables of an outer function. The inner function will keep a hold on these variables and can continue to use them even if the outer function returns. This website has some good examples of closures – including number 5, which is very similar to one in the book.

We can use closures to help remember the result of previous invocations in order to cut down on the number of times they are called. This called memoization and involves an array to store the calculated results, as well as an inner function. The example the Crockford gives is reproduced (from pg 44/45 of the text) below:

var fibonacci = function() {
    var memo = [ 0, 1 ];
    var fib = function(n) {
        var result = memo[n];
        if (typeof result !== 'number') {
            result = fib(n - 1) + fib(n - 2);
            memo[n] = result;
        }
        return result;
    };
    return fib;
}();

for ( var i = 0; i <= 10; i += 1) {
    document.writeln(fibonacci(i));
}

JSLint

In the text Crockford discusses JSLint – a JavaScript syntax checker and verifier that he’s created. I used it on the code I wrote for this post and it did help identify some missing semi-colons!

December 20, 2008

Things I like about Buildr

A few months ago the idea of myself writing such words (“Things I like about Buildr“) seemed very unlikely and I dare say that my project buddies may be surprised at the statement. Buildr, for those unfamiliar, is a build tool for Java applications that is written in Ruby. It’s key benefit is its concise and extensible nature. A bit of the wow factor of Buildr is a bit lost on me because I’ve not yet used Maven and I’ve only used Ant in some pretty straightforward ways… and I’d not used Rake prior to using Buildr. (So a strong starting point I’m sure you’d agree. Hhhmm, anyway…)

Our project buildfile started off looking very much like the example in the Buildr documentation, but has since grown significantly in functionality but not proportionally in size. We have complimented the Buildr functionality with handfuls of Rake tasks that perform other bits and pieces associated with our build, such as:

  • Deploying a WAR package to a Tomcat server
  • Starting and stopping database and Selenium servers
  • Updating and rolling back our HSQLDB and Oracle databases using LiquiBase
  • Checking the contents of the build artifacts produced using the Buildr check functionality

The time we’ve spent trawling through the documentation and getting ankle deep in the source has paid off. I want to capture how we’ve set up some of these build activities. So without further introduction and in no particular order, here are some of my favourites (drumroll):

1. Pretty packaging

In my earlier post I described how we used One-JAR to create a single JAR containing all the bits required to update/rollback a database using LiquiBase. Below is the sub-project task that is used to package the lot. The nicest things about this sub-project are how easily we’ve packaged the included JARs, and how easily we’ve added entries into the manifest file:

        define "assembly" do
            package(:jar).path("lib").tap do | p |
                p.include artifact(LIQUIBASE_JAR).to_s
                p.include artifact(HSQLDB_CLIENT_JAR).to_s
            end
            package(:jar).path("main").tap do | p |
                p.include project('database-migration').package(:jar)
            end
            package(:jar).include file('../changelog.xml')
            package(:jar).with :manifest=>manifest.merge(
                    'One-Jar-Main-Class'=>'my.package.DatabaseMigration',
                            'Main-Class'=>'com.simontuffs.onejar.Boot'
            )
        end

2. Delightful dependencies

Some of our rake tasks require us to depend on the existence of a WAR or JAR that has been packaged in one of our buildfile sub-projects. For example, the task that deploys to a Tomcat server depends on a WAR file being generated from one of our sub-projects. Thanks to Buildr, you can do something like this:

task :foo => ['rake:MyProject:MySubProject:package'] do

Note that it is also possible and extemely easy to refer to an artifact that one of your projects has created by using syntax like this:

"#{GROUP}:MyProject-MySubProject:war:#{VERSION_NUMBER}"

3. Fabulous filtering

We are using HSQLDB for development because it’s really light. Our application also needs to support Oracle though, and hence we wanted to run some of our acceptance tests using both databases. To achieve this we created another Buildr sub-project that runs some of the tests against Oracle (we already had the one that runs all the acceptance tests with HSQLDB). There are two things about this sub-project (below) that impress me. The first is that we reuse code using Buildr’s filter task. The second is how easily we can run only a subset of the tests using ‘test.include’:

            define 'my-sub-project' do
                filter(project('bar').compile.sources).into(_('my_directory_1')).run
                filter(project('bar').test.compile.sources).into(_('my_directory_2')).run
                compile.from(_('my_directory_1'))
                compile.into(_('target/classes'))
                test.compile.from(_('my_directory_2'))
                test.compile.into(_('target/test/classes'))
                test.compile.with _('target/classes')
                test.using :properties => { :my_property => property_value }
                test.include '*only_these_tests*'
                test.setup(
                    ...
                )
                test.teardown(
                    ...
                )
            end

4. Cheeky checking

Buildr callbacks can be used to extend projects. We’ve combined the after-define callback with the handy project check task to test that we’ve built what we expect to and created a number of modules like this one:

module CheckJarExists
    include Extension

    after_define do |project|
        project.enhance do
            project.check_jar_exists project
        end
    end

    def check_jar_exists project
        project.check project.package(:jar), 'should exist' do
            puts 'checking jar package exists....'
            it.should exist
        end
    end
end

And just in-case you’re like me and unsure of how to include this module in a project task, here’s how we did it:

define "subproject" do
      extend CheckJarExists
      package(:jar)
end

I’m sure there’s lots more favourites out there in the deep blue Buildr sea… happy fishing!