use of org.apache.beam.sdk.coders.CannotProvideCoderException in project beam by apache.
the class Create method getDefaultCreateCoder.
private static <T> Coder<T> getDefaultCreateCoder(CoderRegistry registry, Iterable<T> elems) throws CannotProvideCoderException {
checkArgument(!Iterables.isEmpty(elems), "Can not determine a default Coder for a 'Create' PTransform that " + "has no elements. Either add elements, call Create.empty(Coder)," + " Create.empty(TypeDescriptor), or call 'withCoder(Coder)' or " + "'withType(TypeDescriptor)' on the PTransform.");
// First try to deduce a coder using the types of the elements.
Class<?> elementClazz = Void.class;
for (T elem : elems) {
if (elem == null) {
continue;
}
Class<?> clazz = elem.getClass();
if (elementClazz.equals(Void.class)) {
elementClazz = clazz;
} else if (!elementClazz.equals(clazz)) {
// Elements are not the same type, require a user-specified coder.
throw new CannotProvideCoderException(String.format("Cannot provide coder for %s: The elements are not all of the same class.", Create.class.getSimpleName()));
}
}
if (elementClazz.getTypeParameters().length == 0) {
try {
// elementClazz is a wildcard type
@SuppressWarnings("unchecked") Coder<T> coder = (Coder<T>) registry.getCoder(TypeDescriptor.of(elementClazz));
return coder;
} catch (CannotProvideCoderException exc) {
// Can't get a coder from the class of the elements, try with the elements next
}
}
// If that fails, try to deduce a coder using the elements themselves
return (Coder<T>) inferCoderFromObjects(registry, elems);
}
use of org.apache.beam.sdk.coders.CannotProvideCoderException in project beam by apache.
the class PCollection method inferCoderOrFail.
/**
* If the coder is not explicitly set, this sets the coder for this {@link PCollection} to the
* best coder that can be inferred based upon the known {@link TypeDescriptor}. By default, this
* is null, but can and should be improved by subclasses.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private CoderOrFailure<T> inferCoderOrFail(PInput input, PTransform<?, ?> transform, CoderRegistry registry) {
// First option for a coder: use the Coder set on this PValue.
if (coderOrFailure.coder != null) {
return coderOrFailure;
}
// Second option for a coder: use the default Coder from the producing PTransform.
CannotProvideCoderException inputCoderException;
try {
return new CoderOrFailure<>(((PTransform) transform).getDefaultOutputCoder(input, this), null);
} catch (CannotProvideCoderException exc) {
inputCoderException = exc;
}
// Third option for a coder: Look in the coder registry.
TypeDescriptor<T> token = getTypeDescriptor();
CannotProvideCoderException inferFromTokenException = null;
if (token != null) {
try {
return new CoderOrFailure<>(registry.getCoder(token), null);
} catch (CannotProvideCoderException exc) {
inferFromTokenException = exc;
// and the error message itself.
if (transform instanceof ParDo.MultiOutput && exc.getReason() == ReasonCode.TYPE_ERASURE) {
inferFromTokenException = new CannotProvideCoderException(exc.getMessage() + " If this error occurs for an output of the producing ParDo, verify that the " + "TupleTag for this output is constructed with proper type information (see " + "TupleTag Javadoc) or explicitly set the Coder to use if this is not possible.");
}
}
}
// Build up the error message and list of causes.
StringBuilder messageBuilder = new StringBuilder().append("Unable to return a default Coder for ").append(this).append(". Correct one of the following root causes:");
// No exception, but give the user a message about .setCoder() has not been called.
messageBuilder.append("\n No Coder has been manually specified; ").append(" you may do so using .setCoder().");
if (inferFromTokenException != null) {
messageBuilder.append("\n Inferring a Coder from the CoderRegistry failed: ").append(inferFromTokenException.getMessage());
}
if (inputCoderException != null) {
messageBuilder.append("\n Using the default output Coder from the producing PTransform failed: ").append(inputCoderException.getMessage());
}
// Build and throw the exception.
return new CoderOrFailure<>(null, messageBuilder.toString());
}
use of org.apache.beam.sdk.coders.CannotProvideCoderException in project beam by apache.
the class WithKeys method expand.
@Override
public PCollection<KV<K, V>> expand(PCollection<V> in) {
PCollection<KV<K, V>> result = in.apply("AddKeys", MapElements.via(new SimpleFunction<V, KV<K, V>>() {
@Override
public KV<K, V> apply(V element) {
return KV.of(fn.apply(element), element);
}
}));
try {
Coder<K> keyCoder;
CoderRegistry coderRegistry = in.getPipeline().getCoderRegistry();
if (keyClass == null) {
keyCoder = coderRegistry.getOutputCoder(fn, in.getCoder());
} else {
keyCoder = coderRegistry.getCoder(TypeDescriptor.of(keyClass));
}
// TODO: Remove when we can set the coder inference context.
result.setCoder(KvCoder.of(keyCoder, in.getCoder()));
} catch (CannotProvideCoderException exc) {
// let lazy coder inference have a try
}
return result;
}
use of org.apache.beam.sdk.coders.CannotProvideCoderException in project beam by apache.
the class ParDo method codersForStateSpecTypes.
/**
* Try to provide coders for as many of the type arguments of given
* {@link DoFnSignature.StateDeclaration} as possible.
*/
private static <InputT> Coder[] codersForStateSpecTypes(DoFnSignature.StateDeclaration stateDeclaration, CoderRegistry coderRegistry, Coder<InputT> inputCoder) {
Type stateType = stateDeclaration.stateType().getType();
if (!(stateType instanceof ParameterizedType)) {
// No type arguments means no coders to infer.
return new Coder[0];
}
Type[] typeArguments = ((ParameterizedType) stateType).getActualTypeArguments();
Coder[] coders = new Coder[typeArguments.length];
for (int i = 0; i < typeArguments.length; i++) {
Type typeArgument = typeArguments[i];
TypeDescriptor<?> typeDescriptor = TypeDescriptor.of(typeArgument);
try {
coders[i] = coderRegistry.getCoder(typeDescriptor);
} catch (CannotProvideCoderException e) {
try {
coders[i] = coderRegistry.getCoder(typeDescriptor, inputCoder.getEncodedTypeDescriptor(), inputCoder);
} catch (CannotProvideCoderException ignored) {
// Since not all type arguments will have a registered coder we ignore this exception.
}
}
}
return coders;
}
use of org.apache.beam.sdk.coders.CannotProvideCoderException in project beam by apache.
the class KafkaIO method inferCoder.
/**
* Attempt to infer a {@link Coder} by extracting the type of the deserialized-class from the
* deserializer argument using the {@link Coder} registry.
*/
@VisibleForTesting
static <T> NullableCoder<T> inferCoder(CoderRegistry coderRegistry, Class<? extends Deserializer<T>> deserializer) {
checkNotNull(deserializer);
for (Type type : deserializer.getGenericInterfaces()) {
if (!(type instanceof ParameterizedType)) {
continue;
}
// This does not recurse: we will not infer from a class that extends
// a class that extends Deserializer<T>.
ParameterizedType parameterizedType = (ParameterizedType) type;
if (parameterizedType.getRawType() == Deserializer.class) {
Type parameter = parameterizedType.getActualTypeArguments()[0];
@SuppressWarnings("unchecked") Class<T> clazz = (Class<T>) parameter;
try {
return NullableCoder.of(coderRegistry.getCoder(clazz));
} catch (CannotProvideCoderException e) {
throw new RuntimeException(String.format("Unable to automatically infer a Coder for " + "the Kafka Deserializer %s: no coder registered for type %s", deserializer, clazz));
}
}
}
throw new RuntimeException(String.format("Could not extract the Kafka Deserializer type from %s", deserializer));
}
Aggregations