Wednesday, January 25, 2012

NoSQL at IndyJug

I attended a session on NoSQL databases at IndyJUG today. Tom Hunter, the presenter, had done a very extensive research last year on the entire NoSQL landscape for his personal project, and the presentation was a aggregation of this information - he managed to give a good overview of the different NoSQL databases and had a very interesting way of classifying them, if I remember correctly:
1. Column type databases - Hadoop, Big Table
2. Key/Value type - Memcache,..
3. Document type - MongoDB, Couch DB
4. Graph type - Neo4J

Tuesday, January 24, 2012

(-14)%3 and 14%(-3)

Never really thought about it before, if I offhand look at -14%3 and 14%-3, I would have guessed the result to be the same in both cases...but it is -2 in the first case and 2 in the second case.

the rule is a = (a/b)*b + a%b,
(-14) = (-4)*( 3) + (-14)%3
( 14) = (-4)*(-3) + ( 14)%3

Sunday, January 22, 2012

New way of looking at VIM

I am a long time VIM user, but never thought of it this way - http://yanpritzker.com/2011/12/16/learn-to-speak-vim-verbs-nouns-and-modifiers/

Highly recommended if you are planning to take a second look at vim.

Sunday, January 15, 2012

Spring Custom Property Editor - Convert String to Calendar

Continuing on a previous entry:

The previous blog entry was about a custom property editor to convert a string representation of a date to a java.util.Date field. The approach here is a little different, to convert a string representation to a "java.util.Calendar" type, which is a little more complicated.

Say if I have a bean defined this way:

<bean name="project1" class="org.bk.simplygtd.domain.GtdProject" p:name="project1" p:startDate="2010-01-01T12:00:00.000-0800" p:completedDate="2010-01-04T12:08:56.235-0800" p:isDone="true" />


and the class has startDate and completedDate of type java.util.Calendar type.

If no custom property editors are registered this error will be returned when trying to start up the container:

Cannot convert value of type [java.lang.String] to required type [java.util.Calendar] for property 'completedDate': no matching editors or conversion strategy found

This is perfectly reasonable as the container does not know how to transform the Calendar string to Calendar type.

The approach that has best worked for me is to actually write a custom property editor and register it with the container.

This is how my property editor looks:

import java.beans.PropertyEditorSupport;
import java.util.Calendar;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.springframework.util.StringUtils;

public class CustomCalendarEditor extends PropertyEditorSupport {
    private final DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime();

    @Override
    public String getAsText() {
        Calendar value = (Calendar) getValue();
        DateTime dateTime = new DateTime(value);
        return (value != null ? dateTime.toString(this.dateTimeFormatter) : "");
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        if (!StringUtils.hasText(text)) {
            setValue(null);
        } else {
            DateTime dateTime = this.dateTimeFormatter.parseDateTime(text);
            setValue(dateTime.toGregorianCalendar());
        }
    }
}

Note that I have used joda time as bridge between the string representation and java.util.Calendar and have assumed a ISO-8601 format for date.

Now, to register this property editor:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="java.util.Calendar">
                    <bean class="org.bk.simplygtd.spring.CustomCalendarEditor"/>
                </entry>
            </map>
        </property>
    </bean>

That's it, now the conversion between string to Calendar and back should work.

Thursday, January 12, 2012

Spring integration and version 2.0 schema files

Something to note when upgrading Spring Integration from version 2.0 to 2.1.0 -

Schema location to the custom namespace used to be specified this way:
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:int="http://www.springframework.org/schema/integration"
 xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd

This either has to be explicitly the 2.1 version schema or version less, otherwise the start-up of the container aborts:
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:int="http://www.springframework.org/schema/integration"
 xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd

More details here: https://github.com/SpringSource/spring-integration/wiki/Spring-Integration-2.0-to-2.1-Migration-Guide

Sunday, January 1, 2012

Ext-JS, Json - Date/time mapping in Spring MVC with Jackson

The default date/time handling with Jackson and Spring is:

  • To serialize dates as a Unix epoch time - number of millseconds since Jan 1, 1970 (UTC). 
  • To always use GMT as the timezone, irrespective of the default timezone on the server. 

I prefer to see the dates in a string format with ISO-8601 standard. The way to handle this in Spring MVC with version 3.1 of the Spring framework is to provide a custom Jackson ObjectMapper, to handle the date serialization differently. A custom Object Mapper would be along these lines:

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig.Feature;

public class CustomObjectMapper extends ObjectMapper {
    public CustomObjectMapper(){
        super.configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
    }
}

Now Spring 3.1 has made it really simple to register this Custom Object Mapper with the Handler Adapters:
<mvc:annotation-driven > 
    <mvc:message-converters register-defaults="false">
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
            <property name="objectMapper">
                <bean class="org.bk.simplygtd.web.spring.CustomObjectMapper"/>
            </property>
        </bean>
    </mvc:message-converters>
 </mvc:annotation-driven>

Prior to Spring 3.1, a way to register this Custom Object Mapper would have been to write a custom BeanPostProcessor, to iterate through the handler adapters, find the relevant message converter(MappingJacksonHttpMessageConverter) and register the custom object mapper, something along these lines:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;

public class CustomObjectMapperBeanPostProcessor implements BeanPostProcessor{

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof AnnotationMethodHandlerAdapter){
            AnnotationMethodHandlerAdapter methodHandlerAdapter = (AnnotationMethodHandlerAdapter)bean;
            for (HttpMessageConverter<?> messageConverter: methodHandlerAdapter.getMessageConverters()){
                if (messageConverter instanceof MappingJacksonHttpMessageConverter){
                    ((MappingJacksonHttpMessageConverter)messageConverter).setObjectMapper(new CustomObjectMapper());
                }
            }
        }
        return bean;
    }
}

Now the json responses from Spring MVC should be formatted correctly in this format: 2011-12-06T00:00:00.000+0000


If the user interface is using created using Ext-JS, the model for Ext-JS can be customized to use this date format along these lines - date format of 'c' indicates that the date string should be interpreted using ISO-8601 standard:
Ext.define('CUSTOM.model.Proj',{
    extend: 'Ext.data.Model',
    fields:[{name:'id', type:'string'},{name:'name', type:'string'}, 
            {name:'startDate', type:'date', dateFormat:'c'}, {name:'completedDate', type:'date', dateFormat:'c'},
            {name:'isDone', type:'boolean'}, {name:'version', type:'string'}]
});

There is still one problem, when submitting this date Ext-JS still does not format the date string correctly - it would, by default, send the date without the timezone offset(eg. 2011-12-25T00:15:00), which would be interpreted by the JSON deserializer as  a GMT date/time. To fix this just have this global function:

Ext.JSON.encodeDate = function(o)
{
   return '"' + Ext.Date.format(o, 'c') + '"';
};

Now the dates should be correctly posted to the server with timezone offsets also eg. 2011-12-25T01:15:00-05:00



References:
Jackson JSON Processing: http://jackson.codehaus.org/
Jackson Date Handling FAQ: http://wiki.fasterxml.com/JacksonFAQDateHandling
Some ideas from this blog entry: http://magicmonster.com/kb/prg/java/spring/webmvc/jackson_custom.html
Date type in Ext-JS: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.Date