Overriding converters

Sometimes you are required to use multiple converters for the same data type.

This should not be a localization issue which is accomplished with locale based converter, capable of reading an user locale and using it to convert the data, but this is the typical situation where you have two Calendar's... one is meant for a date and the other one only for time... how can we handle it?

The model

The locale calendar converter is activated by default and deals with short dates.

So we would have a problem dealing with a time based calendar:

package org.vraptor.example.converter;

import java.util.Calendar;

/**
 * A class which maintains information on a starting date and duration (time)
 * 
 * @author Guilherme Silveira
 */
public class TimeInfo {

        private Calendar startDate;

        private Calendar duration;

        /**
         * @return the duration
         */
        public Calendar getDuration() {
                return duration;
        }

        /**
         * @param duration
         *            the duration to set
         */
        public void setDuration(Calendar duration) {
                this.duration = duration;
        }

        /**
         * @return the startDate
         */
        public Calendar getStartDate() {
                return startDate;
        }

        /**
         * @param startDate
         *            the startDate to set
         */
        public void setStartDate(Calendar startDate) {
                this.startDate = startDate;
        }

}

Let's see how our logic looks like... a simple logic which does nothing:

package org.vraptor.example.converter;

import org.vraptor.annotations.Component;

@Component("converter")
public class ConverterOverridingLogic {

        private TimeInfo info;

        public void overriding(TimeInfo info) {
                //sua lógica de negócios
                this.info = info;
        }

        public TimeInfo getInfo() {
                return this.info;
        }

}

The solution

So we will override or converter fo the duration property...

We do it by making use of the @Conversion annotation, which takes a converter as parameter:

        /**
         * @param duration
         *            the duration to set
         */
        @Conversion(LocaleCalendarTimeConverter.class)
        public void setDuration(Calendar duration) {
                this.duration = duration;
        }

The form

Let's create the file called /converter/overriding.jsp.

<html>
Fill in the form bellow and remember to use the english (default web.xml) locale!<br/>
<form action="converter.overriding.logic">
        Start date: <input name="info.startDate"/> (example: <b>10/31/2005</b>)<br/>
        Duration: <input name="info.duration"/> (example: <b>11:05 pm</b>)<br/>
        <input type="submit"/>
</form>
</html>

The result and views.properties

So the result page is converter/overriding.ok.jsp:

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html>
Conversion done:
        
Start date: <fmt:formatDate dateStyle="full" type="date" value="${info.startDate.time}"/><br/>
Duration: <fmt:formatDate timeStyle="full" type="time" value="${info.duration.time}"/><br/>
</html>