-
Notifications
You must be signed in to change notification settings - Fork 96
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
cache JsonProvider result in JsonBindingBuilder #363
base: master
Are you sure you want to change the base?
cache JsonProvider result in JsonBindingBuilder #363
Conversation
Signed-off-by: Simulant <[email protected]>
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.
hi @Simulant87, thanks for having a go at this enhancement. There are a few things that I would like to change in order to widen the scope of caching to make it cover more realistic scenarios
@@ -25,17 +27,24 @@ | |||
public class JsonBindingBuilder implements JsonbBuilder { | |||
private JsonbConfig config = new JsonbConfig(); | |||
private JsonProvider provider = null; | |||
private JsonBinding bindingCache = null; |
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.
A few things on the binding cache here:
- The binding cache needs to be
static
so that it is global (i.e. across multiple different instances ofJsonBindingBuilder
). - We should allow more than one configuration of a
JsonbBinding
to be cached. Consider creating a composite key class (that combines provider and config) so we can store cached instances in aMap<JsonbKey,Jsonbinding>
. This would also allow us to eagerly initialize the map and make itfinal
- whatever data structure we use to store the JsonBinding instances needs to be a weak reference so we don't cause claassloader leaks when this is used in an app server environment where the server-side Yasson code has references to application-side classes that may be restarted/recycled multiple times during the same instance of the server-side 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.
the JsonbKey
class could look like this:
private static class JsonbKey {
private final JsonbConfig config;
private final JsonProvider provider;
public JsonbKey(JsonbConfig config, JsonProvider provider) {
// set final fields
}
// implement equals() and hashCode()
}
In order for this to work, we will need to properly compare equality for Jsonb
instances which can be done by doing configA.getAsMap().equals(configB.getAsMap())
|
||
@Override | ||
public JsonbBuilder withConfig(JsonbConfig config) { | ||
this.config = config; | ||
return this; | ||
synchronized (this) { |
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.
synchronization shouldn't be necessary here or in withProvider
. Instead, if we store cached instances in a map we can handle all concurrency within the build
method
@@ -58,6 +67,33 @@ public JsonbConfig getConfig() { | |||
|
|||
@Override | |||
public Jsonb build() { | |||
return new JsonBinding(this); | |||
synchronized (this) { |
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.
Instead of synchronizing here, we could take advantage of some concurrent map operations. For example:
JsonbKey currentKey = new JsonbKey(config, provider);
return jsonbCache.computeIfAbsent(currentKey, key -> new JsonBinding(this));
public class JsonBindingBuilderTest { | ||
|
||
@Test | ||
public void testMultipleCallsToBuildWithoutChangesReturnTheSameInstance() { |
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.
lets write tests that are more similar to how our users interact with Yasson/JSONB. In this case, you are doing new JsonBindingBuilder()
which is from a Yasson internal package and users should never be using.
Instead, lets do things like JsonbBuilder.create()
or JsonbBuilder.newBuilder().build()
|
||
|
||
@Test | ||
public void testMultipleCallsToBuildWithChangedConfigReturnNotTheSameInstance() { |
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.
lets also test that multiple instances with config changed in the same way are equal. In this case, 2 instances that both do config.withStrictIJSON(true);
should be equal
|
||
assertNotSame(jsonb1, jsonb2); | ||
} | ||
|
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.
lets also add a test that verifies 2 instances that both specify the same Adapter instance are the same, likewise another test that verifies 2 instances with different instances of the same Adapter class are different
Another complexity I just realized is that the
|
Hi @Simulant87 , your build is failing on copyright job in our pipeline. Currently there is an issue with that on our side. See PR #365 . Please when this PR is merged, just rebase on it and everything should be fine. |
Fix StackOverflowError on recursive references Signed-off-by: Jorge Bescos Gascon <[email protected]>
* Copyright plugin version fix. Printing of incorrect copyrights improved. Signed-off-by: David Kral <[email protected]> * Suggestions of aguibert according to copyright implemented. Signed-off-by: David Kral <[email protected]>
Signed-off-by: David Kral <[email protected]>
implement ticket #333