-
Notifications
You must be signed in to change notification settings - Fork 129
feat: REST GAPIC (REGAPIC) Support for Java #3275
Changes from all commits
7666bdf
59c36da
45022ca
7b32072
e2b56c0
0bae1fc
676b82c
63d4e38
0f4eee3
4395976
3157ca5
6045612
9219acf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,6 +78,7 @@ def java_gapic_srcjar( | |
package = None, | ||
service_yaml = None, | ||
grpc_service_config = None, | ||
transport = None, | ||
**kwargs): | ||
raw_srcjar_name = "%s_raw" % name | ||
|
||
|
@@ -90,6 +91,7 @@ def java_gapic_srcjar( | |
language = "java", | ||
package = package, | ||
grpc_service_config = grpc_service_config, | ||
transport = transport, | ||
**kwargs | ||
) | ||
|
||
|
@@ -132,6 +134,7 @@ def java_gapic_library( | |
package = None, | ||
gen_resource_name = True, | ||
grpc_service_config = None, | ||
transport = None, | ||
deps = [], | ||
test_deps = [], | ||
**kwargs): | ||
|
@@ -144,6 +147,7 @@ def java_gapic_library( | |
artifact_type = "GAPIC_CODE", | ||
package = package, | ||
grpc_service_config = grpc_service_config, | ||
transport = transport, | ||
**kwargs | ||
) | ||
|
||
|
@@ -162,10 +166,7 @@ def java_gapic_library( | |
"@com_google_protobuf//:protobuf_java", | ||
"@com_google_api_api_common//jar", | ||
"@com_google_api_gax_java//gax:gax", | ||
"@com_google_api_gax_java//gax-grpc:gax_grpc", | ||
"@com_google_guava_guava//jar", | ||
"@io_grpc_grpc_java//core:core", | ||
"@io_grpc_grpc_java//protobuf:protobuf", | ||
"@com_google_code_findbugs_jsr305//jar", | ||
"@org_threeten_threetenbp//jar", | ||
"@io_opencensus_opencensus_api//jar", | ||
|
@@ -175,6 +176,17 @@ def java_gapic_library( | |
"@javax_annotation_javax_annotation_api//jar", | ||
] | ||
|
||
if transport == "rest": | ||
actual_deps += [ | ||
"@com_google_api_gax_java//gax-httpjson:gax_httpjson", | ||
] | ||
else: | ||
actual_deps += [ | ||
"@com_google_api_gax_java//gax-grpc:gax_grpc", | ||
"@io_grpc_grpc_java//core:core", | ||
"@io_grpc_grpc_java//protobuf:protobuf", | ||
] | ||
|
||
native.java_library( | ||
name = name, | ||
srcs = [":%s.srcjar" % srcjar_name], | ||
|
@@ -183,16 +195,24 @@ def java_gapic_library( | |
) | ||
|
||
actual_test_deps = test_deps + [ | ||
"@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", | ||
"@com_google_api_gax_java//gax:gax_testlib", | ||
"@com_google_code_gson_gson//jar", | ||
"@io_grpc_grpc_java//auth:auth", | ||
"@io_grpc_grpc_netty_shaded//jar", | ||
"@io_grpc_grpc_java//stub:stub", | ||
"@io_opencensus_opencensus_contrib_grpc_metrics//jar", | ||
"@junit_junit//jar", | ||
] | ||
|
||
if transport == "rest": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment above. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please lets keep it simple, not trying to support in the rules something which is not supported in the generator itself. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I fully agree with YAGNI, but I think the structure I propose is only a hair less simple and makes this part just work, increasing clarity. |
||
actual_test_deps += [ | ||
"@com_google_api_gax_java//gax-httpjson:gax_httpjson_testlib", | ||
] | ||
else: | ||
actual_test_deps += [ | ||
"@com_google_api_gax_java//gax-grpc:gax_grpc_testlib", | ||
"@io_grpc_grpc_java//auth:auth", | ||
"@io_grpc_grpc_netty_shaded//jar", | ||
"@io_grpc_grpc_java//stub:stub", | ||
"@io_opencensus_opencensus_contrib_grpc_metrics//jar", | ||
] | ||
|
||
native.java_library( | ||
name = "%s_test" % name, | ||
srcs = [":%s-test.srcjar" % srcjar_name], | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -160,6 +160,7 @@ def java_gapic_assembly_gradle_pkg( | |
name, | ||
deps, | ||
assembly_name = None, | ||
transport = None, | ||
**kwargs): | ||
package_dir = name | ||
if assembly_name: | ||
|
@@ -206,9 +207,14 @@ def java_gapic_assembly_gradle_pkg( | |
grpc_target_dep = ["%s" % grpc_target] | ||
|
||
if client_deps: | ||
if transport == "rest": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would use a similar construct to above to get all the transports, and then be explicit about the special casing if we're not yet generating multi-transport GAPICs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was aiming to have the interface (the rules) have the desired surface, and then provide stubs for what is not implemented (ie dual transport fails for now) |
||
template_label = Label("//rules_gapic/java:resources/gradle/client_disco.gradle.tmpl") | ||
else: | ||
vchudnov-g marked this conversation as resolved.
Show resolved
Hide resolved
|
||
template_label = Label("//rules_gapic/java:resources/gradle/client.gradle.tmpl") | ||
|
||
_java_gapic_gradle_pkg( | ||
name = client_target, | ||
template_label = Label("//rules_gapic/java:resources/gradle/client.gradle.tmpl"), | ||
template_label = template_label, | ||
deps = proto_target_dep + client_deps, | ||
test_deps = grpc_target_dep + client_test_deps, | ||
**kwargs | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -149,6 +149,17 @@ public class GeneratorMain { | |
.argName("GRPC-SERVICE-CONFIG") | ||
.required(false) | ||
.build(); | ||
private static final Option TRANSPORT = | ||
Option.builder() | ||
.longOpt("transport") | ||
.desc( | ||
"List of transports to support. Valid transport names ('grpc' or 'rest') are" | ||
+ " separated by '+'. Default is 'grpc'. NOTE: for now, GAPICs support only" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment as phrased makes sense with the code changes I suggested in the last pass, where (a) the default list is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please update the comment if you're not handling the list option: you're not handling the "+" separated list unless you make changes like the ones I suggested,. |
||
+ " the first transport in the list.") | ||
.hasArg() | ||
.argName("TRANSPORT") | ||
.required(false) | ||
.build(); | ||
|
||
public static void printAvailableCommands() { | ||
System.err.println(" Available artifact types:"); | ||
|
@@ -249,6 +260,7 @@ public static void gapicGeneratorMain(ArtifactType artifactType, String[] args) | |
options.addOption(OUTPUT_OPTION); | ||
options.addOption(SAMPLE_YAML_NONREQUIRED_OPTION); | ||
options.addOption(GRPC_SERVICE_CONFIG_OPTION); | ||
options.addOption(TRANSPORT); | ||
Option enabledArtifactsOption = | ||
Option.builder() | ||
.longOpt("enabled_artifacts") | ||
|
@@ -299,6 +311,9 @@ public static void gapicGeneratorMain(ArtifactType artifactType, String[] args) | |
|
||
checkFile(toolOptions.get(ToolOptions.DESCRIPTOR_SET)); | ||
|
||
if (cl.getOptionValue(TRANSPORT.getLongOpt()) != null) { | ||
toolOptions.set(GapicGeneratorApp.TRANSPORT, cl.getOptionValue(TRANSPORT.getLongOpt())); | ||
} | ||
if (cl.getOptionValues(SERVICE_YAML_NONREQUIRED_OPTION.getLongOpt()) != null) { | ||
toolOptions.set( | ||
ToolOptions.CONFIG_FILES, | ||
|
@@ -346,6 +361,7 @@ public static ToolOptions createCodeGeneratorOptionsFromProtoc(String[] args) | |
options.addOption(DESCRIPTOR_SET_OPTION); | ||
options.addOption(LANGUAGE_OPTION); | ||
options.addOption(TARGET_API_PROTO_PACKAGE); | ||
options.addOption(TRANSPORT); | ||
|
||
CommandLine cl = (new DefaultParser()).parse(options, args); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ | |
import com.google.api.codegen.config.GapicProductConfig; | ||
import com.google.api.codegen.config.PackageMetadataConfig; | ||
import com.google.api.codegen.config.PackagingConfig; | ||
import com.google.api.codegen.config.TransportProtocol; | ||
import com.google.api.codegen.grpc.ServiceConfig; | ||
import com.google.api.codegen.samplegen.v1p2.SampleConfigProto; | ||
import com.google.api.codegen.util.MultiYamlReader; | ||
|
@@ -112,6 +113,14 @@ public class GapicGeneratorApp extends ToolDriverBase { | |
"The filepath of the JSON gRPC Service Config file.", | ||
""); | ||
|
||
public static final Option<String> TRANSPORT = | ||
ToolOptions.createOption( | ||
String.class, | ||
"transport", | ||
"List of transports to use ('rest' or 'grpc') separated by '+'. NOTE: For now" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this just be "Transport to use" since it's not a List option? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But you can list more than one, separated by "+". It's a string representation of a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, change the NOTE to be accurate: for now, we only support a single transport. |
||
+ " we only support the first transport in the list.", | ||
"grpc"); | ||
|
||
private ArtifactType artifactType; | ||
|
||
private final GapicWriter gapicWriter; | ||
|
@@ -208,6 +217,16 @@ protected void process() throws Exception { | |
} | ||
|
||
String clientPackage = Strings.emptyToNull(options.get(CLIENT_PACKAGE)); | ||
String transport = options.get(TRANSPORT).toLowerCase(); | ||
|
||
TransportProtocol tp; | ||
if (transport.equals("grpc")) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use a construct like I suggested for the Bazel file, taking just the first element in the transport list (with a TODO that this is not the intended ultimate behavior). Let's also add a TODO that when we do support multiple transports, we'll have to change the code below. (If we were to do it in the monolith, what would be your approach? Having multiple There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, lets keep it as is. It is very unlikely that we will ever support multiple transports in the monolith. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. My own preference, as I said above, is to have the right outer structure and just stubs for the unimplemented parts (ie multi-transport). It's just as simple and clearer. But I feel more strongly about it in the outermost surface (Bazel) than in the generator. |
||
tp = TransportProtocol.GRPC; | ||
} else if (transport.equals("rest")) { | ||
tp = TransportProtocol.HTTP; | ||
} else { | ||
throw new IllegalArgumentException("Unknown transport protocol: " + transport); | ||
} | ||
|
||
GapicProductConfig productConfig = | ||
GapicProductConfig.create( | ||
|
@@ -217,7 +236,8 @@ protected void process() throws Exception { | |
protoPackage, | ||
clientPackage, | ||
language, | ||
gRPCServiceConfig); | ||
gRPCServiceConfig, | ||
tp); | ||
if (productConfig == null) { | ||
ToolUtil.reportDiags(model.getDiagReporter().getDiagCollector(), true); | ||
return; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about doing these additively?
If you don't want to support rest+grpc for now, in #[1] you can add
all_transports = all_transports[0:1] # TODO: remove when we generate multi-transport GAPIC
(Maybe you can factor out #[1] and #[2] into a helper function, since this conditional appears another time below.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to keep it backward-compatible with the older version of the rules, when no transport argument meant grpc. If the implementation of gapic generator does not support rest+grpc I don't think it makes much sense to support that in the rules. The current implementation is both backward compatible and the simplest I could come up with. Doing removal would mean that
rest+grpc
andgrpc+rest
"rest" only which is confusing and more complicated behavior.Note, it is very unlikely that grpc+rest will ever be implemented in monolith. This is the main reason why the rest of this implementation avoids going into complications of grpc+rest support (including bazel rules or command line args parsing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to backwards-compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code I suggest above is backwards-compatible (if you include the line I suggest for #[1]). It does everything your existing code does, but makes it clear that the intent is to support both protocols eventually. The line I suggest for #[1] above makes it clear that dual protocols are not supported yet (and as you say, may never be in the monolith).
I strongly urge you to consider this because it's only a hair less simple than what you have now and it makes the project intention very clear by putting in the structure that we would have in a full implementation. In my experience, this is a good principle because of that clarity and because it diminishes the technical debt should, say, the monolith be in use longer than we're planning now.
(I'm not going to block on this, but do consider it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, all this is essentially a throw away code, because the final destination of it will be in java microgenerator. Please lets not try to polish throwaway code or add features which most likely will never be fully implemented here (like the http+grpc option).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a very simple change that increases clarity, IMO. My preference would be to add it. But as I said, I'm not going to block on this.