You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2019/02/20 00:32:30 UTC
[geode] branch feature/GEODE-6291 updated: added reflection based
auto serializer support
This is an automated email from the ASF dual-hosted git repository.
dschneider pushed a commit to branch feature/GEODE-6291
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/feature/GEODE-6291 by this push:
new da0dfc9 added reflection based auto serializer support
da0dfc9 is described below
commit da0dfc9e90ae89fad67aa91440983e343c71ae1c
Author: Darrel Schneider <ds...@pivotal.io>
AuthorDate: Tue Feb 19 16:32:01 2019 -0800
added reflection based auto serializer support
---
.../CreateMappingPreconditionCheckFunction.java | 44 ++++-
...CreateMappingPreconditionCheckFunctionTest.java | 180 ++++++++++++++++++++-
2 files changed, 213 insertions(+), 11 deletions(-)
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunction.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunction.java
index 9091ca4..a12c510 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunction.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunction.java
@@ -40,8 +40,12 @@ import org.apache.geode.internal.jndi.JNDIInvoker;
import org.apache.geode.management.cli.CliFunction;
import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
import org.apache.geode.pdx.PdxSerializable;
+import org.apache.geode.pdx.PdxWriter;
+import org.apache.geode.pdx.ReflectionBasedAutoSerializer;
import org.apache.geode.pdx.internal.PdxField;
+import org.apache.geode.pdx.internal.PdxOutputStream;
import org.apache.geode.pdx.internal.PdxType;
+import org.apache.geode.pdx.internal.PdxWriterImpl;
import org.apache.geode.pdx.internal.TypeRegistry;
@Experimental
@@ -49,18 +53,26 @@ public class CreateMappingPreconditionCheckFunction extends CliFunction<RegionMa
private transient DataSourceFactory dataSourceFactory;
private transient ClassFactory classFactory;
+ private transient ReflectionBasedAutoSerializerFactory reflectionBasedAutoSerializerFactory;
+ private transient PdxWriterFactory pdxWriterFactory;
private transient TableMetaDataManager tableMetaDataManager;
CreateMappingPreconditionCheckFunction(DataSourceFactory factory, ClassFactory classFactory,
+ ReflectionBasedAutoSerializerFactory reflectionBasedAutoSerializerFactory,
+ PdxWriterFactory pdxWriterFactory,
TableMetaDataManager manager) {
this.dataSourceFactory = factory;
this.classFactory = classFactory;
+ this.reflectionBasedAutoSerializerFactory = reflectionBasedAutoSerializerFactory;
+ this.pdxWriterFactory = pdxWriterFactory;
this.tableMetaDataManager = manager;
}
CreateMappingPreconditionCheckFunction() {
this(dataSourceName -> JNDIInvoker.getDataSource(dataSourceName),
className -> Class.forName(className),
+ className -> new ReflectionBasedAutoSerializer(className),
+ (typeRegistry, object) -> new PdxWriterImpl(typeRegistry, object, new PdxOutputStream()),
new TableMetaDataManager());
}
@@ -68,6 +80,10 @@ public class CreateMappingPreconditionCheckFunction extends CliFunction<RegionMa
private void readObject(ObjectInputStream stream) {
this.dataSourceFactory = dataSourceName -> JNDIInvoker.getDataSource(dataSourceName);
this.classFactory = className -> Class.forName(className);
+ this.reflectionBasedAutoSerializerFactory =
+ className -> new ReflectionBasedAutoSerializer(className);
+ this.pdxWriterFactory =
+ (typeRegistry, object) -> new PdxWriterImpl(typeRegistry, object, new PdxOutputStream());
this.tableMetaDataManager = new TableMetaDataManager();
}
@@ -172,22 +188,28 @@ public class CreateMappingPreconditionCheckFunction extends CliFunction<RegionMa
*/
private PdxType generatePdxTypeForClass(InternalCache cache, TypeRegistry typeRegistry,
Class<?> clazz) {
+ Object object = createInstance(clazz);
if (PdxSerializable.class.isAssignableFrom(clazz)) {
- Object object = createInstance(clazz);
try {
cache.registerPdxMetaData(object);
} catch (SerializationException ex) {
throw new JdbcConnectorException(
"Could not generate a PdxType for the class " + clazz.getName() + " because: " + ex);
}
- // serialization will leave the type in the registry
- return typeRegistry.getExistingTypeForClass(clazz);
+ } else {
+ String className = clazz.getName();
+ ReflectionBasedAutoSerializer serializer =
+ this.reflectionBasedAutoSerializerFactory.create(className);
+ PdxWriter writer = this.pdxWriterFactory.create(typeRegistry, object);
+ boolean result = serializer.toData(object, writer);
+ if (!result) {
+ throw new JdbcConnectorException(
+ "Could not generate a PdxType using the ReflectionBasedAutoSerializer for the class "
+ + clazz.getName() + ". Check the server log for details.");
+ }
}
- // TODO
- // Otherwise use the ReflectionBasedAutoSerializer to generate
- // a PdxType for the class.
- throw new JdbcConnectorException(
- "Could not generate a PdxType for the class " + clazz.getName());
+ // serialization will leave the type in the registry
+ return typeRegistry.getExistingTypeForClass(clazz);
}
private Object createInstance(Class<?> clazz) {
@@ -214,4 +236,10 @@ public class CreateMappingPreconditionCheckFunction extends CliFunction<RegionMa
public interface ClassFactory {
public Class loadClass(String className) throws ClassNotFoundException;
}
+ public interface ReflectionBasedAutoSerializerFactory {
+ public ReflectionBasedAutoSerializer create(String className);
+ }
+ public interface PdxWriterFactory {
+ public PdxWriter create(TypeRegistry typeRegistry, Object object);
+ }
}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunctionTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunctionTest.java
index 6074e3e..098b0ce 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunctionTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingPreconditionCheckFunctionTest.java
@@ -16,7 +16,11 @@ package org.apache.geode.connectors.jdbc.internal.cli;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.same;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.Serializable;
@@ -36,6 +40,7 @@ import org.apache.commons.lang3.SerializationUtils;
import org.junit.Before;
import org.junit.Test;
+import org.apache.geode.SerializationException;
import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.cache.execute.ResultSender;
import org.apache.geode.connectors.jdbc.JdbcConnectorException;
@@ -43,11 +48,17 @@ import org.apache.geode.connectors.jdbc.internal.SqlHandler.DataSourceFactory;
import org.apache.geode.connectors.jdbc.internal.TableMetaDataManager;
import org.apache.geode.connectors.jdbc.internal.TableMetaDataView;
import org.apache.geode.connectors.jdbc.internal.cli.CreateMappingPreconditionCheckFunction.ClassFactory;
+import org.apache.geode.connectors.jdbc.internal.cli.CreateMappingPreconditionCheckFunction.PdxWriterFactory;
+import org.apache.geode.connectors.jdbc.internal.cli.CreateMappingPreconditionCheckFunction.ReflectionBasedAutoSerializerFactory;
import org.apache.geode.connectors.jdbc.internal.configuration.FieldMapping;
import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
import org.apache.geode.pdx.FieldType;
+import org.apache.geode.pdx.PdxReader;
+import org.apache.geode.pdx.PdxSerializable;
+import org.apache.geode.pdx.PdxWriter;
+import org.apache.geode.pdx.ReflectionBasedAutoSerializer;
import org.apache.geode.pdx.internal.PdxField;
import org.apache.geode.pdx.internal.PdxType;
import org.apache.geode.pdx.internal.TypeRegistry;
@@ -73,7 +84,19 @@ public class CreateMappingPreconditionCheckFunctionTest {
private CreateMappingPreconditionCheckFunction function;
- public static class PdxClassDummy {
+ public static class NonPdxDummy {
+ }
+
+ public static class PdxClassDummy implements PdxSerializable {
+ @Override
+ public void toData(PdxWriter writer) {}
+
+ @Override
+ public void fromData(PdxReader reader) {}
+ }
+
+ public static class PdxClassDummyNoZeroArg extends PdxClassDummy {
+ public PdxClassDummyNoZeroArg(int arg) {}
}
@Before
@@ -106,8 +129,9 @@ public class CreateMappingPreconditionCheckFunctionTest {
tableMetaDataView = mock(TableMetaDataView.class);
when(tableMetaDataManager.getTableMetaDataView(connection, regionMapping))
.thenReturn(tableMetaDataView);
- function = new CreateMappingPreconditionCheckFunction(dataSourceFactory, classFactory,
- tableMetaDataManager);
+ function =
+ new CreateMappingPreconditionCheckFunction(dataSourceFactory, classFactory, null, null,
+ tableMetaDataManager);
}
@Test
@@ -234,6 +258,156 @@ public class CreateMappingPreconditionCheckFunctionTest {
}
@Test
+ public void executeFunctionGivenPdxSerializableCallsRegisterPdxMetaData()
+ throws Exception {
+ Set<String> columnNames = new LinkedHashSet<>(Arrays.asList("col1"));
+ when(tableMetaDataView.getColumnNames()).thenReturn(columnNames);
+ when(tableMetaDataView.isColumnNullable("col1")).thenReturn(false);
+ when(tableMetaDataView.getColumnDataType("col1")).thenReturn(JDBCType.DATE);
+ PdxField pdxField1 = mock(PdxField.class);
+ when(pdxField1.getFieldName()).thenReturn("COL1");
+ when(pdxField1.getFieldType()).thenReturn(FieldType.LONG);
+ when(pdxType.getFieldCount()).thenReturn(1);
+ when(pdxType.getFields()).thenReturn(Arrays.asList(pdxField1));
+ when(typeRegistry.getExistingTypeForClass(PdxClassDummy.class)).thenReturn(null)
+ .thenReturn(pdxType);
+
+ CliFunctionResult result = function.executeFunction(context);
+
+ assertThat(result.isSuccessful()).isTrue();
+ verify(cache).registerPdxMetaData(any());
+ Object[] outputs = (Object[]) result.getResultObject();
+ ArrayList<FieldMapping> fieldsMappings = (ArrayList<FieldMapping>) outputs[1];
+ assertThat(fieldsMappings).hasSize(1);
+ assertThat(fieldsMappings.get(0))
+ .isEqualTo(
+ new FieldMapping("COL1", FieldType.LONG.name(), "col1", JDBCType.DATE.name(), false));
+ }
+
+ @Test
+ public void executeFunctionThrowsGivenPdxSerializableWithNoZeroArgConstructor()
+ throws Exception {
+ Set<String> columnNames = new LinkedHashSet<>(Arrays.asList("col1"));
+ when(tableMetaDataView.getColumnNames()).thenReturn(columnNames);
+ when(tableMetaDataView.isColumnNullable("col1")).thenReturn(false);
+ when(tableMetaDataView.getColumnDataType("col1")).thenReturn(JDBCType.DATE);
+ PdxField pdxField1 = mock(PdxField.class);
+ when(pdxField1.getFieldName()).thenReturn("COL1");
+ when(pdxField1.getFieldType()).thenReturn(FieldType.LONG);
+ when(pdxType.getFieldCount()).thenReturn(1);
+ when(pdxType.getFields()).thenReturn(Arrays.asList(pdxField1));
+ when(classFactory.loadClass(PDX_CLASS_NAME)).thenReturn(PdxClassDummyNoZeroArg.class);
+ when(typeRegistry.getExistingTypeForClass(PdxClassDummyNoZeroArg.class)).thenReturn(null);
+
+ Throwable throwable = catchThrowable(() -> function.executeFunction(context));
+
+ assertThat(throwable).isInstanceOf(JdbcConnectorException.class)
+ .hasMessage(
+ "Could not generate a PdxType for the class org.apache.geode.connectors.jdbc.internal.cli.CreateMappingPreconditionCheckFunctionTest$PdxClassDummyNoZeroArg because it did not have a public zero arg constructor. Details: java.lang.NoSuchMethodException: org.apache.geode.connectors.jdbc.internal.cli.CreateMappingPreconditionCheckFunctionTest$PdxClassDummyNoZeroArg.<init>()");
+ }
+
+ @Test
+ public void executeFunctionGivenNonPdxUsesReflectionBasedAutoSerializer()
+ throws Exception {
+ Set<String> columnNames = new LinkedHashSet<>(Arrays.asList("col1"));
+ when(tableMetaDataView.getColumnNames()).thenReturn(columnNames);
+ when(tableMetaDataView.isColumnNullable("col1")).thenReturn(false);
+ when(tableMetaDataView.getColumnDataType("col1")).thenReturn(JDBCType.DATE);
+ PdxField pdxField1 = mock(PdxField.class);
+ when(pdxField1.getFieldName()).thenReturn("COL1");
+ when(pdxField1.getFieldType()).thenReturn(FieldType.LONG);
+ when(pdxType.getFieldCount()).thenReturn(1);
+ when(pdxType.getFields()).thenReturn(Arrays.asList(pdxField1));
+ when(classFactory.loadClass(PDX_CLASS_NAME)).thenReturn(NonPdxDummy.class);
+ when(typeRegistry.getExistingTypeForClass(NonPdxDummy.class)).thenReturn(null)
+ .thenReturn(pdxType);
+ ReflectionBasedAutoSerializer reflectionedBasedAutoSerializer =
+ mock(ReflectionBasedAutoSerializer.class);
+ PdxWriter pdxWriter = mock(PdxWriter.class);
+ when(reflectionedBasedAutoSerializer.toData(any(), same(pdxWriter))).thenReturn(true);
+ ReflectionBasedAutoSerializerFactory reflectionBasedAutoSerializerFactory =
+ mock(ReflectionBasedAutoSerializerFactory.class);
+ when(reflectionBasedAutoSerializerFactory.create(NonPdxDummy.class.getName()))
+ .thenReturn(reflectionedBasedAutoSerializer);
+ PdxWriterFactory pdxWriterFactory = mock(PdxWriterFactory.class);
+ when(pdxWriterFactory.create(same(typeRegistry), any())).thenReturn(pdxWriter);
+ function = new CreateMappingPreconditionCheckFunction(dataSourceFactory, classFactory,
+ reflectionBasedAutoSerializerFactory, pdxWriterFactory,
+ tableMetaDataManager);
+
+ CliFunctionResult result = function.executeFunction(context);
+
+ assertThat(result.isSuccessful()).isTrue();
+ Object[] outputs = (Object[]) result.getResultObject();
+ ArrayList<FieldMapping> fieldsMappings = (ArrayList<FieldMapping>) outputs[1];
+ assertThat(fieldsMappings).hasSize(1);
+ assertThat(fieldsMappings.get(0))
+ .isEqualTo(
+ new FieldMapping("COL1", FieldType.LONG.name(), "col1", JDBCType.DATE.name(), false));
+ }
+
+
+ @Test
+ public void executeFunctionThrowsGivenNonPdxUsesAndReflectionBasedAutoSerializerThatReturnsFalse()
+ throws Exception {
+ Set<String> columnNames = new LinkedHashSet<>(Arrays.asList("col1"));
+ when(tableMetaDataView.getColumnNames()).thenReturn(columnNames);
+ when(tableMetaDataView.isColumnNullable("col1")).thenReturn(false);
+ when(tableMetaDataView.getColumnDataType("col1")).thenReturn(JDBCType.DATE);
+ PdxField pdxField1 = mock(PdxField.class);
+ when(pdxField1.getFieldName()).thenReturn("COL1");
+ when(pdxField1.getFieldType()).thenReturn(FieldType.LONG);
+ when(pdxType.getFieldCount()).thenReturn(1);
+ when(pdxType.getFields()).thenReturn(Arrays.asList(pdxField1));
+ when(classFactory.loadClass(PDX_CLASS_NAME)).thenReturn(NonPdxDummy.class);
+ when(typeRegistry.getExistingTypeForClass(NonPdxDummy.class)).thenReturn(null)
+ .thenReturn(pdxType);
+ ReflectionBasedAutoSerializer reflectionedBasedAutoSerializer =
+ mock(ReflectionBasedAutoSerializer.class);
+ PdxWriter pdxWriter = mock(PdxWriter.class);
+ when(reflectionedBasedAutoSerializer.toData(any(), same(pdxWriter))).thenReturn(false);
+ ReflectionBasedAutoSerializerFactory reflectionBasedAutoSerializerFactory =
+ mock(ReflectionBasedAutoSerializerFactory.class);
+ when(reflectionBasedAutoSerializerFactory.create(NonPdxDummy.class.getName()))
+ .thenReturn(reflectionedBasedAutoSerializer);
+ PdxWriterFactory pdxWriterFactory = mock(PdxWriterFactory.class);
+ when(pdxWriterFactory.create(same(typeRegistry), any())).thenReturn(pdxWriter);
+ function = new CreateMappingPreconditionCheckFunction(dataSourceFactory, classFactory,
+ reflectionBasedAutoSerializerFactory, pdxWriterFactory,
+ tableMetaDataManager);
+
+ Throwable throwable = catchThrowable(() -> function.executeFunction(context));
+
+ assertThat(throwable).isInstanceOf(JdbcConnectorException.class)
+ .hasMessage(
+ "Could not generate a PdxType using the ReflectionBasedAutoSerializer for the class org.apache.geode.connectors.jdbc.internal.cli.CreateMappingPreconditionCheckFunctionTest$NonPdxDummy. Check the server log for details.");
+ }
+
+ @Test
+ public void executeFunctionThrowsGivenPdxSerializableAndRegisterThatThrows()
+ throws Exception {
+ Set<String> columnNames = new LinkedHashSet<>(Arrays.asList("col1"));
+ when(tableMetaDataView.getColumnNames()).thenReturn(columnNames);
+ when(tableMetaDataView.isColumnNullable("col1")).thenReturn(false);
+ when(tableMetaDataView.getColumnDataType("col1")).thenReturn(JDBCType.DATE);
+ PdxField pdxField1 = mock(PdxField.class);
+ when(pdxField1.getFieldName()).thenReturn("COL1");
+ when(pdxField1.getFieldType()).thenReturn(FieldType.LONG);
+ when(pdxType.getFieldCount()).thenReturn(1);
+ when(pdxType.getFields()).thenReturn(Arrays.asList(pdxField1));
+ when(typeRegistry.getExistingTypeForClass(PdxClassDummy.class)).thenReturn(null)
+ .thenReturn(pdxType);
+ SerializationException ex = new SerializationException("test");
+ doThrow(ex).when(cache).registerPdxMetaData(any());
+
+ Throwable throwable = catchThrowable(() -> function.executeFunction(context));
+
+ assertThat(throwable).isInstanceOf(JdbcConnectorException.class)
+ .hasMessage(
+ "Could not generate a PdxType for the class org.apache.geode.connectors.jdbc.internal.cli.CreateMappingPreconditionCheckFunctionTest$PdxClassDummy because: org.apache.geode.SerializationException: test");
+ }
+
+ @Test
public void executeFunctionThrowsGivenExistingPdxTypeWithMultipleInexactMatches()
throws Exception {
Set<String> columnNames = new LinkedHashSet<>(Arrays.asList("col1"));