Project: springxd
Issue XD-2581: JDBC sink doesn't deserialize JSON types correctly
*Expected* 1. Create MYTABLE table with DATE or TIMESTAMP column MYTIME 2. Create a stream ending with {code}... | object-to-json | jdbc --tableName=MYTABLE ...{code} 3. Send a message with payload being a Java object that has a property myTime of type java.util.Date 4. Message payload is inserted into MYTABLE table, date is correctly stored in MYTIME column. *Actual* 4. Exception is thrown from JDBC sink which attempts to bind a long into MYTIME column. *Root cause* JDBC sink uses *org.springframework.xd.jdbc.JdbcMessagePayloadTransformer* class to deserialize JSON payload into Map which will later be used to bind parameters into java.sql.PreparedStatement. Unfortunately JdbcMessagePayloadTransformer, and MessageTransformingHandler which is calling it, doesn't respect *json\_\_TypeId\_\_* message header so information about Java types is lost. Other Spring XD components serialize java.util.Date as Unix timestamp e.g. object-to-json transformer. JDBC sink will deserialize the date as java.lang.Long and later attempt to bind incorrect type to query parameter. In case of GemFire XD following exception will be thrown during query parameter binding phase: {code} com.pivotal.gemfirexd.internal.shared.common.sanity.AssertFailure: ASSERT FAILED Number of parameters expected for message id 22005 (3) does not match number of arguments received (2) com.pivotal.gemfirexd.internal.shared.common.sanity.SanityManager.ASSERT(SanityManager.java:239) com.pivotal.gemfirexd.internal.shared.common.i18n.MessageUtil.formatMessage(MessageUtil.java:245) com.pivotal.gemfirexd.internal.shared.common.i18n.MessageUtil.getCompleteMessage(MessageUtil.java:151) com.pivotal.gemfirexd.internal.shared.common.i18n.MessageUtil.getCompleteMessage(MessageUtil.java:191) com.pivotal.gemfirexd.internal.shared.common.i18n.MessageUtil.getCompleteMessage(MessageUtil.java:107) com.pivotal.gemfirexd.internal.client.am.SqlException.(SqlException.java:184) com.pivotal.gemfirexd.internal.client.am.PreparedStatement$PossibleTypes.throw22005Exception(PreparedStatement.java:4007) com.pivotal.gemfirexd.internal.client.am.PreparedStatement.setLong(PreparedStatement.java:843) com.pivotal.gemfirexd.internal.client.am.PreparedStatement.setObject(PreparedStatement.java:1688) org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:402) org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:235) org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:150) org.springframework.jdbc.core.PreparedStatementCreatorFactory$PreparedStatementCreatorImpl.setValues(PreparedStatementCreatorFactory.java:300) org.springframework.jdbc.core.PreparedStatementCreatorFactory$PreparedStatementCreatorImpl.createPreparedStatement(PreparedStatementCreatorFactory.java:252) org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:638) org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:909) org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:933) org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.update(NamedParameterJdbcTemplate.java:313) org.springframework.integration.jdbc.JdbcMessageHandler.executeUpdateQuery(JdbcMessageHandler.java:130) org.springframework.integration.jdbc.JdbcMessageHandler.handleMessageInternal(JdbcMessageHandler.java:112) org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)	... 372 more {code}
Story points: 2