[TransWarp] The return of naming.Reference()

Phillip J. Eby pje at telecommunity.com
Tue Jul 15 12:55:36 EDT 2003

During the 0.5 alpha 3 release cycle, I changed peak.naming to require that 
you use adaptTo to convert addresses to desired objects.  The intent was to 
get retrieval logic out of address classes, in order to reduce the 
unnecessarily tight coupling between addresses and things retrieved, and to 
get rid of the IObjectFactory interface and utilities.

So far, this has not worked very well.  I think that the double amputation 
was a success, but the patient would now like his healthy leg back.  ;)

The original idea of making addresses "object factories" was that it 
eliminated the need to create custom Context subclasses to go with every 
new kind of address.  JNDI dealt with this issue somewhat differently: 
naming contexts generally store 'Reference' objects, which specify a class, 
factory, and zero or more addresses.  The addresses are either strings or 
binary data, and are not interpreted.  Thus, the class and/or factory 
specified in the reference were responsible for interpreting the addresses.

I thought this was rather silly, since for 'peak.naming', this just pushed 
right back to the issue of how to resolve an address in the first 
place.  Early versions of the naming package wrapped addresses in a 
Reference() object, then unwrapped it again later in order to .retrieve() 
it.  So, that code got factored out a long time ago, as it seemed to make 
no sense.

Recently, we've gotten some experience in actually using peak.naming with 
our "enterprise" naming systems, and have come to realize that having 
References() does make sense, for somewhat different reasons.  For one 
thing, there are many objects one may wish to store in a naming system, 
that really don't make any sense as URLs.  But, we don't always have the 
option of storing a pickle or something of that sort.  Plus, pickling is 
tightly tied to a specific module structure, but directory contents may be 
used by multiple deployed application versions.  So, we'd like some 
indirection ability.

Here's what I propose to do.  I will re-introduce naming.Reference, and 
naming.IObjectFactory.  However, IObjectFactory will not be used as a 
utility any more, nor will addresses implement it.  Instead, 
naming.Reference and naming.LinkRef will implement it, as will any objects 
that want to be creatable *from* a Reference (e.g. database connections, 
lockfiles, logfiles, etc.)  Naming contexts will attempt to adapt retrieved 
objects to IObjectFactory before returning them to the caller, and the 
AddressContext base class will once again wrap addresses in a Reference 
before returning them.

Reference objects will have a "class/factory name", and a sequence of 
"addresses".  The "class/factory name" will actually be looked up in a 
property namespace ('peak.naming.factories'), where the default will be to 
interpret the factory name as an import string.  Thus, one can use import
names as class/factory names, but you will be able to "redirect" them using 
configuration properties, if needed.  References will be able to find the 
specified factory and invoke it, passing in the reference's data along with 
any available context information (e.g. the context the reference was found 

Here is the likely impact on existing PEAK and user code using peak.naming:

* The adaptTo=IWhatever requirement will go away again, although code using 
it will not break.  It will simply be optional for most naming system 
usage.  (Of course, it's still suggested that you use it for early 
detection that you've retrieved something you can't use!)

* The current adapter declarations from address classes to "desired object" 
interfaces will be replaced with a method that goes on the "desired object" 
class directly.  This method will need to accept a Reference and some other 
parameters (TBD), and return a new instance.  For example, SQLConnection 
will grow such a secondary constructor method.

* Addresses will have a new attribute, 'defaultFactory', that will be used 
by AddressContext to create a Reference() from an address.  This should be 
the qualified name (dotted import path) of the "desired object" class.

Notice that this means that naming contexts which can store References will 
be able to either use the default interpretation of an address, or store a 
Reference to a different class, bound to the same address.  (For example, 
one could create a reference to either a PsycoPG or PygreSQL connection, 
using the same 'pgsql:' address.)

Comments welcome, preferably *before* I implement this...  ;)

More information about the PEAK mailing list