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