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

fix(spring): update setters for properties of type Duration #1093

Merged
merged 4 commits into from
Nov 16, 2022

Conversation

emmileaf
Copy link
Contributor

@emmileaf emmileaf commented Nov 14, 2022

This PR: updates setters for Spring properties of type org.threeten.bp.Duration to accept argument of type java.time.Duration instead, and parse to org.threeten.bp.Duration in the setter body.

  • Converting between the two types: parse() and toString() methods for both will accept or return ISO-8601 seconds based representation, such as PT8H6M12.345S.

This addresses the issue that properties of type org.threeten.bp.Duration cannot be set from strings (e.g. specified in Spring property files) because the implicit conversion is unsupported. Spring boot has dedicated support for properties of type java.time.Duration.

Note for review: would appreciate any feedback or thoughts on the conversion approach here! Some alternative approaches explored were:

  • The property type itself can be changed to java.time.Duration, but have getters modified to convert to org.threeten.bp.Duration (poc)
  • Adding custom converter for String to org.threeten.bp.Duration through @ConfigurationPropertiesBinding (poc)

@conventional-commit-lint-gcf
Copy link

conventional-commit-lint-gcf bot commented Nov 14, 2022

🤖 I detect that the PR title and the commit message differ and there's only one commit. To use the PR title for the commit history, you can use Github's automerge feature with squashing, or use automerge label. Good luck human!

-- conventional-commit-lint bot
https://conventionalcommits.org/

@emmileaf emmileaf marked this pull request as ready for review November 14, 2022 15:24
@emmileaf emmileaf requested review from a team as code owners November 14, 2022 15:24
getterAndSetter.add(
createDurationSetterMethod(thisClassType, propertyName, propertyType));
} else {
getterAndSetter.add(createSetterMethod(thisClassType, propertyName, propertyType));
Copy link
Member

Choose a reason for hiding this comment

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

This effectively changes the "correct usage" contract of createSetterMethod to be createNonDurationSetterMethod. Callers have to know about the second potential implementation and call the correct version -- which will either results in duplicated checks or a bug if someone doesn't realize.

Instead, consider relocating this check to be inside the createSetterMethod to maintain the simpler contract of "call this to get the correct setter 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.

Ah, that’s a good point! Currently the only call pattern is through createGetterSetters() since these are not exposed as public methods, but it will probably benefit future maintenance. I’ve moved the logic to all live inside createSetterMethod().

.setValueExpr(parsedDurationExpr)
.build();

String methodName = "set" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, propertyName);
Copy link
Member

Choose a reason for hiding this comment

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

Is this equivalent?

String methodName = "set" + JavaStyle.toUpperCamelCase(propertyName);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm good question - looks like under the hood JavaStyle.ToUpperCamelCase() uses CaseFormat to convert from lower snake to upper camel case, whereas we are converting from lower camel in this line.

I'm inclined to keep the current implementation but practically they do yield the same result, since here we just need the first letter of propertyName to change from lower to upper case.

Copy link
Contributor

@zhumin8 zhumin8 left a comment

Choose a reason for hiding this comment

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

LGTM!

@@ -365,14 +394,8 @@ private static Map<String, TypeNode> createDynamicTypes(Service service, String
.setPakkage("org.springframework.boot.context.properties")
.build());

// import org.threeten.bp.Duration;
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for catching this, it should be concrete type instead.

Variable propertyVar = Variable.builder().setName(propertyName).setType(returnType).build();
Expr thisExpr = ValueExpr.withValue(ThisObjectValue.withType(thisClassType));
TypeNode oldDurationType = staticTypes.get("org.threeten.bp.Duration");
TypeNode newDurationType = staticTypes.get("java.time.Duration");
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: perhaps naming as threetenDurationType and JavaDurationType?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup - updated to threetenBpDurationType and javaTimeDurationType.

@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

100.0% 100.0% Coverage
0.0% 0.0% Duplication

@emmileaf emmileaf merged commit b873b60 into autoconfig-gen-draft2 Nov 16, 2022
@emmileaf emmileaf deleted the spring-duration-conversion branch November 16, 2022 14:51
zhumin8 added a commit that referenced this pull request Nov 21, 2022
…tatic types instead of vapor references (#1046)

Adding Spring related dependencies to build files and use static types instead of vapor references. 
Benefit of this change:
- easier to test
- less code change needed for future changes (e.g. package change of classes).

One caveat is that because `gapic-generator-java` is brought into `googleapis` as `http_archive` code addition to `googleapis` is also needed to include these libraries. Add below code snippet to [WORKSPACE](https://github.com/googleapis/googleapis/blob/38e8b447d173909d3b2fe8fdc3e6cbb3c85442fd/WORKSPACE#L239-L245):
```
SPRING_MAVEN_ARTIFACTS = [
    "org.springframework.boot:spring-boot-starter:2.7.4",
    "com.google.cloud:spring-cloud-gcp-core:3.3.0",
]

maven_install(
    artifacts = PROTOBUF_MAVEN_ARTIFACTS + SPRING_MAVEN_ARTIFACTS,
    generate_compat_repositories = True,
    repositories = [
        "https://repo.maven.apache.org/maven2/",
    ],
)

```

------------
Updates:
- Updated pr with #1065, 
- Moved annotation classed added in #1045 to static types.
- Fixed conflicts from merged changes in #1093
- Moved logging classes added in #1053 to static types.
@zhumin8 zhumin8 added the spring pr that's related to spring code gen, intend to merge into autoconfig-gen-draft2 branch. label Dec 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
spring pr that's related to spring code gen, intend to merge into autoconfig-gen-draft2 branch.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants