You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@streams.apache.org by Steve Blackmon <sb...@apache.org> on 2017/08/26 21:11:35 UTC

Standardize + Improve Singleton pattern

 TL;DR I’m thinking of adding commons-pool2 as a dependency and refactoring
streams classes that have a keyed singleton access pattern to use it.

Hello all,

We have a fairly common pattern in streams modules where utility classes
have private constructors and getInstance methods with a configuration
parameter.

Each getInstance method returns an existing utility class instance matching
that configuration, or a new instance if that configuration has not yet
been instantiated.

Some examples of classes that follow some variant of this pattern:

org.apache.streams.jackson.StreamsJacksonMapper

org.apache.streams.pojo.extensions.ExtensionUtil

org.apache.streams.elasticsearch.ElasticsearchClientManager

org.apache.streams.converter.LineReadWriteUtil

org.apache.streams.twitter.api.Twitter

There are more, this is just the first five I found searching the code for
'getInstance'.

These classes are using a Factory Singleton model, but without a factory
class or parent class / interface.  And it’s up to the user to do their own
synchronization, if necessary.  All of the above happen to be thread-safe,
but there’s no support for streams for sharing or coordinating work on a
class that isn’t thread-safe in streams.

While refactoring some non-Apache code to get rid of a lingering dependency
on dropwizard-lifecycle, I came across the commons-pool library and did a
clean swap and suitability test.

https://commons.apache.org/proper/commons-pool/

It seems like a great fit to adopt in all the classes above; in addition to
standardizing the keyed singleton pattern on a common library, it has
lifecycle methods:
KeyedPooledObjectFactory.( create, destroy ) during process startup /
shutdown
KeyedPooledObjectFactory.( activate, passivate ) for spinning up/down
connections at start and end of batches of work
KeyedPooledObjectFactory.( validate ) which can be used for health checks
PooledObject.( allocate, deallocate ) which each thread can use to signal
use of the object
PooledObejct.( get*TimeMillis ) which can reveal how much time the object
is active / idle and when it was last used

Anyway, inviting all to take a look at the library and the classes above
and chime in whether to take this refactoring on.  Basically I’m thinking
each of the classes above would become a PooledObject and get a companion
singleton KeyedPooledObjectFactory which other threads would use to get
access to configured utility and connection management classes.

Steve