An ISO 8583 message is composed of data elements. Time data elements are formatted as HHmmss (hours-minutes-seconds) strings. Date data elements are formatted as MMdd (month-day) strings. The current code base had a lot of duplicated code that used SimpleDateFormat instances to set the date/time data elements. To remove duplication (and avoid future duplication), we needed a helper method that would format date/time objects correctly and set the desired data element.
We didn't want to extend the ISO 8583 message (ISOMsg) class of jPOS. Instead, we created a helper class that wraps the ISOMsg class, and provides methods that we needed.
Again, we start with a test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import static org.junit.Assert.*; import java.util.*; import org.junit.*; import org.jpos.iso.ISOException; import org.jpos.iso.ISOMsg; public class ISOMsgHelperTest { private ISOMsg isoMsg = new ISOMsg(); private ISOMsgHelper helper = new ISOMsgHelper(isoMsg); private Date dateTime = new GregorianCalendar( 2011 , Calendar.APRIL, 15 , 9 , 30 , 59 ).getTime(); @Test public void setsIsoDateAsMonthDay() throws Exception { helper.setIsoDate( 12 , dateTime); assertEquals( "0415" , isoMsg.getString( 12 )); } @Test public void setsIsoTimeAsHourMinuteSecond() throws Exception { helper.setIsoDate( 13 , dateTime); assertEquals( "093059" , isoMsg.getString( 13 )); } @Test public void setsIsoDateTime() throws Exception { helper.setIsoDate( 7 , dateTime); assertEquals( "0415093059" , isoMsg.getString( 7 )); } } |
And here's the class that passes the test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | import java.util.Date; import java.text.*; import org.jpos.iso.ISOException; import org.jpos.iso.ISOMsg; public class ISOMsgHelper { private ISOMsg isoMsg; public ISOMsgHelper(ISOMsg isoMsg) { if (isoMsg == null ) { throw new IllegalArgumentException( "isoMsg cannot be null" ); } this .isoMsg = isoMsg; } public void setIsoDate( int fldNo, Date date) throws ISOException { this .isoMsg.set(fldNo, dateFormat.get().format(date)); } public void setIsoTime( int fldNo, Date time) throws ISOException { this .isoMsg.set(fldNo, timeFormat.get().format(time)); } public void setIsoDateTime( int fldNo, Date dateTime) throws ISOException { this .isoMsg.set(fldNo, dateTimeFormat.get().format(dateTime)); } public Date getIsoDate( int fldNo) throws ISOException { if ( this .isoMsg.hasField(fldNo)) { try { return dateFormat.get().parse( this .isoMsg.getString(fldNo)); } catch (ParseException e) { throw new ISOException( "Error getting date field " + fldNo, e); } } return null ; } // Other getters were removed to improve clarity // Need to make SimpleDateFormat objects thread-safe private static final ThreadLocal<SimpleDateFormat> dateFormat = new ThreadLocal<SimpleDateFormat>() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat( "MMdd" ); } }; private static final ThreadLocal<SimpleDateFormat> timeFormat = new ThreadLocal<SimpleDateFormat>() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat( "HHmmss" ); } }; private static final ThreadLocal<SimpleDateFormat> dateTimeFormat = new ThreadLocal<SimpleDateFormat>() { @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat( "MMddHHmmss" ); } }; } |
Now, we can easily set date/time fields! And the date formatting objects are nicely encapsulated in one place.
1 2 3 4 5 6 7 8 | ISOMsg isoMsg = ...; ISOMsgHelper isoMsgHelper = new ISOMsgHelper(isoMsg); Date now = new Date(); isoMsgHelper.setIsoDate( 12 , now); // local transaction date isoMsgHelper.setIsoTime( 13 , now); // local transaction time ... isoMsgHelper.setIsoDateTime( 7 , new Date()); // transmission date/time |
So far, it has removed a lot of duplicated code. We are expanding ISOMsgHelper to support other commonly used formats. Hope this helps!