Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix: serialize the type of timestamp lost nano value #1443

Merged
merged 29 commits into from
Aug 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ec6d35f
optimize config loading when start up
l81893521 Apr 29, 2019
99899a3
do not catch MissingException, change to Exception
l81893521 Apr 29, 2019
7f4c883
Merge branch 'develop' of github.com:l81893521/seata into my-develop
l81893521 Apr 29, 2019
a0b4254
Merge branch 'develop' into develop
slievrly Apr 29, 2019
309e658
add warn log while could not found properties
l81893521 Apr 29, 2019
30efbd3
Merge remote-tracking branch 'seata/develop' into my-develop
l81893521 Apr 29, 2019
7c0ac22
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Apr 30, 2019
90bc335
Merge branch 'develop' into develop
slievrly Apr 30, 2019
b3ca5cf
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Apr 30, 2019
3156f6f
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Apr 30, 2019
7aa8165
Merge branch 'develop' of github.com:l81893521/seata into my-develop
l81893521 Apr 30, 2019
88cffd3
Merge branch 'develop' into develop
xingfudeshi May 3, 2019
c3a8888
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 May 24, 2019
00a7fe0
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Jun 4, 2019
10db1db
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Jul 3, 2019
9bc9aa9
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Jul 10, 2019
0ebf5a4
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Aug 7, 2019
a1c4562
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Aug 7, 2019
665b604
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Aug 9, 2019
926ffa1
Merge remote-tracking branch 'origin/develop' into my-develop
l81893521 Aug 10, 2019
e0bc7bb
provide some special type serialize test unit
l81893521 Aug 10, 2019
93463a0
fix java.sql.Timestamp serialize bug
l81893521 Aug 11, 2019
25c887e
change the serializer name
l81893521 Aug 11, 2019
92b8676
remove unused import
l81893521 Aug 11, 2019
19ad43b
fix typo
l81893521 Aug 11, 2019
316afdc
fix typo
l81893521 Aug 11, 2019
96414e8
remove unused code and fix NPE
l81893521 Aug 12, 2019
b521a11
Merge branch 'develop' into fix_special_type_serialize
slievrly Aug 13, 2019
a6823c2
Merge branch 'develop' into fix_special_type_serialize
slievrly Aug 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,30 @@
package io.seata.rm.datasource.undo.parser;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.WritableTypeId;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.ser.std.ArraySerializerBase;
import io.seata.common.Constants;
import io.seata.common.loader.LoadLevel;
import io.seata.rm.datasource.undo.BranchUndoLog;
import io.seata.rm.datasource.undo.UndoLogParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.sql.Timestamp;

/**
* The type Json based undo log parser.
Expand All @@ -41,7 +54,23 @@ public class JacksonUndoLogParser implements UndoLogParser {
private static final Logger LOGGER = LoggerFactory.getLogger(JacksonUndoLogParser.class);

private static final ObjectMapper MAPPER = new ObjectMapper();

private static final SimpleModule MODULE = new SimpleModule();

/**
* customize serializer for java.sql.Timestamp
*/
private static final JsonSerializer TIMESTAMP_SERIALIZER = new TimestampSerializer();

/**
* customize deserializer for java.sql.Timestamp
*/
private static final JsonDeserializer TIMESTAMP_DESERIALIZER = new TimestampDeserializer();

static {
MODULE.addSerializer(Timestamp.class, TIMESTAMP_SERIALIZER);
MODULE.addDeserializer(Timestamp.class, TIMESTAMP_DESERIALIZER);
MAPPER.registerModule(MODULE);
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MAPPER.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
}
Expand Down Expand Up @@ -78,4 +107,53 @@ public BranchUndoLog decode(byte[] bytes) {
}
}

