-
Notifications
You must be signed in to change notification settings - Fork 45
HTTP-78 Support for optional query parameters for body-based requests #79
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
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.
Looking good but I have few nits and questions.
public LookupQueryInfo(String lookupQuery, Map<String, String> bodyBasedUrlQueryParams) { | ||
this.lookupQuery = | ||
Optional.ofNullable(lookupQuery) | ||
.orElseGet(() -> ""); |
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.
you can use orElse("")
instead orElseGet
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.
although your proposal is equivalent to what I wrote, there would be a performance penalty to use orElse("")
instead orElseGet
as explained here: https://www.baeldung.com/java-optional-or-else-vs-or-else-get#orElseGet
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 link you've provided explains when orElse
would introduce a performance penalty - that is, when you're calling a method inside the orElse()
method, especially not straight forward one like random
.
This performance hit comes because in case of orElse
we're always calling that method, no matter if we need it or not. In case of orElseGet
, we just call it when we actually need it. This is the only difference. Please refer to the implementation of both methods to confirm the above.
And so here, where a constant is used (see Java String Pool), there should be no performance difference whatsoever.
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.
.orElseGet(() -> ""); | ||
this.bodyBasedUrlQueryParams = | ||
Optional.ofNullable(bodyBasedUrlQueryParams) | ||
.orElseGet(() -> new LinkedHashMap<>()); |
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.
please consider using .orElse(Collections.emptyMap())
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 same performance penalty mentioned in comment #79 (comment) would come into play
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.
but I understand your point to use a read-only collection with Collections.emptyMap()
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.
Same as above - we're passing a constant here, there should be no difference in performance.
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.
Indeed, the Collections.emptyMap()
uses a static member compared to new LinkedHashMap<>()
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.
} | ||
|
||
public String getBodyBasedUrlQueryParameters() { | ||
return URLEncodedUtils.format( |
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.
what would be returned if bodyBasedUrlQueryParams
would be empty?
A null or empty string?
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.
An empty string is returned
if (lookupQueryInfo.hasBodyBasedUrlQueryParameters()) { | ||
resolvedUrl.append(baseUrl.contains("?") ? "&" : "?") | ||
.append(lookupQueryInfo.getBodyBasedUrlQueryParameters()); | ||
} |
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 guessing you are planing to have your own LookupQueryCreator
custom implementation that will return a LookupQueryInfo
that will have both, query and body params right?
And you plan to use it with one of the HttpRequestFactory
implementation right?
I wonder about contract between LookupQueryInfo
and HttpRequestFactory
.
In other words I wonder if the logic above is an implementation detail of LookupQueryInfo
or public contract that LookupQueryInfo
creator should know.
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 guessing you are planing to have your own LookupQueryCreator custom implementation that will return a LookupQueryInfo that will have both, query and body params right?
Yes, that's the final purpose:
- having POST requests with body parameters only
- having POST requests with body parameters and query parameters
In other words I wonder if the logic above is an implementation detail of LookupQueryInfo
In my view, this is rather an implementation detail and the HttpRequestFactory can be left untouched thereby remaining the "happy path".
this.bodyBasedUrlQueryParams = | ||
Optional.ofNullable(bodyBasedUrlQueryParams) | ||
.orElse(Collections.emptyMap()); | ||
} |
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.
Actually I don't think optional are the best thing to use here.
We are not gaining much from them and I would argue they are used not as Optionala were intend to be used.
I see that you are using them to have "nicely looking" null checks, but I think below code would do the same thing and will not be much harder do read:
this.lookupQuery = lookupQuery == null ? "" : lookupQuery;
this.bodyBasedUrlQueryParams = bodyBasedUrlQueryParams == null ? Collections.emptyMap() : bodyBasedUrlQueryParams;
Please substitute Optionals with the above code.
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.
No problem, change done in d0e1822#diff-5d0d1d1012fdd57bd2aa4b4fe50dca8d1ce442236c2eea7283222092d917b4a4R34-R38
Support for optional query parameters for body-based requests Signed-off-by: Olivier Zembri <<ozembri@fr.ibm.com>>
@@ -53,9 +53,15 @@ protected Logger getLogger() { | |||
return log; | |||
} | |||
|
|||
private URI constructGetUri() { | |||
URI constructBodyBasedUri(LookupQueryInfo lookupQueryInfo) { |
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.
Small comment, I was confused by the name of this method. I wonder if constructUri or addQueryInfoToURI would be more appropriate.
When we add path parameters I assume there would be another map in LookupQueryInfo that we would use to replace content in the parameterised baseUrl.
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.
When we add path parameters
This is not the scope of the current PR. It might be revisited with a PR dedicated to path parameters.
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.
When we add path parameters
This is not the scope of the current PR. It might be revisited with a PR dedicated to path parameters.
OK
…getindata#79) Support for optional query parameters for body-based requests Signed-off-by: Olivier Zembri <<ozembri@fr.ibm.com>>
Support for optional query parameters for body-based requests
Description
As documented, the connector currently create a lookup query from the HTTP TableLookup Source to build either:
There is no way to change this behaviour with custom factories.
Modification:
Change the signature of createLookupQuery(RowData lookupDataRow) in interface
LookupQueryCreator
so that it returns a classLookupQueryInfo
holding:Adapt the creation of the URIs in the constructions of HTTP requests to retrieve information from the class
LookupQueryInfo
.With these changes, any custom implementation of this interface that aims to provide body-based request is able to provide the lookup query as the payload and an optional formatted string representing the query parameters.
Resolves #78
PR Checklist