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

Enforce REQUIRED annotations via API call signatures #861

Open
sinelaw opened this issue Oct 19, 2021 · 9 comments
Open

Enforce REQUIRED annotations via API call signatures #861

sinelaw opened this issue Oct 19, 2021 · 9 comments
Labels
priority: p3 Desirable enhancement or fix. May not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. type: question Request for information or clarification. Not an issue.

Comments

@sinelaw
Copy link

sinelaw commented Oct 19, 2021

Problem:

When a field is annotated as REQUIRED, the API allows constructing objects without specifying explicitly the value of the required field.

Example:

import "google/api/field_behavior.proto";

message Child { ... }

message Parent {
  Child child = 1 [
    (google.api.field_behavior) = REQUIRED
  ];
}

The Parent will generate a Builder that has a setChild() method, but there's no compile-time way to check that this setter was called. So it's possible to write code that constructs "bad" messages which will only be manifest at runtime.

Describe the solution you'd like

Positional arguments for required fields. In the example above, to get a Parent Builder (or to create a Parent in some other way) your only option would be to call a method that requires a Child as a parameter.

To preserve the existing API, this feature could be placed behind a flag / option for the proto generator.

Describe alternatives you've considered

Don't think there's an alternative besides changing how code is generated.

Thanks!

@sinelaw sinelaw added priority: p3 Desirable enhancement or fix. May not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. labels Oct 19, 2021
@noahdietz
Copy link
Contributor

Based on discussion in answer to yaqs/3650180692123320320.

@chanseokoh
Copy link
Contributor

chanseokoh commented Oct 19, 2021

@noahdietz the yaqs link is broken. Nvm, it works when prefixed with a protocol.

@noahdietz
Copy link
Contributor

@noahdietz the yaqs link is broken.

It works for me. If you are expecting it to be hyperlinked, I intentionally did not do that.

@chanseokoh
Copy link
Contributor

chanseokoh commented Oct 26, 2021

Gone through the yaqs discussion. Enforcing this is a breaking change to the Java API surface, so it's unlikely that we do this for existing protos.

But more importantly, as hinted in the discussion, it is debatable that enforcing this is the right thing to do; not supplying a REQUIRED filed will make proto supply the default value, which may work well and be actually intended in most cases. For example, a backend API service annotation a boolean field with REQUIRED, indicating that the backend will read the value out of it. However, the default value when not supplied by the user is false, and the intention may be to make user set it to true only in some specific cases.

@chanseokoh chanseokoh added the type: question Request for information or clarification. Not an issue. label Oct 26, 2021
@sinelaw
Copy link
Author

sinelaw commented Oct 27, 2021

@chanseokoh -

Regarding breaking the Java API surface - we can require an option/flag to enable the new API (and maybe one day deprecate the old one), so existing code will not be affected.

The discussion here is about the field_behavior annotation, not arbitrary protobuf. Please see https://google.aip.dev/203, which dictates

The use of REQUIRED indicates that the field must be present (and set to a non-empty value) on the request or resource.

A field should only be described as required if either:

  • It is a field on a resource that a user provides somewhere as input. In this case, the resource is only valid if a "truthy" value is stored.
    • When creating the resource, a value must be provided for the field on the create request.
    • When updating the resource, the user may omit the field provided that the field is also absent from the field mask, indicating no change to the field (otherwise it must be provided).
  • It is a field on a request message (a message that is an argument to an RPC, with a name usually ending in Request). In this case, a value must be provided as part of the request, and failure to do so must cause an error (usually INVALID_ARGUMENT).

We define the term "truthy" above as follows:

  • For primitives, values other than 0, 0.0, empty string/bytes, and false
  • For repeated fields maps, values with at least one entry
  • For messages, any message with at least one "truthy" field.

Based on the above it makes no sense for the client API to allow constructing a create request that simply uses default values for REQUIRED fields.

@chanseokoh
Copy link
Contributor

chanseokoh commented Oct 27, 2021

Aha, you're right. Didn't know falsy values are not allowed for REQUIRED. So a REQUIRED boolean field must always be set to true.

A corollary to this is that a required boolean must be set to true.

@chanseokoh
Copy link
Contributor

However, another aspect to take into consideration before implementing this is that, once implemented, changing REQUIRED to OPTIONAL (which is a non-breaking change on the API side) becomes a breaking change at the Java interface surface. This relaxation is what service teams may actually want to do (yaqs: 1277373026731556864), and it is hinted there too that it may cause a breaking change on end user's code. So this increases the risk of failure and everyone should be well aware of this subtlety.

@chanseokoh
Copy link
Contributor

That said, IMO, as much as required proto (not annotation) fields have been discouraged and actually everything is now optional in proto3, which has good reasons, I think we need to be careful of enforcing something always required on the Java surface too. Once something becomes explicitly required, there is no turning back. Service teams cannot change their APIs, and the Java API surface just can't change at all.

@meltsufin
Copy link
Member

@chanseokoh I agree that we should not enforce the (google.api.field_behavior) = REQUIRED at the API level. However, I think there are benefits to annotating the fields and method arguments with @NonNull or a similar annotation that IDEs and static analysis tools can use.
(Related to: b/113137879)

@yoshi-automation yoshi-automation added 🚨 This issue needs some love. and removed 🚨 This issue needs some love. labels May 2, 2022
suztomo pushed a commit that referenced this issue Mar 21, 2023
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [com.google.cloud:google-cloud-core](https://github.com/googleapis/java-core) | `2.8.20` -> `2.8.21` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-core/2.8.21/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-core/2.8.21/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-core/2.8.21/compatibility-slim/2.8.20)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-core/2.8.21/confidence-slim/2.8.20)](https://docs.renovatebot.com/merge-confidence/) |
| [com.google.cloud:google-cloud-core-bom](https://github.com/googleapis/java-core) | `2.8.20` -> `2.8.21` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-core-bom/2.8.21/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-core-bom/2.8.21/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-core-bom/2.8.21/compatibility-slim/2.8.20)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-core-bom/2.8.21/confidence-slim/2.8.20)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>googleapis/java-core</summary>

### [`v2.8.21`](https://github.com/googleapis/java-core/blob/HEAD/CHANGELOG.md#&#8203;2821-httpsgithubcomgoogleapisjava-corecomparev2820v2821-2022-10-10)

[Compare Source](https://github.com/googleapis/java-core/compare/v2.8.20...v2.8.21)

##### Dependencies

-   Update dependency com.google.api.grpc:proto-google-iam-v1 to v1.6.2 ([#&#8203;971](https://github.com/googleapis/java-core/issues/971)) ([5d778fc](https://github.com/googleapis/java-core/commit/5d778fc0d78e67cbcc4eb061da3b66dd3cab440e))
-   Update dependency com.google.api.grpc:proto-google-iam-v1 to v1.6.3 ([#&#8203;974](https://github.com/googleapis/java-core/issues/974)) ([1b7fcb9](https://github.com/googleapis/java-core/commit/1b7fcb978da55f8d30cf66941bc8208853fef116))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox.

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-shared-dependencies).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzMi4yMzAuMCIsInVwZGF0ZWRJblZlciI6IjMyLjIzNy4wIn0=-->
suztomo pushed a commit that referenced this issue Mar 21, 2023
🤖 I have created a release *beep* *boop*
---


## [3.0.5](https://github.com/googleapis/java-shared-dependencies/compare/v3.0.4...v3.0.5) (2022-10-20)


### Dependencies

* Update dependency com.fasterxml.jackson:jackson-bom to v2.13.4.20221013 ([#868](https://github.com/googleapis/java-shared-dependencies/issues/868)) ([5c2a825](https://github.com/googleapis/java-shared-dependencies/commit/5c2a825c18af61784287dd41eba3a21be80bbe6b))
* Update dependency com.google.auth:google-auth-library-bom to v1.12.0 ([#870](https://github.com/googleapis/java-shared-dependencies/issues/870)) ([3e3a60d](https://github.com/googleapis/java-shared-dependencies/commit/3e3a60dfd45f08401ee3ac7a98007fae21d5bba6))
* Update dependency com.google.auth:google-auth-library-bom to v1.12.1 ([#871](https://github.com/googleapis/java-shared-dependencies/issues/871)) ([4d94c75](https://github.com/googleapis/java-shared-dependencies/commit/4d94c753b46d7f8c787b0efa21d7bc42b1ca1c6c))
* Update dependency com.google.cloud:grpc-gcp to v1.3.0 ([#867](https://github.com/googleapis/java-shared-dependencies/issues/867)) ([48ca222](https://github.com/googleapis/java-shared-dependencies/commit/48ca222a5e4d9f88737d4c4a4ee2a42a7145619e))
* Update dependency com.google.errorprone:error_prone_annotations to v2.16 ([#865](https://github.com/googleapis/java-shared-dependencies/issues/865)) ([d7a494d](https://github.com/googleapis/java-shared-dependencies/commit/d7a494dcd12a529121b74fd9fb9dfc679017f844))
* Update dependency com.google.protobuf:protobuf-bom to v3.21.8 ([#872](https://github.com/googleapis/java-shared-dependencies/issues/872)) ([ebe5d5f](https://github.com/googleapis/java-shared-dependencies/commit/ebe5d5f27dbe4f12c06d3a69c14c74bbf4e76dd1))
* Update dependency gcp-releasetool to v1.8.10 ([#853](https://github.com/googleapis/java-shared-dependencies/issues/853)) ([5c6367a](https://github.com/googleapis/java-shared-dependencies/commit/5c6367a643f491d2ec04be58c1ff0eca5aa10904))
* Update dependency google-api-core to v2.10.2 ([#858](https://github.com/googleapis/java-shared-dependencies/issues/858)) ([bc91e8d](https://github.com/googleapis/java-shared-dependencies/commit/bc91e8df54f9d919a9e0dc69e61d52fd855a8dbf))
* Update dependency io.grpc:grpc-bom to v1.50.0 ([#866](https://github.com/googleapis/java-shared-dependencies/issues/866)) ([50039f4](https://github.com/googleapis/java-shared-dependencies/commit/50039f41bfba37e65685c4a5b279d3cb2a92f2c5))
* Update dependency io.grpc:grpc-bom to v1.50.1 ([#873](https://github.com/googleapis/java-shared-dependencies/issues/873)) ([9fb1561](https://github.com/googleapis/java-shared-dependencies/commit/9fb15613976f83c5545e2b664c488e9811c1f185))
* Update dependency org.checkerframework:checker-qual to v3.26.0 ([#852](https://github.com/googleapis/java-shared-dependencies/issues/852)) ([1e8cd60](https://github.com/googleapis/java-shared-dependencies/commit/1e8cd609b3be0cdd748a8fea6bc0fcb15d8f4c96))
* Update dependency org.threeten:threetenbp to v1.6.3 ([#869](https://github.com/googleapis/java-shared-dependencies/issues/869)) ([e992190](https://github.com/googleapis/java-shared-dependencies/commit/e9921900ec590e281b5ae6e16ab51e7bd67c1242))
* Update dependency typing-extensions to v4.4.0 ([#854](https://github.com/googleapis/java-shared-dependencies/issues/854)) ([c909a13](https://github.com/googleapis/java-shared-dependencies/commit/c909a13fa626eb387c8ee87b7cc22607cb9cf889))
* Update dependency zipp to v3.9.0 ([#859](https://github.com/googleapis/java-shared-dependencies/issues/859)) ([971b84e](https://github.com/googleapis/java-shared-dependencies/commit/971b84eb801699b585cd35300bed8d4fb65046d8))
* Update gax.version to v2.19.4 ([#875](https://github.com/googleapis/java-shared-dependencies/issues/875)) ([2eb7f3d](https://github.com/googleapis/java-shared-dependencies/commit/2eb7f3d6cf834c474dcdc99740f8cdabf50bca51))
* Update google.core.version to v2.8.21 ([#861](https://github.com/googleapis/java-shared-dependencies/issues/861)) ([2fda421](https://github.com/googleapis/java-shared-dependencies/commit/2fda4213796df086450fdc3d69d53a0bd1d59f46))
* Update google.core.version to v2.8.22 ([#879](https://github.com/googleapis/java-shared-dependencies/issues/879)) ([e4f9f9a](https://github.com/googleapis/java-shared-dependencies/commit/e4f9f9ad6373fb52c069985ca4390663ccdacb7d))
* Update iam.version to v1.6.3 ([#857](https://github.com/googleapis/java-shared-dependencies/issues/857)) ([6758373](https://github.com/googleapis/java-shared-dependencies/commit/675837378642f39fe55c0e30b62755b9185bee3d))
* Update iam.version to v1.6.4 ([#862](https://github.com/googleapis/java-shared-dependencies/issues/862)) ([1e1bc34](https://github.com/googleapis/java-shared-dependencies/commit/1e1bc341c9dd0f8f5a2d14aa8dd52399b2ce71c1))

---
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
suztomo pushed a commit that referenced this issue Mar 21, 2023
… to v1.42.1 (#861)

[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [com.google.http-client:google-http-client-bom](https://github.com/googleapis/google-http-java-client) | `1.42.0` -> `1.42.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.http-client:google-http-client-bom/1.42.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.http-client:google-http-client-bom/1.42.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.http-client:google-http-client-bom/1.42.1/compatibility-slim/1.42.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.http-client:google-http-client-bom/1.42.1/confidence-slim/1.42.0)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>googleapis/google-http-java-client</summary>

### [`v1.42.1`](https://github.com/googleapis/google-http-java-client/blob/HEAD/CHANGELOG.md#&#8203;1421-httpsgithubcomgoogleapisgoogle-http-java-clientcomparev1420v1421-2022-06-30)

[Compare Source](https://github.com/googleapis/google-http-java-client/compare/v1.42.0...v1.42.1)

##### Dependencies

-   update dependency com.google.protobuf:protobuf-java to v3.21.2 ([#&#8203;1676](https://github.com/googleapis/google-http-java-client/issues/1676)) ([d7638ec](https://github.com/googleapis/google-http-java-client/commit/d7638ec8a3e626790f33f4fb04889fe4dfb31575))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox.

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-core).
suztomo pushed a commit that referenced this issue Mar 21, 2023
🤖 I have created a release *beep* *boop*
---


## [2.8.2](googleapis/java-core@v2.8.1...v2.8.2) (2022-07-13)


### Bug Fixes

* enable longpaths support for windows test ([#1485](https://github.com/googleapis/java-core/issues/1485)) ([#866](googleapis/java-core#866)) ([8a8ac99](googleapis/java-core@8a8ac99))


### Dependencies

* update dependency com.google.api-client:google-api-client-bom to v1.35.2 ([#859](googleapis/java-core#859)) ([6b51a1c](googleapis/java-core@6b51a1c))
* update dependency com.google.api:gax-bom to v2.18.3 ([#860](googleapis/java-core#860)) ([f5a5278](googleapis/java-core@f5a5278))
* update dependency com.google.api.grpc:proto-google-common-protos to v2.9.1 ([#855](googleapis/java-core#855)) ([4ec6635](googleapis/java-core@4ec6635))
* update dependency com.google.api.grpc:proto-google-iam-v1 to v1.5.0 ([#862](googleapis/java-core#862)) ([19aebbe](googleapis/java-core@19aebbe))
* update dependency com.google.http-client:google-http-client-bom to v1.42.1 ([#861](googleapis/java-core#861)) ([4d7548b](googleapis/java-core@4d7548b))

---
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
priority: p3 Desirable enhancement or fix. May not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. type: question Request for information or clarification. Not an issue.
Projects
None yet
Development

No branches or pull requests

5 participants