commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Richard Sitze <rsi...@us.ibm.com>
Subject Re: [discovery] Take III
Date Fri, 30 Aug 2002 20:30:40 GMT
>"Type-safe polymorphism" ? If that requires "Resource IS_A name", 
>then we should loose it. Why would you need it ? Just remove 
ResourceName,
>use String - and pass the string if you want the name, the real
>resource if you want the 'named object'. 
>
>There is no 'polymorphism' between a name and a named resource. 

My goal was to allow use of a Resource or ResourceClass as a 
ResourceName...    Since DiscoverResource and/or ResourceClass don't map a 
name to a new name (or are not intended to) as DiscoverResourceName does, 
this may not be as usefull as I thought.

Let me think on this and play around with it... I will either come up with 
a specific scenario, or I'll either remove it.

>
>> >Why not moving the only method from ResourceClass into Resource?
>> Type-safety. When I get a ResourceClass, I *know* I can load it.
>> I don't have to check..  I'm removing complexity *from* the users
>> code.  Seriously, as soon as I broke things up, the errors in my
>> test code just jumped out at me.  I fixed the broken types, and
>> my tests ran fine.  No more guess work.
>
>Again, what I disagree with is the arbitrary type distinction between
>Resource and ResourceClass. At least I don't see them as distinct,
>the real information is a string in the META-INF or some property
>file, and it can be used to construct a class or just to display
>a selection box ( say 'select JDBC driver' or 'select xslt processor' ). 

>Same info can be used either way. The user is required anyway to 
>know what he is looking for - and the name and where it should look
>and in what order. It is not absurt do expect him to know if he's 
>looking for a class that he wants to instantiate or just a class.

But is my (generic) method getting a (file) resource or a class?
The parameter type communicates to me & my users what I'm expecting: a 
class.

>And I don't agree you 'know' you can load it. You may know that
>the class is defined in META-INF/services, and you may even know
>that the class is in the classpath - but you may not be able to
>load it or instantiate it ( for example because of missing 
>dependencies ).

If it's a ResourceClass from a ResourceClassIterator, it's loadable by the 
ClassLoader.  I *know* I can load it (barring security exceptions.. I/O 
problems, etc).

Ahh..  perhaps a bit of mind-sync will help here.  With current scheme we 
have DiscoverServiceNames...  no longer do I have a DiscoverService 
(though it would be easy to add).  DiscoverServiceNames returns (for now) 
ResourceNameIterator, not ResourceIterator.  **There is not a guarantee 
that a class of a given name exists or can be loaded until is goes through 
DiscoverClasses**  DiscoverClasses has a 
findResourceClasses(ResourceNameIterator) which will resolve a 'list of 
names into valid classes.

>And any 'resource' can be used as either a class or a string. 
>Displaying the list of available drivers is a valid use for the
>discovered resource - and the same discovery can be used to 
>instantiate.
>
>> >Or even better - return Resource[].
>> 
>> If I knew how to defer file I/O, ClassLoader.getResource(), etc.
>> then I would much prefer this also.
>
>Resource can do the deferal. ( i.e Resource.getXXX would do the 
>operation, instead of putting it in the constructor ).

That would work for some cases, but not all.  Maybe my answer is to go 
ahead and use [] in the general case, but provide a ResourceIterator for 
those that don't.  Now that I have all the logic mapped out, I'll go back 
through & see exactly which ones still benefit from an Iterator...

>> >For the record - ClassLoaders also seems un-natural, and 
>> >so is creating ResourceClassDiscovery and all other with ClassLoaders
>> >in constructor... 
>> >I think a regular java-beans pattern, with an emptry constructor
>> >and then 'addClassLoader', etc would be much more intuititve.
>> 
>> The problem is performance again, particularly when working with
>> lots of little 'building blocks' that can be put together..
>> I want an holder of information that needs to be used in different
>> contexts.  Otherwise performance is a killer.
>
>Then use the bean model and reuse the bean.

Can't.  I've got multiple discoverers strung together:
- DiscoverNamesInSystemProperties
- DiscoverNamesInDictionary
- DiscoverServiceNames [extends DiscoverNamesInFile,
         which requires a set of class loaders]
All of which get sent through DiscoverClasses [requires class loaders]

A model that requires that the list be built up in each case (and how many 
OTHER discovery sequences might I build up in a system?) just seems like 
unnecessary work (code to write) for user and for Discovery (code to 
execute).  Holders represent common policy....

BTW, here is where Iterators are useful.  If I return a [] for the whole 
list of classes, then I have to process all names before returning to 
user.  This is a killer if my logic returns the Nth class it finds (not 
necessarily the first name or the first class).  Performance comes from 
simplicity of design, yes, but also by-design.

