diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstSerializerFactory.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstSerializerFactory.java index 987d2b1f03358634a41eff1f6f8bfe6cfc9810e1..5006ec1cca5072afa8bd240800c2cd4a01130fbf 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstSerializerFactory.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstSerializerFactory.java @@ -19,6 +19,7 @@ import java.sql.Timestamp; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; import org.nustaq.serialization.FSTConfiguration; +import org.nustaq.serialization.FSTObjectSerializer; /** * @author funkye @@ -39,6 +40,10 @@ public class FstSerializerFactory { UndoLogSerializerClassRegistry.getRegisteredClasses().keySet().forEach(conf::registerClass); } + public void registerSerializer(Class type, FSTObjectSerializer ser, boolean alsoForAllSubclasses) { + conf.registerSerializer(type, ser, alsoForAllSubclasses); + } + public <T> byte[] serialize(T t) { return conf.asByteArray(t); } diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstUndoLogParser.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstUndoLogParser.java index 146c6724d6b81f27066264e237cebb9fc00f1cdb..0231db22100f3803fab85574771ad8f389a531b0 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstUndoLogParser.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/FstUndoLogParser.java @@ -15,21 +15,55 @@ */ package io.seata.rm.datasource.undo.parser; +import io.seata.common.executor.Initialize; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.EnhancedServiceNotFoundException; import io.seata.common.loader.LoadLevel; +import io.seata.common.util.CollectionUtils; import io.seata.rm.datasource.undo.BranchUndoLog; import io.seata.rm.datasource.undo.UndoLogParser; +import io.seata.rm.datasource.undo.parser.spi.FstSerializer; +import org.nustaq.serialization.FSTObjectSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; /** * fst serializer * @author funkye */ @LoadLevel(name = FstUndoLogParser.NAME) -public class FstUndoLogParser implements UndoLogParser { +public class FstUndoLogParser implements UndoLogParser, Initialize { + + private static final Logger LOGGER = LoggerFactory.getLogger(FstUndoLogParser.class); public static final String NAME = "fst"; private FstSerializerFactory fstFactory = FstSerializerFactory.getDefaultFactory(); + @Override + public void init() { + try { + List<FstSerializer> serializers = EnhancedServiceLoader.loadAll(FstSerializer.class); + if (CollectionUtils.isNotEmpty(serializers)) { + for (FstSerializer serializer : serializers) { + if (serializer != null) { + Class type = serializer.type(); + FSTObjectSerializer ser = serializer.ser(); + boolean alsoForAllSubclasses = serializer.alsoForAllSubclasses(); + if (type != null && ser != null) { + fstFactory.registerSerializer(type, ser, alsoForAllSubclasses); + LOGGER.info("fst undo log parser load [{}].", serializer.getClass().getName()); + } + } + } + } + } catch (EnhancedServiceNotFoundException e) { + LOGGER.warn("FstSerializer not found children class.", e); + } + } + @Override public String getName() { return NAME; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/JacksonUndoLogParser.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/JacksonUndoLogParser.java index 6bf6cd07a78645405a7d4f4d3d5e3e96941d139b..95111267c9b2e7b4a3880f35bb150d2b9a1d3577 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/JacksonUndoLogParser.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/JacksonUndoLogParser.java @@ -19,6 +19,7 @@ import java.util.Arrays; import java.io.IOException; import java.sql.SQLException; import java.sql.Timestamp; +import java.util.List; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; import javax.sql.rowset.serial.SerialException; @@ -43,9 +44,13 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.ser.std.ArraySerializerBase; import io.seata.common.Constants; import io.seata.common.executor.Initialize; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.EnhancedServiceNotFoundException; import io.seata.common.loader.LoadLevel; +import io.seata.common.util.CollectionUtils; import io.seata.rm.datasource.undo.BranchUndoLog; import io.seata.rm.datasource.undo.UndoLogParser; +import io.seata.rm.datasource.undo.parser.spi.JacksonSerializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -97,6 +102,28 @@ public class JacksonUndoLogParser implements UndoLogParser, Initialize { @Override public void init() { + try { + List<JacksonSerializer> jacksonSerializers = EnhancedServiceLoader.loadAll(JacksonSerializer.class); + if (CollectionUtils.isNotEmpty(jacksonSerializers)) { + for (JacksonSerializer jacksonSerializer : jacksonSerializers) { + Class type = jacksonSerializer.type(); + JsonSerializer ser = jacksonSerializer.ser(); + JsonDeserializer deser = jacksonSerializer.deser(); + if (type != null) { + if (ser != null) { + module.addSerializer(type, ser); + } + if (deser != null) { + module.addDeserializer(type, deser); + } + LOGGER.info("jackson undo log parser load [{}].", jacksonSerializer.getClass().getName()); + } + } + } + } catch (EnhancedServiceNotFoundException e) { + LOGGER.warn("JacksonSerializer not found children class.", e); + } + module.addSerializer(Timestamp.class, timestampSerializer); module.addDeserializer(Timestamp.class, timestampDeserializer); module.addSerializer(SerialBlob.class, blobSerializer); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoSerializerFactory.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoSerializerFactory.java index fd1d66820fa7b7ed2847af43459a5a69d41bc9e3..6b566928a6237cd7b64f2d52d961701970165590 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoSerializerFactory.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoSerializerFactory.java @@ -20,6 +20,8 @@ import java.sql.Blob; import java.sql.Clob; import java.sql.SQLException; import java.sql.Timestamp; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; import com.esotericsoftware.kryo.Kryo; @@ -43,6 +45,8 @@ public class KryoSerializerFactory implements KryoFactory { private KryoPool pool = new KryoPool.Builder(this).softReferences().build(); + private static final Map<Class, Serializer> TYPE_MAP = new ConcurrentHashMap<>(); + private KryoSerializerFactory() {} public static KryoSerializerFactory getInstance() { @@ -60,11 +64,21 @@ public class KryoSerializerFactory implements KryoFactory { pool.release(kryoSerializer.getKryo()); } + public void registerSerializer(Class type, Serializer ser) { + if (type != null && ser != null) { + TYPE_MAP.put(type, ser); + } + } + @Override public Kryo create() { Kryo kryo = new Kryo(); kryo.setRegistrationRequired(false); + for (Map.Entry<Class, Serializer> entry : TYPE_MAP.entrySet()) { + kryo.register(entry.getKey(), entry.getValue()); + } + // support clob and blob kryo.register(SerialBlob.class, new BlobSerializer()); kryo.register(SerialClob.class, new ClobSerializer()); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoUndoLogParser.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoUndoLogParser.java index c794573d8fcf715f6962debc11b86b54c23431c8..2ab834eef8dbcfd6978e2554a56daf1c97a2ed48 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoUndoLogParser.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/KryoUndoLogParser.java @@ -15,19 +15,52 @@ */ package io.seata.rm.datasource.undo.parser; +import com.esotericsoftware.kryo.Serializer; +import io.seata.common.executor.Initialize; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.EnhancedServiceNotFoundException; import io.seata.common.loader.LoadLevel; +import io.seata.common.util.CollectionUtils; import io.seata.rm.datasource.undo.BranchUndoLog; import io.seata.rm.datasource.undo.UndoLogParser; +import io.seata.rm.datasource.undo.parser.spi.KryoTypeSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; /** * kryo serializer * @author jsbxyyx */ @LoadLevel(name = KryoUndoLogParser.NAME) -public class KryoUndoLogParser implements UndoLogParser { +public class KryoUndoLogParser implements UndoLogParser, Initialize { + + private static final Logger LOGGER = LoggerFactory.getLogger(KryoUndoLogParser.class); public static final String NAME = "kryo"; + @Override + public void init() { + try { + List<KryoTypeSerializer> serializers = EnhancedServiceLoader.loadAll(KryoTypeSerializer.class); + if (CollectionUtils.isNotEmpty(serializers)) { + for (KryoTypeSerializer typeSerializer : serializers) { + if (typeSerializer != null) { + Class type = typeSerializer.type(); + Serializer ser = typeSerializer.serializer(); + if (type != null) { + KryoSerializerFactory.getInstance().registerSerializer(type, ser); + LOGGER.info("kryo undo log parser load [{}].", typeSerializer.getClass().getName()); + } + } + } + } + } catch (EnhancedServiceNotFoundException e) { + LOGGER.warn("KryoTypeSerializer not found children class.", e); + } + } + @Override public String getName() { return NAME; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/ProtostuffUndoLogParser.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/ProtostuffUndoLogParser.java index 9f1a8cdda8aeca378bcbbe6dbc78159b0e7daaf7..6df392f67118cac3b6cef3034e447eff1f924879 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/ProtostuffUndoLogParser.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/ProtostuffUndoLogParser.java @@ -18,6 +18,7 @@ package io.seata.rm.datasource.undo.parser; import java.io.IOException; import java.nio.ByteBuffer; import java.sql.Timestamp; +import java.util.List; import io.protostuff.Input; import io.protostuff.LinkedBuffer; @@ -31,9 +32,15 @@ import io.protostuff.runtime.Delegate; import io.protostuff.runtime.RuntimeEnv; import io.protostuff.runtime.RuntimeSchema; import io.seata.common.executor.Initialize; +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.common.loader.EnhancedServiceNotFoundException; import io.seata.common.loader.LoadLevel; +import io.seata.common.util.CollectionUtils; import io.seata.rm.datasource.undo.BranchUndoLog; import io.seata.rm.datasource.undo.UndoLogParser; +import io.seata.rm.datasource.undo.parser.spi.ProtostuffDelegate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The type protostuff based undo log parser. @@ -43,6 +50,8 @@ import io.seata.rm.datasource.undo.UndoLogParser; @LoadLevel(name = ProtostuffUndoLogParser.NAME) public class ProtostuffUndoLogParser implements UndoLogParser, Initialize { + private static final Logger LOGGER = LoggerFactory.getLogger(ProtostuffUndoLogParser.class); + public static final String NAME = "protostuff"; private final DefaultIdStrategy idStrategy = (DefaultIdStrategy) RuntimeEnv.ID_STRATEGY; @@ -51,6 +60,18 @@ public class ProtostuffUndoLogParser implements UndoLogParser, Initialize { @Override public void init() { + try { + List<ProtostuffDelegate> delegates = EnhancedServiceLoader.loadAll(ProtostuffDelegate.class); + if (CollectionUtils.isNotEmpty(delegates)) { + for (ProtostuffDelegate delegate : delegates) { + idStrategy.registerDelegate(delegate.create()); + LOGGER.info("protostuff undo log parser load [{}].", delegate.getClass().getName()); + } + } + } catch (EnhancedServiceNotFoundException e) { + LOGGER.warn("ProtostuffDelegate not found children class.", e); + } + idStrategy.registerDelegate(new DateDelegate()); idStrategy.registerDelegate(new TimestampDelegate()); idStrategy.registerDelegate(new SqlDateDelegate()); diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/FstSerializer.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/FstSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..88fd697c75654ff0892d8bf4fd93d7b2567262f4 --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/FstSerializer.java @@ -0,0 +1,44 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.seata.rm.datasource.undo.parser.spi; + +import org.nustaq.serialization.FSTObjectSerializer; + +/** + * @author jsbxyyx + */ +public interface FstSerializer { + + /** + * fst serializer class type + * @return + */ + Class type(); + + /** + * FSTObjectSerializer custom serializer + * @return + */ + FSTObjectSerializer ser(); + + /** + * for sub classes + * @return + */ + boolean alsoForAllSubclasses(); + +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/JacksonSerializer.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/JacksonSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..bfefa812f240734f12f482fce91f5941b324a6a1 --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/JacksonSerializer.java @@ -0,0 +1,45 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.seata.rm.datasource.undo.parser.spi; + +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; + +/** + * @author jsbxyyx + */ +public interface JacksonSerializer<T> { + + /** + * jackson serializer class type. + * @return + */ + Class<T> type(); + + /** + * Jackson custom serializer + * @return + */ + JsonSerializer<T> ser(); + + /** + * Jackson custom deserializer + * @return + */ + JsonDeserializer<? extends T> deser(); + +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/KryoTypeSerializer.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/KryoTypeSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..54542359176db4720a49bda80fefdb56ec1b09ed --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/KryoTypeSerializer.java @@ -0,0 +1,38 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.seata.rm.datasource.undo.parser.spi; + +import com.esotericsoftware.kryo.Serializer; + +/** + * @author jsbxyyx + */ +public interface KryoTypeSerializer<T> { + + /** + * kryo serializer class type. + * @return + */ + Class<T> type(); + + /** + * kryo custom serializer. + * @return + */ + Serializer serializer(); + +} diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/ProtostuffDelegate.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/ProtostuffDelegate.java new file mode 100644 index 0000000000000000000000000000000000000000..9ec9683985af36e0c7c089a01d32826b41d22614 --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/parser/spi/ProtostuffDelegate.java @@ -0,0 +1,32 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.seata.rm.datasource.undo.parser.spi; + +import io.protostuff.runtime.Delegate; + +/** + * @author jsbxyyx + */ +public interface ProtostuffDelegate<T> { + + /** + * Delegate create. + * @return + */ + Delegate<T> create(); + +} diff --git a/seata-plugin/pom.xml b/seata-plugin/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..dd7ba7be2ab0babbeae666a826b64490fe301082 --- /dev/null +++ b/seata-plugin/pom.xml @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright 1999-2019 Seata.io Group. + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <groupId>io.seata</groupId> + <artifactId>seata-plugin</artifactId> + <version>${revision}</version> + <packaging>pom</packaging> + + <modules> + <module>seata-jackson-parser-oracle</module> + </modules> + + <properties> + <!-- seata plugin version --> + <revision>1.5.0-SNAPSHOT</revision> + + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + + <maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version> + <maven-source-plugin.version>2.2.1</maven-source-plugin.version> + <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version> + + <ojdbc.version>19.3.0.0</ojdbc.version> + <seata.version>1.5.0-SNAPSHOT</seata.version> + + <junit-jupiter.version>5.4.2</junit-jupiter.version> + <mockito.version>2.23.4</mockito.version> + <assertj-core.version>3.12.2</assertj-core.version> + <junit-platform-launcher.version>1.4.2</junit-platform-launcher.version> + </properties> + + <!--test--> + <dependencies> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>${junit-jupiter.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + <version>${junit-jupiter.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + <version>${junit-platform-launcher.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>${mockito.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <version>${mockito.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>${assertj-core.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + <dependencyManagement> + <dependencies> + <dependency> + <groupId>com.oracle.ojdbc</groupId> + <artifactId>ojdbc8</artifactId> + <version>${ojdbc.version}</version> + </dependency> + <dependency> + <groupId>io.seata</groupId> + <artifactId>seata-rm-datasource</artifactId> + <version>${seata.version}</version> + </dependency> + </dependencies> + </dependencyManagement> + + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>${maven-compiler-plugin.version}</version> + <configuration> + <source>${maven.compiler.source}</source> + <target>${maven.compiler.target}</target> + <encoding>${project.build.sourceEncoding}</encoding> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>${maven-surefire-plugin.version}</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-source-plugin</artifactId> + <version>${maven-source-plugin.version}</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>jar-no-fork</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <repositories> + <repository> + <id>ICM</id> + <url>http://maven.icm.edu.pl/artifactory/repo/</url> + <releases> + <enabled>true</enabled> + </releases> + </repository> + </repositories> + +</project> diff --git a/seata-plugin/seata-jackson-parser-oracle/pom.xml b/seata-plugin/seata-jackson-parser-oracle/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..93c6f0395a7b55aa3a9dba2b0d7aea43d42c83e5 --- /dev/null +++ b/seata-plugin/seata-jackson-parser-oracle/pom.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Copyright 1999-2019 Seata.io Group. + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>seata-plugin</artifactId> + <groupId>io.seata</groupId> + <version>${revision}</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>seata-jackson-parser-oracle</artifactId> + + <dependencies> + <dependency> + <groupId>io.seata</groupId> + <artifactId>seata-rm-datasource</artifactId> + </dependency> + <dependency> + <groupId>com.oracle.ojdbc</groupId> + <artifactId>ojdbc8</artifactId> + </dependency> + </dependencies> + +</project> \ No newline at end of file diff --git a/seata-plugin/seata-jackson-parser-oracle/src/main/java/io.seata.plugin.jackson.parser.oracle/OracleTimestampJacksonSerializer.java b/seata-plugin/seata-jackson-parser-oracle/src/main/java/io.seata.plugin.jackson.parser.oracle/OracleTimestampJacksonSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..a583a50eb27add54e509f2949c87a20a5c1a12ab --- /dev/null +++ b/seata-plugin/seata-jackson-parser-oracle/src/main/java/io.seata.plugin.jackson.parser.oracle/OracleTimestampJacksonSerializer.java @@ -0,0 +1,86 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.seata.plugin.jackson.parser.oracle; + +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.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.TypeSerializer; +import io.seata.common.loader.LoadLevel; +import io.seata.rm.datasource.undo.parser.spi.JacksonSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * @author jsbxyyx + */ +@LoadLevel(name = "oracleTimestamp") +public class OracleTimestampJacksonSerializer implements JacksonSerializer<oracle.sql.TIMESTAMP> { + + private static final Logger LOGGER = LoggerFactory.getLogger(OracleTimestampJacksonSerializer.class); + + @Override + public Class<oracle.sql.TIMESTAMP> type() { + return oracle.sql.TIMESTAMP.class; + } + + @Override + public JsonSerializer<oracle.sql.TIMESTAMP> ser() { + return new JsonSerializer<oracle.sql.TIMESTAMP>() { + @Override + public void serializeWithType(oracle.sql.TIMESTAMP timestamp, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSerializer) throws IOException { + WritableTypeId typeId = typeSerializer.writeTypePrefix(gen, typeSerializer.typeId(timestamp, JsonToken.VALUE_EMBEDDED_OBJECT)); + serialize(timestamp, gen, serializers); + gen.writeTypeSuffix(typeId); + } + + @Override + public void serialize(oracle.sql.TIMESTAMP timestamp, JsonGenerator gen, SerializerProvider serializers) throws IOException { + try { + gen.writeBinary(timestamp.getBytes()); + } catch (IOException e) { + LOGGER.error("serialize oralce.sql.Timestamp error : {}", e.getMessage(), e); + } + } + }; + } + + @Override + public JsonDeserializer<? extends oracle.sql.TIMESTAMP> deser() { + return new JsonDeserializer<oracle.sql.TIMESTAMP>() { + @Override + public oracle.sql.TIMESTAMP deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { + try { + oracle.sql.TIMESTAMP timestamp = new oracle.sql.TIMESTAMP(p.getBinaryValue()); + return timestamp; + } catch (IOException e) { + LOGGER.error("deserialize oracle.sql.Timestamp error : {}", e.getMessage(), e); + } + return null; + } + }; + } + +} diff --git a/seata-plugin/seata-jackson-parser-oracle/src/main/resources/META-INF/services/io.seata.rm.datasource.undo.parser.spi.JacksonSerializer b/seata-plugin/seata-jackson-parser-oracle/src/main/resources/META-INF/services/io.seata.rm.datasource.undo.parser.spi.JacksonSerializer new file mode 100644 index 0000000000000000000000000000000000000000..581b57e403ca50777c44e740c0125b2332e18877 --- /dev/null +++ b/seata-plugin/seata-jackson-parser-oracle/src/main/resources/META-INF/services/io.seata.rm.datasource.undo.parser.spi.JacksonSerializer @@ -0,0 +1,17 @@ +# +# Copyright 1999-2019 Seata.io Group. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +io.seata.plugin.jackson.parser.oracle.OracleTimestampJacksonSerializer \ No newline at end of file diff --git a/seata-plugin/seata-jackson-parser-oracle/src/test/java/io/seata/plugin/jackson/parser/oracle/OracleTimestampJacksonSerializerTest.java b/seata-plugin/seata-jackson-parser-oracle/src/test/java/io/seata/plugin/jackson/parser/oracle/OracleTimestampJacksonSerializerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6c1d7942efa680b02bde21dac925dc241e03f925 --- /dev/null +++ b/seata-plugin/seata-jackson-parser-oracle/src/test/java/io/seata/plugin/jackson/parser/oracle/OracleTimestampJacksonSerializerTest.java @@ -0,0 +1,29 @@ +package io.seata.plugin.jackson.parser.oracle; + +import io.seata.common.loader.EnhancedServiceLoader; +import io.seata.rm.datasource.undo.parser.spi.JacksonSerializer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; + +/** + * @author jsbxyyx + */ +public class OracleTimestampJacksonSerializerTest { + + @Test + public void test_oracleJacksonSerializer() throws Exception { + List<JacksonSerializer> serializers = EnhancedServiceLoader.loadAll(JacksonSerializer.class); + Assertions.assertTrue(serializers.size() > 0, "Jackson Serializer is empty"); + OracleTimestampJacksonSerializer s = null; + for (JacksonSerializer serializer : serializers) { + if (serializer instanceof OracleTimestampJacksonSerializer) { + s = (OracleTimestampJacksonSerializer) serializer; + break; + } + } + Assertions.assertNotNull(s); + } + +}