StorageService API
Marvin S. Addison
marvin.addison at gmail.com
Mon May 6 14:24:55 EDT 2013
The StorageService API is of interest because it will be a core API
component needed for the CAS protocol (ticket storage). I've been
studying the component and considering how it would be used in my case,
and more generally to meet other needs. While I can imagine how I would
use it in my case, it would be more awkward than I'd like.
I struggled with the notion of exposing two different storage formats
(string/text) for all operations. I'm fairly certain I don't understand
the use cases where that feature would be required or even desirable,
but for simple cases like mine it's an obstacle. If you must have both
methods, it would be nice to expose a simple create/read/delete
interface that delegates through internal logic, i.e.
public create(String context, String key, String value) {
if (value.length() > capabilities.getStringLength()) {
createText(context, key, value);
} else {
createString(context, key, value);
}
}
Choosing a context name for every call seems verbose. I can imagine most
components working with a StorageService would use one or at most a few
context names. It might be helpful to expose a view on the storage
service that assumes the same context name for all operations. For example:
public StorageServiceView createView(String context) {...}
The StorageServiceView would expose the same contract as StorageService,
but without the context name parameter. It's more or less syntactic
sugar, but valuable in my mind.
It may be helpful if not necessary to provide a registry for context
names. Assuming all components consult the registry, it would provide a
means to guarantee that components don't step on one another by
inadvertently writing to the same context. You could enforce
consultation of the registry by leveraging a registry check in the
creation of a storage view as above.
Going beyond the CAS use case, I had a concern about the use of String
as the storage format in all cases. Thinking about RDBMS and LDAP there
seems like a fair bit of impedance mismatch. I'm most familiar with the
RDBMS case, but I believe the concerns apply to LDAP as well. In the
RDBMS case it would be most natural to persist an annotated type where
the context name (@Table), key (@Id), version (@Version), and possibly
expiration are derived from fields on the object. While you could
decompose an object into those fields before calling
StorageService#create, you would lose the expressive power of modern
Java ORM tools. You'd also incur BLOB/CLOB storage which has been a
substantial headache for us in the CAS project.
In summary, the PersistenceManager interface is much more like what I
would want from a general persistence/storage API component. Perhaps
there's room for both; for example the StorageService provides a
cache-like interface and PersistenceManager for more general object
persistence. I wish I had some suggestions to consolidate the two
components into a best of both, but I simply don't see it.
Thanks for reading,
M
More information about the dev
mailing list