I agree that your proposal *would* be more performant for worst-case 
scenarious where you will be looking at everything that Discovery returns. 
 My model is going to be more performant in the median case, and if I can 
save even ONE file read or class load, then it's likely that the time lost 
in overhead to iterators etc. is more than offset.

>Please trust me on this one - I did a bit of 'performance'
>work ( try tomcat 3.1 and tomcat 3.3 for example ), a simpler
>model and design almost allways leads to better performance in the
>longer term.
>
>> Yea, I know that in a majority of use cases discovery can be
>> contained as start-up cost.  However, we have had some discussions
>> where it appears that we could use discovery in a more central
>> manner for some scenarios.  Performance is becoming a concern.
>
>I don't see any alghoritmic difference. Information can be 
cached/recycled 
>- there is nothing funamentally slow in a simpler design. 
>
>You create a DiscoverSource, addClassLoaders, and reuse this in
>different contexts. That's identical with a ClassLoaders object
> and using it to construct DiscoverSources ( as param in 
>the constructor ).

Not all Discoverers need the classloader.  Remember also that the set of 
ClassLoaders represents a policy that might be shared by different 
instances of Discovers...   Maybe you have an example?


>> One solution is to introduce an additional set of
>> API's (duck richard!): findFirst().
>> Also, for those cases where nothing is gained by defering - it
>> would be much better to use []'s... so a mix-and-match approach
>> might get me the best performance.
>
>But there's nothing to loose either. A findFirst() would be
>reasonable - since many use cases require this kind of behavior.
>And the internal implementation can use a 
>
>private discoverResources(boolean findFirst) that would stop
>after the first found resource if findFirst==true.
>
>The returned object would be 'lazy', but in findFirst case you'll
>just evaluate it before returning.
>
>
>> >The fact that we need a Log abstraction is a big 
>> >danger sign. We may become too complex.
>> Discovery is destined to be used in an Enterprise environment
>> which imposes certain restrictions on me.  I *need* to know
>> what's going on inside of discovery, and I *cannot* use System.out..
>> so.. Log.
>
>Then just use commons-logging, and we'll deal with the build
>problems when c-l starts using discovery.

OK with this, I can remove the copied classes.  I'll leave the behaviour, 
because I don't want discovery initiating a call to LogFactory if, one 
day, LogFactory calls discovery...  I want discovery to have resolved all 
Log implementations at one-level before those classes get used by 
LogFactory...

>
>Or ( even better IMO ) - use a Listener interface instead
> of log, so you can be finely notified by all events in the
>discovery process ( and may even react !).

Hmm.. this maybe another way to handle defered processing..
to many choices...  trix are for kids!

>> - I've copied ONLY the (current) Log interface & LogFactory
>>   in Discovery so that we don't have a build dependency on
>>   commons-logging.
>
>Duplicating Log and LogFactory is IMO far worse than having 
>a build dependency ( or even cross dependency ). 
>And if you also factor in the extra complexity... 
>
>
>> >>   I keep a history of classes found (URL), and only return
>> >>   the first for duplicate URL's.  So, it's *possible* that
>> >>   you might get back multiple classes found by different
>> >>   class loaders.. then you have the URL's if you desire.
>> >
>> >I don't think this is such a big problem - as long as we return
>> >all the info we find. 
>> >It is perfectly possible that some of the 'discoveries' are 
>> >false hits. It's up to the user to filter and decide which one
>> >is good and what to do with it.
>> 
>> Why?  It is my understanding that you CANNOT load the other
>> classes.  There is nothing the user can do, is there?  Hmm...
>> unless you write your own classloader... but then you can use
>> o.a.c.d.r.DiscoverResources(pathName + ".class") instead.
>
>???
>
>Not sure I understand. You get back a Resource with the URL, loader,
>etc. That will signal that a certain resource is available ( say
> a JDBC driver ). In ant case ( with the current extensions in 'embed') 
>it is possible to add more jars to the loader. In addition,
>I will probably add some Manifest-based discovery, and the user 
>could use information from the manifest to download the required
>deps. 
>
>There are many cases in which the user can do something to load
>the classes ( after discovering the 'resource/driver' is available
>and eventually looking up in manifest what is required ). 

Sounds like an extension of DiscoverClasses (which implements behaviour 
appropriate to ClassLoader).  Maybe I should rename it?


>> I suppose I could introduce another Discoverer for such a case,
>> but I think the general use will be to get the *one* class that
>> the ClassLoader would return.
>
>Again - there are very valid and common cases where the 'one' class
>can't be returned at the moment of discovery, but only later. 
>
>Costin
>

Great comments, thanks!

*******************************************
Richard A. Sitze
IBM WebSphere WebServices Development

--
To unsubscribe, e-mail:   <mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@jakarta.apache.org>


Mime
View raw message