Skip to content

Commit fe5f9c2

Browse files
sclukas77Scott Lukas
andauthored
[BEAM-10629] Added KnownBuilderInstances to ExternalTransformRegistrar (#12454)
Co-authored-by: Scott Lukas <slukas@google.com>
1 parent 6612b24 commit fe5f9c2

File tree

2 files changed

+53
-36
lines changed

2 files changed

+53
-36
lines changed

sdks/java/core/src/main/java/org/apache/beam/sdk/expansion/ExternalTransformRegistrar.java

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717
*/
1818
package org.apache.beam.sdk.expansion;
1919

20+
import java.lang.reflect.Constructor;
2021
import java.util.Map;
22+
import java.util.Map.Entry;
2123
import org.apache.beam.sdk.annotations.Experimental;
2224
import org.apache.beam.sdk.annotations.Experimental.Kind;
2325
import org.apache.beam.sdk.transforms.ExternalTransformBuilder;
26+
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Preconditions;
27+
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.ImmutableMap;
2428

2529
/**
2630
* A registrar which contains a mapping from URNs to available {@link ExternalTransformBuilder}s.
@@ -29,6 +33,42 @@
2933
@Experimental(Kind.PORTABILITY)
3034
public interface ExternalTransformRegistrar {
3135

32-
/** A mapping from URN to an {@link ExternalTransformBuilder} class. */
33-
Map<String, Class<? extends ExternalTransformBuilder<?, ?, ?>>> knownBuilders();
36+
/**
37+
* A mapping from URN to an {@link ExternalTransformBuilder} class.
38+
*
39+
* @deprecated Prefer implementing 'knownBuilderInstances'. This method will be removed in a
40+
* future version of Beam.
41+
*/
42+
@Deprecated
43+
default Map<String, Class<? extends ExternalTransformBuilder<?, ?, ?>>> knownBuilders() {
44+
return ImmutableMap.<String, Class<? extends ExternalTransformBuilder<?, ?, ?>>>builder()
45+
.build();
46+
}
47+
48+
/** A mapping from URN to an {@link ExternalTransformBuilder} instance. */
49+
default Map<String, ExternalTransformBuilder<?, ?, ?>> knownBuilderInstances() {
50+
ImmutableMap.Builder builder = ImmutableMap.<String, ExternalTransformBuilder>builder();
51+
Map<String, Class<? extends ExternalTransformBuilder<?, ?, ?>>> knownBuilders = knownBuilders();
52+
for (Entry<String, Class<? extends ExternalTransformBuilder<?, ?, ?>>> knownBuilder :
53+
knownBuilders.entrySet()) {
54+
Preconditions.checkState(
55+
ExternalTransformBuilder.class.isAssignableFrom(knownBuilder.getValue()),
56+
"Provided identifier %s is not an ExternalTransformBuilder.",
57+
knownBuilder.getValue().getName());
58+
try {
59+
Constructor<? extends ExternalTransformBuilder> constructor =
60+
knownBuilder.getValue().getDeclaredConstructor();
61+
62+
constructor.setAccessible(true);
63+
builder.put(knownBuilder.getKey(), constructor.newInstance());
64+
65+
} catch (RuntimeException e) {
66+
throw e;
67+
} catch (Exception e) {
68+
throw new RuntimeException(
69+
"Unable to instantiate ExternalTransformBuilder from constructor.");
70+
}
71+
}
72+
return builder.build();
73+
}
3474
}

sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/ExpansionService.java

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222

2323
import com.google.auto.service.AutoService;
2424
import java.io.IOException;
25-
import java.lang.reflect.Constructor;
2625
import java.lang.reflect.Method;
2726
import java.util.ArrayDeque;
2827
import java.util.Collections;
@@ -107,39 +106,39 @@ public Map<String, ExpansionService.TransformProvider> knownTransforms() {
107106
ImmutableMap.builder();
108107
for (ExternalTransformRegistrar registrar :
109108
ServiceLoader.load(ExternalTransformRegistrar.class)) {
110-
for (Map.Entry<String, Class<? extends ExternalTransformBuilder<?, ?, ?>>> entry :
111-
registrar.knownBuilders().entrySet()) {
109+
for (Map.Entry<String, ExternalTransformBuilder<?, ?, ?>> entry :
110+
registrar.knownBuilderInstances().entrySet()) {
112111
String urn = entry.getKey();
113-
Class<? extends ExternalTransformBuilder<?, ?, ?>> builderClass = entry.getValue();
112+
ExternalTransformBuilder builderInstance = entry.getValue();
114113
builder.put(
115114
urn,
116115
spec -> {
117116
try {
118117
ExternalTransforms.ExternalConfigurationPayload payload =
119118
ExternalTransforms.ExternalConfigurationPayload.parseFrom(spec.getPayload());
120-
return translate(payload, builderClass);
119+
return builderInstance.buildExternal(
120+
payloadToConfig(
121+
payload,
122+
(Class<? extends ExternalTransformBuilder<?, ?, ?>>)
123+
builderInstance.getClass()));
121124
} catch (Exception e) {
122125
throw new RuntimeException(
123126
String.format("Failed to build transform %s from spec %s", urn, spec), e);
124127
}
125128
});
126129
}
127130
}
131+
128132
return builder.build();
129133
}
130134

131-
private static PTransform<?, ?> translate(
135+
Object payloadToConfig(
132136
ExternalTransforms.ExternalConfigurationPayload payload,
133137
Class<? extends ExternalTransformBuilder<?, ?, ?>> builderClass)
134138
throws Exception {
135-
Preconditions.checkState(
136-
ExternalTransformBuilder.class.isAssignableFrom(builderClass),
137-
"Provided identifier %s is not an ExternalTransformBuilder.",
138-
builderClass.getName());
139-
140139
Object configObject = initConfiguration(builderClass);
141140
populateConfiguration(configObject, payload);
142-
return buildTransform(builderClass, configObject);
141+
return configObject;
143142
}
144143

145144
private static Object initConfiguration(
@@ -239,28 +238,6 @@ private static RunnerApi.Coder buildProto(
239238

240239
return coderBuilder.build();
241240
}
242-
243-
private static PTransform<?, ?> buildTransform(
244-
Class<? extends ExternalTransformBuilder<?, ?, ?>> builderClass, Object configObject)
245-
throws Exception {
246-
Constructor<? extends ExternalTransformBuilder<?, ?, ?>> constructor =
247-
builderClass.getDeclaredConstructor();
248-
constructor.setAccessible(true);
249-
ExternalTransformBuilder<?, ?, ?> externalTransformBuilder = constructor.newInstance();
250-
Method buildMethod = builderClass.getMethod("buildExternal", configObject.getClass());
251-
buildMethod.setAccessible(true);
252-
253-
PTransform<?, ?> transform =
254-
(PTransform<?, ?>)
255-
checkArgumentNotNull(
256-
buildMethod.invoke(externalTransformBuilder, configObject),
257-
"Invoking %s.%s(%s) returned null, violating its type.",
258-
builderClass.getCanonicalName(),
259-
"buildExternal",
260-
configObject);
261-
262-
return transform;
263-
}
264241
}
265242

266243
/**

0 commit comments

Comments
 (0)