Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: DIREGAPIC initial implementation #746

Merged
merged 12 commits into from Jun 7, 2021

Conversation

vam-google
Copy link
Contributor

@vam-google vam-google commented Jun 2, 2021

Integration tests (compute_small) are not present in this commit, as they depend on #743 and #744. Also, as a prerequisite, at least a basic implementation of DIREGAPIC must be merged in gapic-generator-java, to integrate it with googleapis-discovery first (since integration test infra depends on the actual googleapis/googleapis-discovery targets). Please check vam-google@8983e23 to see how it would look like with compute integration tests not excluded.

compliance.proto is used as a basis for the REST composer tests. It was copied as is from showcase/compliance.proto.

Changes in WORKSPACE and repositories.bzl are necessary to make this repo work with gax-java 1.63.0 and above (gax-java vs gapic-generator-java java dependencies imports precedence). The other dependencies changes are either to bring deps in sync with the actual ones in googleapis, or to fix a specific import precedence issue.

I also added (in a form of bazel rules) a proto descriptor dumper and a runner from the dumped file (for debugging purposes). Not technically required here (but was very helpful for debugging purposes, so hopefully we can preserve it).

@vam-google vam-google requested review from miraleung and a team as code owners June 2, 2021 06:56
@google-cla google-cla bot added the cla: yes This human has signed the Contributor License Agreement. label Jun 2, 2021
@codecov
Copy link

codecov bot commented Jun 2, 2021

Codecov Report

Merging #746 (f0563bb) into master (72fa76f) will increase coverage by 0.35%.
The diff coverage is 92.84%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #746      +/-   ##
==========================================
+ Coverage   91.30%   91.66%   +0.35%     
==========================================
  Files         133      140       +7     
  Lines       13900    14697     +797     
  Branches     1032     1051      +19     
==========================================
+ Hits        12692    13472     +780     
- Misses        927      941      +14     
- Partials      281      284       +3     
Impacted Files Coverage Δ
.../google/api/generator/gapic/composer/Composer.java 10.11% <0.00%> (-2.57%) ⬇️
...n/AbstractServiceCallableFactoryClassComposer.java 100.00% <ø> (+16.42%) ⬆️
...erator/gapic/protoparser/PluginArgumentParser.java 51.61% <30.76%> (-17.96%) ⬇️
...google/api/generator/gapic/protoparser/Parser.java 43.21% <40.00%> (+0.10%) ⬆️
.../api/generator/gapic/composer/store/TypeStore.java 70.21% <50.00%> (-1.89%) ⬇️
...pi/generator/gapic/protoparser/HttpRuleParser.java 82.35% <81.08%> (-3.37%) ⬇️
...poser/common/AbstractServiceStubClassComposer.java 98.35% <87.50%> (+0.56%) ⬆️
...google/api/generator/gapic/model/HttpBindings.java 90.90% <90.90%> (ø)
...api/generator/gapic/composer/rest/RestContext.java 95.00% <95.00%> (ø)
.../composer/rest/ServiceClientTestClassComposer.java 97.39% <97.39%> (ø)
... and 20 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 72fa76f...f0563bb. Read the comment docs.

Copy link
Contributor

@miraleung miraleung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a first pass, will do a finer-grained review on the next one.

import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse;
import java.io.IOException;

public class MainDumper {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be really useful. Could we move this into a debug-only subpackage (to separate this from the main generator logic) and rename this class to something like GeneratorRequestDumper?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed from this PR, will add in a separate one, incorporating the PR feedback.

}

/** Register all extensions needed to process API protofiles. */
private static void registerAllExtensions(ExtensionRegistry extensionRegistry) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we're doing this in three places now, can we centralize this? We can have a minimal standalone class (e.g. in a generator.registry package) that has just this method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed from this PR, will add in a separate one, incorporating the PR feedback.

import java.io.InputStream;
import java.io.OutputStream;

