Hey Przemyslaw,
Just to remove any confusion, when I talk about cache here, I am not
thinking of a classic cache that stores data and all the stuff it implies.
I am thinking more about datastructures that hold the metadata they need to
work once they are created + some lookup map that points to instances of
those datastructures.
The rest in line...
2015-02-02 8:37 GMT+01:00 Przemyslaw Bielicki <pbielicki_at_gmail.com>:
Eugen - I could not agree with you more on not having the JsonbContext, but
> there are some technical limitations. The problem (I see) with not having a
> context is that you either:
>
> 1. Have to process annotations and object graph every time you want to
> marshall/unmarshall an object (rather bad for performance)
>
To not have 1, means that the context would have this cache (or the
Un/Marshaller) and the user will have to reuse it.
If it is the Un/Marshaller, then JsonbContext does not much. If it is
JsonbContext, ok, but I have difficulties seeing a clean design of what he
will cache and why there.
Json databinding libs such as Jackson, Gson and Genson all cache
De/Serialiers instances (basically a lookup map by type). In this case a
De/Ser instance is tied to a single type (Un/Marshallers are not as they
can ser/de any type) and has all the introspected properties etc.
2. Have to have a global cache for all classes scanned so far (with a
> configurable size (?) limit, to avoid memory leak)
>
Well, there will have to be a lookup map somewhere (JsonbContext or
Un/Marshaller), global not really as it will be tied to an instance - no
reuse of the instance no cache. Not sure if it needs such configuration, it
is not caching data but rather metadata, thus it should remain small in
memory.
>
> Yes, it would free end users from managing the context themselves, but
> bare in mind that JSONB is a core middleware component but might be used by
> other middleware who knows better than us how to manage their context
> objects.
>
If the lookup map is tied to an instance (and not some static field) then
the user has full control over it. If he wants to take advantage of the
"caching" then he can reuse it.
> Also, if we want to employ such global cache into RI it would probably
> mean more bugs to resolve later on :)
>
>
I *REALLY like* the example you showed i.e.:
>
> Jsonb jsonb = new Jsonb.Builder()
> .setClasses(Book.class, Author.class, Language.class)
> .with(new MyJsonbConfig())
> .use(new SomeJsonbProvider()) // optional - by default would
> load one using ServiceLoader
> .use(new JsonpProvider()) // used to obtain jsonp read/write
> instances
> .build();
>
> As you can see I added one line to provide a config (could implement
> javax.json.bind.JsonbConfig interface). I think that having a config
> class is more flexible and powerfull than just setProperty method. In such
> case I would drop system properties thing - it would be a job of the config
> class to define where and how to pick up the Jsonb properties. JsonbConfig
> could also define which provider to use etc.
>
I was also thinking about this config class. I am only not sure at what
point should we have it if there are very few configurable features (pretty
print only?). Also I think that users will create instances of this config
and in this case they will have to know the concrete impl (ugly). If we add
such a class, I prefer to see it as a concrete class not an interface.
Another utility of a config class would be if it is provided to ser/de code
allowing it to self configure, but it is maybe a border case...
About system properties I was trolling :) We should keep configuration keys
as strings as it allows implementors to provide other kind of features
(+typed options for defined ones in the JSR).
>
> Just one question - I see use() called twice - which one wins? What's the
> difference between two providers in your example?
>
The first one is Json*b*Provider for JSONB jsr and the other one is
Json*p*Provider
for JSONP jsr. There could be 2 use method with different signatures.
>
> Last comment on ServiceLoader. I'm not a big fan of it and it seems I'm
> not alone:
> http://stackoverflow.com/questions/7039467/java-serviceloader-with-multiple-classloaders.
> I already had many issues with it in production using JAX-WS. I had to
> extend a bit CXF provider with custom behavior, which was the easiest part.
> The problem appeared when I wanted my provider to be picked up by app
> server. If you have in you classpath more than one service provider it's
> the classloader who decides which one will be used - not you. And it might
> differ from one OS to another (e.g. because of case sensitive JAR paths).
> It was a big pain and when you use ServiceLoader you cannot really
> explicitly say which provider you want to use - which is a showstopper for
> me.
>
>
I agree. The only way I see to avoid it is by providing directly an
instance of JsonbProvider.
I guess things will get more clear once we can see some code for default
ser/de of std types.
Cheers,
Eugen
> Cheers,
> Przemyslaw
>