From 7bbac011afd61dc535de298675ef42cb9a3abb56 Mon Sep 17 00:00:00 2001 From: manuzhang Date: Thu, 16 Jun 2016 12:09:22 +0800 Subject: [PATCH] [BEAM-328] uses SerializableCoder for `T extends Serializable` --- .../apache/beam/sdk/coders/CoderRegistry.java | 10 ++++++---- .../beam/sdk/coders/CoderRegistryTest.java | 18 +++++++++++++++--- .../beam/sdk/values/TypedPValueTest.java | 16 ++++++++++++---- .../transforms/RemoveDuplicatesJava8Test.java | 10 ++++++++-- .../beam/sdk/transforms/WithKeysJava8Test.java | 11 +++++++++-- 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java b/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java index 9c3fabed6e18..50e442208cea 100644 --- a/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java +++ b/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java @@ -163,9 +163,9 @@ public void registerCoder(Class clazz, CoderFactory coderFactory) { */ public void registerCoder(Class rawClazz, Coder coder) { checkArgument( - rawClazz.getTypeParameters().length == 0, - "CoderRegistry.registerCoder(Class, Coder) may not be used " - + "with unspecialized generic classes"); + rawClazz.getTypeParameters().length == 0, + "CoderRegistry.registerCoder(Class, Coder) may not be used " + + "with unspecialized generic classes"); CoderFactory factory = CoderFactories.forCoder(coder); registerCoder(rawClazz, factory); @@ -720,7 +720,9 @@ private Coder getDefaultCoder(Type type, Map> typeCoderBinding return getDefaultCoder(clazz); } else if (type instanceof ParameterizedType) { return getDefaultCoder((ParameterizedType) type, typeCoderBindings); - } else if (type instanceof TypeVariable || type instanceof WildcardType) { + } else if (type instanceof TypeVariable) { + return getDefaultCoder(TypeDescriptor.of(type).getRawType()); + } else if (type instanceof WildcardType) { // No default coder for an unknown generic type. throw new CannotProvideCoderException( String.format("Cannot provide a coder for type variable %s" diff --git a/sdks/java/core/src/test/java/org/apache/beam/sdk/coders/CoderRegistryTest.java b/sdks/java/core/src/test/java/org/apache/beam/sdk/coders/CoderRegistryTest.java index 37f0e10c4a88..817ea207994e 100644 --- a/sdks/java/core/src/test/java/org/apache/beam/sdk/coders/CoderRegistryTest.java +++ b/sdks/java/core/src/test/java/org/apache/beam/sdk/coders/CoderRegistryTest.java @@ -388,15 +388,27 @@ public void testTypeVariableErrorMessage() throws Exception { thrown.expect(CannotProvideCoderException.class); thrown.expectMessage(allOf( - containsString("TestGenericT"), - containsString("erasure"), - containsString("org.apache.beam.sdk.coders.CoderRegistryTest$TestGenericClass"))); + containsString("No CoderFactory has been registered"), + containsString("does not have a @DefaultCoder annotation"), + containsString("does not implement Serializable"))); registry.getDefaultCoder(TypeDescriptor.of( TestGenericClass.class.getTypeParameters()[0])); } private static class TestGenericClass { } + @Test + public void testSerializableTypeVariableDefaultCoder() throws Exception { + CoderRegistry registry = new CoderRegistry(); + + TypeDescriptor type = TypeDescriptor.of( + TestSerializableGenericClass.class.getTypeParameters()[0]); + assertEquals(registry.getDefaultCoder(type), + SerializableCoder.of(type)); + } + + private static class TestSerializableGenericClass {} + /** * In-context test that assures the functionality tested in * {@link #testDefaultCoderAnnotationGeneric} is invoked in the right ways. diff --git a/sdks/java/core/src/test/java/org/apache/beam/sdk/values/TypedPValueTest.java b/sdks/java/core/src/test/java/org/apache/beam/sdk/values/TypedPValueTest.java index 0b7018a9b1ec..ba5dffbbbcee 100644 --- a/sdks/java/core/src/test/java/org/apache/beam/sdk/values/TypedPValueTest.java +++ b/sdks/java/core/src/test/java/org/apache/beam/sdk/values/TypedPValueTest.java @@ -76,8 +76,12 @@ public void testUntypedSideOutputTupleTagGivesActionableMessage() { thrown.expect(IllegalStateException.class); thrown.expectMessage("No Coder has been manually specified"); - thrown.expectMessage("erasure"); - thrown.expectMessage("see TupleTag Javadoc"); + thrown.expectMessage( + containsString("Building a Coder using a registered CoderFactory failed")); + thrown.expectMessage( + containsString("Building a Coder from the @DefaultCoder annotation failed")); + thrown.expectMessage( + containsString("Building a Coder from the fallback CoderProvider failed")); tuple.get(untypedSideOutputTag).getCoder(); } @@ -91,8 +95,12 @@ public void testStaticFactorySideOutputTupleTagGivesActionableMessage() { thrown.expect(IllegalStateException.class); thrown.expectMessage("No Coder has been manually specified"); - thrown.expectMessage("erasure"); - thrown.expectMessage("see TupleTag Javadoc"); + thrown.expectMessage( + containsString("Building a Coder using a registered CoderFactory failed")); + thrown.expectMessage( + containsString("Building a Coder from the @DefaultCoder annotation failed")); + thrown.expectMessage( + containsString("Building a Coder from the fallback CoderProvider failed")); tuple.get(untypedSideOutputTag).getCoder(); } diff --git a/sdks/java/java8tests/src/test/java/org/apache/beam/sdk/transforms/RemoveDuplicatesJava8Test.java b/sdks/java/java8tests/src/test/java/org/apache/beam/sdk/transforms/RemoveDuplicatesJava8Test.java index 93182291c241..aa4c01548c82 100644 --- a/sdks/java/java8tests/src/test/java/org/apache/beam/sdk/transforms/RemoveDuplicatesJava8Test.java +++ b/sdks/java/java8tests/src/test/java/org/apache/beam/sdk/transforms/RemoveDuplicatesJava8Test.java @@ -18,6 +18,7 @@ package org.apache.beam.sdk.transforms; import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; @@ -90,8 +91,13 @@ public void withLambdaRepresentativeValuesFnNoTypeDescriptorShouldThrow() { thrown.expect(IllegalStateException.class); thrown.expectMessage("Unable to return a default Coder for RemoveRepresentativeDupes"); - thrown.expectMessage("Cannot provide a coder for type variable K"); - thrown.expectMessage("the actual type is unknown due to erasure."); + thrown.expectMessage("No Coder has been manually specified"); + thrown.expectMessage( + containsString("Building a Coder using a registered CoderFactory failed")); + thrown.expectMessage( + containsString("Building a Coder from the @DefaultCoder annotation failed")); + thrown.expectMessage( + containsString("Building a Coder from the fallback CoderProvider failed")); // Thrown when applying a transform to the internal WithKeys that withRepresentativeValueFn is // implemented with diff --git a/sdks/java/java8tests/src/test/java/org/apache/beam/sdk/transforms/WithKeysJava8Test.java b/sdks/java/java8tests/src/test/java/org/apache/beam/sdk/transforms/WithKeysJava8Test.java index 1ffb1476eeb0..a89e281e6830 100644 --- a/sdks/java/java8tests/src/test/java/org/apache/beam/sdk/transforms/WithKeysJava8Test.java +++ b/sdks/java/java8tests/src/test/java/org/apache/beam/sdk/transforms/WithKeysJava8Test.java @@ -17,6 +17,8 @@ */ package org.apache.beam.sdk.transforms; +import static org.hamcrest.Matchers.containsString; + import org.apache.beam.sdk.testing.PAssert; import org.apache.beam.sdk.testing.RunnableOnService; import org.apache.beam.sdk.testing.TestPipeline; @@ -66,8 +68,13 @@ public void withLambdaAndNoTypeDescriptorShouldThrow() { thrown.expect(IllegalStateException.class); thrown.expectMessage("Unable to return a default Coder for ApplyKeysWithWithKeys"); - thrown.expectMessage("Cannot provide a coder for type variable K"); - thrown.expectMessage("the actual type is unknown due to erasure."); + thrown.expectMessage("No Coder has been manually specified"); + thrown.expectMessage( + containsString("Building a Coder using a registered CoderFactory failed")); + thrown.expectMessage( + containsString("Building a Coder from the @DefaultCoder annotation failed")); + thrown.expectMessage( + containsString("Building a Coder from the fallback CoderProvider failed")); p.run(); }