public class MainFromFile {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the above comment, could we please move this into a debug-specific package and use a more descriptive name (e.g. GapicLibraryDumper?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed from this PR, will add in a separate one, incorporating the PR feedback.

import java.io.OutputStream;

public class MainFromFile {
public static void main(String[] args)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a usage example, same for the other debug class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed from this PR, will add in a separate one, incorporating the PR feedback.

BUILD.bazel Outdated
@@ -45,6 +45,32 @@ java_binary(
],
)

java_binary(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is independent of DIREGAPIC, could we please split this out into a separate PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed from this PR, will add in a separate one, incorporating the PR feedback.

private static Set<String> getHttpVerbPattern(HttpRule httpRule) {
String pattern = null;
// Assign a temp variable to prevent the formatter from removing the import.
private static String getPattern(HttpRule httpRule) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getHttpRulePattern or similar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess, originally it was called as getPattern, then in one of the recent PRs you renamed it to getHttpVerbPattern and on merge I overrode it back to getPattern. Renamed it to its recent updated name getHttpVerbPattern.

Sets.difference(inputMessageOpt.get().fieldMap().keySet(), bodyBinidngsUnion);
}

HttpRuleBindings.Builder httpBindings = HttpRuleBindings.builder();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can we use the chained builder pattern for consistency? e.g. builder().setFoo().set... .build().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sure. No idea why I used this style here. Refactored to inline return statement with chained builder.


HttpRuleBindings.Builder httpBindings = HttpRuleBindings.builder();
httpBindings.setHttpVerb(httpRule.getPatternCase().toString());
httpBindings.setPattern(pattern);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about a version of setPattern that takes a PatternCase? Then we can move getPattern into HttpRuleBindings, where it fits better anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, I think the whole parsing logic must be moved to HttpRuleBindings. I.e. the current architecture has a split between the class which simply contains the values (HttpRuleBindings, a simple POJO, javabean, whatever), and HttpRuleParser - one of potential classes, which knows how to populate HttpRuleBinding class from a HttpRule. So basically HttpRuleBindings class is detached from HttpRule per se, and may be populated from another source by some other sort of parser or manually. From my experience splitting this stuff into two classes (one contains values, the other one (or a set of, one for each source) knows how to populate those values from a source) usually works better in a long run (especially if a persistence layer is used, like a database, though this is irrelevant here). I can merge them, if you wish, though, I don't have a strong preference here.

@vam-google vam-google requested a review from miraleung June 4, 2021 04:41
…tes for existing integration tests. Will do that in next PR (the update of googleapis is needed for integration test for compute)
WORKSPACE Show resolved Hide resolved
@@ -127,12 +127,14 @@ def java_gapic_library(
service_yaml = None,
deps = [],
test_deps = [],
transport = None,
java_generator_name = "java_gapic",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SG, could we please add some documentation here? And since this is intended only for our use, could we please make this fail if the string does not match the generator or the dumpers' values?

private static final HttpJsonServiceStubClassComposer INSTANCE =
new HttpJsonServiceStubClassComposer();

protected static final TypeStore FIXED_REST_TYPESTORE = createStaticTypes();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant FIXED_REST_TYPESTORE, but I see now they're actually different. In that case, could we make this one private?

Expr returnExpr = null;
VariableExpr fieldsVarExpr = null;
Expr serializerExpr = null;
if (!extractorReturnType.isProtoPrimitiveType()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we please flip the if-blocks so the shorter one comes first?

Copy link
Contributor Author

@vam-google vam-google Jun 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, is there a best practice about this? conditional return/continue is preferred to go first but it is not quite the same as if-else block, after which method continues. Or is it about using not in if-else (as if else always covers both true and !true cases in any case) Well, anyways, flipped.

paramsPutArgs.add(requestBuilderExpr);

if (fieldsVarExpr == null) {
Expr paramsPutExpr =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps I'm missing something, but this looks the same as the if-block. Can we move this assignment out, and leave just the returnExpr / bodyExprs.add() logic inside?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess centennially they were different, as since one of them was missing setReturnType(), but the one with setReturnType matches both cases, so moved it out.

.setPattern("")
.setPathParameters(ImmutableSet.of())
.setQueryParameters(ImmutableSet.of())
.setBodyParameters(ImmutableSet.of());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, we probably shouldn't be able to instantiate an HttpRuleBindings at all (or we'd be able to set an empty pattern and verb with non-empty parameter lists). Could we do the following instead?

  • Make HttpRuleBindings Nullable on Method
  • Remove the empty string setters here, and add checks in build() to fail on invalid cases (i.e. empty string, pattern has no slashes and is not PubSub's _deleted-topic_, etc).
  • Consider making the verb an enum, or check that the string is one of the accepted five values in build(). (Would prefer the enum, since the latter is more error-prone.)

Context: Using rigorous validity checks has really helped me with development in this codebase. For instance, adding type-checking on assignment expressions or requiring set types on methods has helped me catch those errors at compile-time, so I think more rigid checks would help us here as well.

// HttpBinding pending dotted reference support.
public abstract List<String> httpBindings();
public abstract HttpRuleBindings httpBindings();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Continuing the comment above; Can we put a @Nullable on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really would rather not have nulls for things like this. Please check the other comments about HttpBindings. WDYT about renaming the HttpRuleBindings to just HttpBindings to make things clearer that this class is not strictly about the google.api.http option in proto files.

import java.util.Optional;
import java.util.Set;

public class RestTestProtoLoader extends TestProtoLoader {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Since all the classes are prefixed with HttpJson, should we do that here too for consistency?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was intentional, and as consistent as i could make it. The generated files are named HttpJson<Smth> because they generate HttpJson<Smth> so it would comply with naming pattern of composer-generated_class. For everything else, the "rest" is used for naming.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM.

@vam-google vam-google requested a review from miraleung June 5, 2021 00:25
Copy link
Contributor

@miraleung miraleung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving the HttpRuleBindings discussion as-is so we can discuss more next week.

@@ -127,12 +127,14 @@ def java_gapic_library(
service_yaml = None,
deps = [],
test_deps = [],
transport = None,
java_generator_name = "java_gapic",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, although some documentation would still be ideal.

Could you please check if the commits have been pushed? I'm still seeing the param without the leading underscore.

private static final ServiceStubSettingsClassComposer INSTANCE =
new ServiceStubSettingsClassComposer();

protected static final TypeStore FIXED_REST_TYPESTORE = createStaticTypes();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I would prefer this to be privately-scoped, since it's meant to be used just in this class (so it is not consistent with FIXED_TYPESTORE by nature).

@vam-google vam-google requested a review from miraleung June 5, 2021 02:38
Copy link
Contributor

@miraleung miraleung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with the following addressed:

import java.util.Optional;
import java.util.Set;

public class RestTestProtoLoader extends TestProtoLoader {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM.

@vam-google
Copy link
Contributor Author

vam-google commented Jun 7, 2021

@miraleung Thanks for the reveiw!

More detailed responses are at each specific comment, but briefly:

  • Flipped the if blocks
  • The blocks were a bit different, but the bigger one worked for both cases, so moved it out as requested.
  • find/replacing it, I did not acutually replace the one, from which all started =). Fixed.
  • Intentional, to avoid NullPointer and to avoid duplicating NullPointer check here and in autovalue generated class.
  • Intentional, as it would be redundant, since the check is already done at the beginning of the whole method.

@vam-google vam-google requested a review from miraleung June 7, 2021 07:32
@vam-google
Copy link
Contributor Author

@miraleung PTAL

Copy link
Contributor

@miraleung miraleung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with commented-out code removed.

FIXED_REST_TYPESTORE.get(ProtoMessageRequestFormatter.class.getSimpleName()))
.setMethodName("newBuilder")
.setGenerics(Collections.singletonList(protoMethod.inputType().reference()))
// .setArguments(Arrays.asList(m))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Remove?

@vam-google vam-google merged commit 81f6737 into googleapis:master Jun 7, 2021
suztomo pushed a commit that referenced this pull request Mar 21, 2023
🤖 I have created a release *beep* *boop*
---


## [3.0.0](googleapis/java-shared-dependencies@v2.13.0...v3.0.0) (2022-07-29)


### Bug Fixes

* enable longpaths support for windows test ([#1485](https://github.com/googleapis/java-shared-dependencies/issues/1485)) ([#738](googleapis/java-shared-dependencies#738)) ([48b157d](googleapis/java-shared-dependencies@48b157d))


### Dependencies

* update dependency com.google.api-client:google-api-client-bom to v1.35.2 ([#729](googleapis/java-shared-dependencies#729)) ([d518319](googleapis/java-shared-dependencies@d518319))
* update dependency com.google.api-client:google-api-client-bom to v2 ([#746](googleapis/java-shared-dependencies#746)) ([ef2b57a](googleapis/java-shared-dependencies@ef2b57a))
* update dependency com.google.api.grpc:grpc-google-common-protos to v2.9.2 ([#741](googleapis/java-shared-dependencies#741)) ([347269f](googleapis/java-shared-dependencies@347269f))
* update dependency com.google.auth:google-auth-library-bom to v1.8.0 ([#726](googleapis/java-shared-dependencies#726)) ([236bbb3](googleapis/java-shared-dependencies@236bbb3))
* update dependency com.google.auth:google-auth-library-bom to v1.8.1 ([#742](googleapis/java-shared-dependencies#742)) ([dabdbdf](googleapis/java-shared-dependencies@dabdbdf))
* update dependency com.google.cloud:first-party-dependencies to v2 ([#747](googleapis/java-shared-dependencies#747)) ([93b1ed8](googleapis/java-shared-dependencies@93b1ed8))
* update dependency com.google.cloud:grpc-gcp to v1.2.1 ([#751](googleapis/java-shared-dependencies#751)) ([618b00c](googleapis/java-shared-dependencies@618b00c))
* update dependency com.google.cloud:third-party-dependencies to v2 ([#748](googleapis/java-shared-dependencies#748)) ([afca3fd](googleapis/java-shared-dependencies@afca3fd))
* update dependency com.google.http-client:google-http-client-bom to v1.42.1 ([#730](googleapis/java-shared-dependencies#730)) ([4fdaad8](googleapis/java-shared-dependencies@4fdaad8))
* update dependency com.google.http-client:google-http-client-bom to v1.42.2 ([#749](googleapis/java-shared-dependencies#749)) ([68a82f4](googleapis/java-shared-dependencies@68a82f4))
* update dependency com.google.protobuf:protobuf-bom to v3.21.2 ([#722](googleapis/java-shared-dependencies#722)) ([68f570e](googleapis/java-shared-dependencies@68f570e))
* update dependency com.google.protobuf:protobuf-bom to v3.21.3 ([#756](googleapis/java-shared-dependencies#756)) ([7429507](googleapis/java-shared-dependencies@7429507))
* update dependency com.google.protobuf:protobuf-bom to v3.21.4 ([#759](googleapis/java-shared-dependencies#759)) ([f033db0](googleapis/java-shared-dependencies@f033db0))
* update dependency io.grpc:grpc-bom to v1.48.0 ([#752](googleapis/java-shared-dependencies#752)) ([9678d52](googleapis/java-shared-dependencies@9678d52))
* update dependency org.checkerframework:checker-qual to v3.23.0 ([#736](googleapis/java-shared-dependencies#736)) ([816d380](googleapis/java-shared-dependencies@816d380))
* update gax.version to v2.18.3 ([#731](googleapis/java-shared-dependencies#731)) ([5bbf1e1](googleapis/java-shared-dependencies@5bbf1e1))
* update gax.version to v2.18.4 ([#735](googleapis/java-shared-dependencies#735)) ([5161c6e](googleapis/java-shared-dependencies@5161c6e))
* update gax.version to v2.18.5 ([#758](googleapis/java-shared-dependencies#758)) ([608e040](googleapis/java-shared-dependencies@608e040))
* update gax.version to v2.18.6 ([#763](googleapis/java-shared-dependencies#763)) ([84b81e9](googleapis/java-shared-dependencies@84b81e9))
* update google.common-protos.version to v2.9.1 ([#724](googleapis/java-shared-dependencies#724)) ([62cd59a](googleapis/java-shared-dependencies@62cd59a))
* update google.core.version to v2.8.1 ([#725](googleapis/java-shared-dependencies#725)) ([d47af56](googleapis/java-shared-dependencies@d47af56))
* update google.core.version to v2.8.3 ([#760](googleapis/java-shared-dependencies#760)) ([33e38dc](googleapis/java-shared-dependencies@33e38dc))
* update google.core.version to v2.8.4 ([#762](googleapis/java-shared-dependencies#762)) ([5410450](googleapis/java-shared-dependencies@5410450))
* update google.core.version to v2.8.5 ([#764](googleapis/java-shared-dependencies#764)) ([4bc8c75](googleapis/java-shared-dependencies@4bc8c75))
* update iam.version to v1.5.0 ([#732](googleapis/java-shared-dependencies#732)) ([3e64541](googleapis/java-shared-dependencies@3e64541))
* update iam.version to v1.5.1 ([#737](googleapis/java-shared-dependencies#737)) ([5a85115](googleapis/java-shared-dependencies@5a85115))
* update iam.version to v1.5.2 ([#743](googleapis/java-shared-dependencies#743)) ([294ea85](googleapis/java-shared-dependencies@294ea85))

---
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants