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

Functions - Java Spanner example uses DCL #2862

Closed
saturnism opened this issue May 11, 2020 · 6 comments · Fixed by #4197
Closed

Functions - Java Spanner example uses DCL #2862

saturnism opened this issue May 11, 2020 · 6 comments · Fixed by #4197
Assignees
Labels
api: spanner Issues related to the Spanner API. priority: p2 Moderately-important priority. Fix may not be included in next release. 🚨 This issue needs some love. samples Issues that are directly related to samples. type: question Request for information or clarification. Not an issue.

Comments

@saturnism
Copy link
Contributor

Describe the issue

GCF Java 11 Spanner sample uses Double checked locking. The pattern is known to be broken, should follow the lazy field init example

@olavloite
Copy link
Contributor

@saturnism
I considered using the lazy field init idiom, but the problem is that it's use is discouraged if the initialization of the lazy field can fail. From the source that is referenced in the example itself:

While the implementation is an efficient thread-safe "singleton" cache without synchronization overhead, and better performing than uncontended synchronization,[4] the idiom can only be used when the construction of Something can be guaranteed to not fail. In most JVM implementations, if construction of Something fails, subsequent attempts to initialize it from the same class-loader will result in a NoClassDefFoundError failure.

In this case, the initialization of Spanner can fail, which is why I chose to implement the double checked locking idiom instead. To my knowledge, the double check locking idiom was only broken in Java 1.4 and earlier, and should be working correctly from Java 5 and up.

See for example https://www.oracle.com/technical-resources/articles/javase/bloch-effective-08-qa.html.

Or is there something else here that I'm missing?

@yoshi-automation yoshi-automation added the triage me I really want to be triaged. label May 12, 2020
@saturnism
Copy link
Contributor Author

good call on the exception. it is quite a bit of code to show how to use spanner in a function.

does it matter whether it's checks for initialized or simply check for client != null ?

The current code feels like that it will:

  1. first getClient call will throw the error
  2. second time it gets called it will return null and cause npe?

Would it make sense for createSpanner method to be part of SpannerHolder?

Lastly, would, static initialization work in the class, or IODH? static init exceptions can also be caught if the init happens in a static block.

@lesv lesv added api: spanner Issues related to the Spanner API. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. priority: p2 Moderately-important priority. Fix may not be included in next release. type: question Request for information or clarification. Not an issue. and removed triage me I really want to be triaged. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels May 12, 2020
@skuruppu
Copy link
Contributor

skuruppu commented Jul 2, 2020

Friendly ping on this issue to see what the next steps are. @olavloite, do you have any thoughts on the last comment from @saturnism?

@olavloite
Copy link
Contributor

Sorry, this one slipped of my radar.

does it matter whether it's checks for initialized or simply check for client != null ?

Yes, that does matter, as client could still be null after initialization (see below).

The current code feels like that it will:

  1. first getClient call will throw the error
  2. second time it gets called it will return null and cause npe?

No, if an error occurs during initialization, the initialized flag will be set to true and the error will be remembered. The same error that occurred during initialization will therefore also be thrown the next time getClient() is called.

My preferred solution would be if we could add something like the Apache commons LazyInitalizer in the core client libraries that we could use for this. I don't think Spanner is the only cloud client that might throw an exception during initialization, and that should therefore also be using a pattern like this. That would significantly reduce the amount of code in this example, but also make it easier for end users to initialize these kinds of clients.

@product-auto-label product-auto-label bot added the samples Issues that are directly related to samples. label Aug 28, 2020
@stale
Copy link

stale bot commented Nov 1, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale-wontfix label Nov 1, 2020
@olavloite
Copy link
Contributor

olavloite commented Nov 1, 2020

We have added a LazyInitializer to the Spanner client library, so this sample can be updated once version 3.0.1 of the Spanner client is included in the libraries-bom.

@stale stale bot removed the stale-wontfix label Nov 1, 2020
@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Nov 7, 2020
olavloite added a commit to olavloite/java-docs-samples that referenced this issue Nov 8, 2020
The Spanner client library now includes a lazy initializer for Spanner instances
that can be used with Google Cloud Functions and other libraries that want to
create an instance the first time one is needed and reuse this instance for
subsequent requests.

Fixes GoogleCloudPlatform#2862
@lesv lesv closed this as completed in #4197 Nov 9, 2020
lesv pushed a commit that referenced this issue Nov 9, 2020
The Spanner client library now includes a lazy initializer for Spanner instances
that can be used with Google Cloud Functions and other libraries that want to
create an instance the first time one is needed and reuse this instance for
subsequent requests.

Fixes #2862
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: spanner Issues related to the Spanner API. priority: p2 Moderately-important priority. Fix may not be included in next release. 🚨 This issue needs some love. samples Issues that are directly related to samples. type: question Request for information or clarification. Not an issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants