Blog from December, 2017

It may not be well known that we maintain extensive package-level Javadocs in our code.  Whereas the overview document is meant to provide a general overview of the features in Juneau, the package-level docs are intended to provide in-depth information.

To help make these docs more visible, I've added "Additional Information" sections to the overview document that mirror the TOCs of the package-level docs.

Here's an example:

Caveat - Some of these package-level docs need some cleanup.  Also, some of the detailed information currently in the overview document can probably be moved into the package-level docs now that the subtopics are more visible.

 

I've made some improvements to the APIs involved with serializing and parsing HTTP parts (e.g. headers, form data, query parameters, path variables).  This was based on pain-points experienced by the Apache Streams team using the client and proxy APIs.  My hope is that this simplifies their code.

I've added a new package in the juneau-marshall project:

I removed the part handling code in the UON and URL-encoding marshallers and put them in these classes.  

The SimpleUonPartSerializer implementation treats everything as plain-text except for beans and maps (which continue to be serialized as UON objects).  This is now the DEFAULT part marshaller in both the client and server APIs.  So if you were creating your own part serializers (or using StringReaders) to get around how strings were being serialized by UrlEncodingSerializer, this change lets you get rid of them.

This change sacrifices "purity" for "practicality".  It should make adoption considerably easier.

Note that this replaces the existing PartSerializer/PartParser/PartType classes, so there will be code adoption.  But it should be straightforward.

Refer to the 7.0.2 release notes for more information:
http://juneau.apache.org/site/apidocs/overview-summary.html#7.0.2

I've just delivered changes that improve the internals of the Serializer/Parser APIs.  I've been working on this for about a month.  I plan on introducing these changes in 7.0.2.

The general idea is to standardize on the following design:

  • Context - A thread-safe read-only object (e.g. BeanContext, JsonSerializer).
  • ContextBuilder - A thread-safe builder for contexts (e.g. BeanContextBuilder, JsonSerializerBuilder).
  • Session - A non-thread-safe single-use object with configuration combined from context and runtime args (e.g. BeanSession, JsonSerializerSession).
  • PropertyStore - A thread-safe read-only set of configuration properties.  Each Context contains one PropertyStore.
  • PropertyStoreBuilder - A thread-safe builder for PropertyStore objects.  Each ContextBuilder contains one PropertyStoreBuilder.

 

Here are the highlights:

  • Caching improvements on serializers and parsers have reduced execution time of the core JUnits by approximately 1/3.
    The 17000+ JUnit tests now execute in less than 10 seconds (down from around 13s) and have a cache-reuse hit rate of 98% (164104 serializers/parsers/bean-contexts retrieved, but only 1801 created from scratch).

  • All the various separate *Context classes (e.g. JsonSerializerContext) have been folded into their respective serializer or parser classes (e.g. JsonSerializer).
    Additionally, these classes are their own bean contexts.
    For example, the class hierarchy of JsonSerializer is now:


 

  • Session objects also now have a consistent class hierarchy.
    For example, the class hierarchy of JsonSerializerSession is now:

 

  • Builder objects also now have a consistent class hierarchy.
    For example, the class hierarchy of JsonSerializerBuilder is now:


 

  • The PropertyStore class has been completely rewritten.
    It is now a read-only configuration store build using the PropertyStoreBuilder class.
    The previous PropertyStore class was overly-complicated with many read/write locks to ensure thread-safety.
    The new design shifts to a builder-based model with read-only PropertyStore 'snapshot-in-time' objects.
    PropertyStores can be used as hash keys to allow caching and reuse of Serializers and Parsers.

  • ContextBuilders are created by Context.create() and Context.builder() methods and Contexts are created by the ContextBuilder.build().
    Examples:
    • JsonSerializer s = JsonSerializer.create().simple().sq().build();  // Create a serializer from scratch.
    • JsonSerializer s = JsonSerializer.DEFAULT.builder().simple().sq().build();  // Clone and modify an existing serializer.