/**
* if necessary
* extend {@link ArraySerializerBase}
*/
private static class TimestampSerializer extends JsonSerializer<Timestamp> {

@Override
public void serializeWithType(Timestamp timestamp, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSerializer) throws IOException {
WritableTypeId typeId = typeSerializer.writeTypePrefix(gen, typeSerializer.typeId(timestamp, JsonToken.START_ARRAY));
serialize(timestamp, gen, serializers);
gen.writeTypeSuffix(typeId);
}

@Override
public void serialize(Timestamp timestamp, JsonGenerator gen, SerializerProvider serializers) {
try {
gen.writeNumber(timestamp.getTime());
gen.writeNumber(timestamp.getNanos());
} catch (IOException e) {
LOGGER.error("serialize java.sql.Timestamp error : {}", e.getMessage(), e);
}

}
}

/**
* if necessary
* extend {@link JsonNodeDeserializer}
*/
private static class TimestampDeserializer extends JsonDeserializer<Timestamp> {

@Override
public Timestamp deserialize(JsonParser p, DeserializationContext ctxt) {
if(p.isExpectedStartArrayToken()){
ArrayNode arrayNode;
try {
arrayNode = p.getCodec().readTree(p);
Timestamp timestamp = new Timestamp(arrayNode.get(0).asLong());
timestamp.setNanos(arrayNode.get(1).asInt());
return timestamp;
} catch (IOException e) {
LOGGER.error("deserialize java.sql.Timestamp error : {}", e.getMessage(), e);
}
}
LOGGER.error("deserialize java.sql.Timestamp type error.");
return null;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,17 @@
*/
package io.seata.rm.datasource.undo.parser;

import java.io.IOException;
import java.math.BigDecimal;
import java.sql.JDBCType;
import java.sql.Timestamp;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.seata.rm.datasource.DataCompareUtils;
import io.seata.rm.datasource.sql.struct.Field;
import io.seata.rm.datasource.undo.BaseUndoLogParserTest;
import io.seata.rm.datasource.undo.UndoLogParser;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
* @author Geng Zhang
Expand All @@ -25,6 +34,39 @@ public class JacksonUndoLogParserTest extends BaseUndoLogParserTest {

JacksonUndoLogParser parser = new JacksonUndoLogParser();

@Test
public void encode() throws NoSuchFieldException, IllegalAccessException, IOException {
//get the jackson mapper
java.lang.reflect.Field reflectField = parser.getClass().getDeclaredField("MAPPER");
reflectField.setAccessible(true);
ObjectMapper mapper = (ObjectMapper)reflectField.get(null);

//bigint type
Field field = new Field("bigint_type", JDBCType.BIGINT.getVendorTypeNumber(), new Long(9223372036854775807L));
byte[] bytes = mapper.writeValueAsBytes(field);
Field sameField = mapper.readValue(bytes, Field.class);
Assertions.assertTrue(DataCompareUtils.isFieldEquals(field, sameField));

//big decimal type
field = new Field("decimal_type", JDBCType.DECIMAL.getVendorTypeNumber(), new BigDecimal("55555555555555555555.55555555555555555555"));
bytes = mapper.writeValueAsBytes(field);
sameField = mapper.readValue(bytes, Field.class);
Assertions.assertTrue(DataCompareUtils.isFieldEquals(field, sameField));

//double type
field = new Field("double_type", JDBCType.DOUBLE.getVendorTypeNumber(), 999999.999999999);
bytes = mapper.writeValueAsBytes(field);
sameField = mapper.readValue(bytes, Field.class);
Assertions.assertTrue(DataCompareUtils.isFieldEquals(field, sameField));

//timestamp type
field = new Field("timestamp_type", JDBCType.TIMESTAMP.getVendorTypeNumber(), Timestamp.valueOf("2019-08-10 10:49:26.926554"));
bytes = mapper.writeValueAsBytes(field);
sameField = mapper.readValue(bytes, Field.class);
Assertions.assertTrue(DataCompareUtils.isFieldEquals(field, sameField));

}

@Override
public UndoLogParser getParser() {
return parser;
Expand Down