So maybe part of my attraction to something like the setters/getters method
is based on either my relatively simple environment, or over simplifing
things. And my usage is based on ECM, I am just getting into Merlin.
In response to Berin's post:
Typically, maybe always, I just do a lookup, and almost never a release.
Unless my component is obviously a resource hog, like a caching component, I
almost never call the release method. I guess I am counting on the
container to cleanup after me. Having to release every component makes me
think of the bad old days of doing ASP/VB COM programming, where I had to
explicitly set to null all my objects. But, in a more complex system, I can
see how you might have to explicitly release resources.
So, in ECM, and maybe Merlin, following your example, if I retrieved an
email component.. and then logged in, it is possible to have that instance
of the component actually changed under me? I assumed that once I did this:
EmailManager myEmailManager = lookup(EmailManager.ROLE); //(or whatever
lookup is required)
that I have a distinct object for the rest of the lifetime of my enclosing
object? And, when I destroy the calling object, then all the refereneces to
myEmailManager will go away, and then ECM/Merlin could toss the component?
But apprently that doesn't happen.. So, would this be a memory killing
loop:
while(true){
EmailManager myEmailManager = lookup(EmailManager.ROLE);
}
I guess I assumed that when I left the while loop, the object would go away,
just like if I did this:
while(true){
EmailManager myEmailManager = new EmailManager();
}
This is very interesting, because I have recieved reports that Hibernate
running under the Avalon wrapper I wrote has a memory leak, and this may be
related to it.. I am going to be doing some profiling over the next week,
so I am trying to make sure my understanding of Avalon is correct.
In response to Stephen's post:
I am going to study up more on the custom lifecyle.. Basically, after
looking at the tutorial/lifecyle/ demo, what is means is that if we have our
own custom implementation to configure a component, I could provide that
using maybe a commons-configuration object versus the default Avalon object
for example.. So the default lifecyle methods are there for easy of use,
but if I do the work of providing the adapter, the class implementing the
LifecycleCreateExtension class, then I can add additional lifecyle steps,
override existing ones. I guess though what I meant about the mapping of a
components method to an existing activity inteface would be like this:
public class ICanStart {
@avalon.lifecyle name="Startable"
public void startMe(){
System.out.println("I am started");
}
}
What my thinking is that instead of implementing startable, I provide what
method in my component is that "start" method. So basically rewire the
component integration with Avalon. Versus creating some sort of custom
lifecyle that does the same thing. Because I want all my objects to start
together, regardless of whether they implement the Startable interface.
When the kernel starts up, it would see that for this class, the startable
method is called startMe, and would then generate a proxy for it [1]. So,
as far as the kernel is concerned, it would be calling the ICanStart.start()
method, but since it is a proxy, it would then delegate that call down to
the startMe() method.. The same logic could be used with all the activity
lifecyle methods to rewire things.. Heck, a good geek joke would be to wire
the start method to the stop method and vice versa by tweaking the xml file
;-) .
Because the Servicable interface is all about looking up objects, it is a
bit more complex. That long wordy example of doing a lookup I yanked
directly from the tutorial, should I maybe update the tutorial so people
don't think that is the right way to do it? It seems like, assuming the
issues raised by Berin about the need for a lookup/release are resolved,
that what Stephen proposed about the @avalon.dependency would work.. And,
assuming the @avalon.dependency meant an interface, then you could easily
swap the implementation under the covers..
If there is real interest, and I'm not just haring down a bad path, I would
be interested in pursuing this. It seems to me that there are a couple
points of attack.. One is that the DefaultAppliance could be changed.. The
code here:
private void applyServices( Object instance )
throws Exception
{
if( instance instanceof Serviceable )
{
if( getLogger().isDebugEnabled() )
{
int id = System.identityHashCode( instance );
getLogger().debug( "applying service manager to: " + id );
}
ServiceManager manager = new DefaultServiceManager( getLogger(),
m_providers );
((Serviceable)instance).service( manager );
}
}
Seems to be exactly what I want.. Instead of calling service( manager) I
would do something like this:
// get a list of objects names to look up. Which I assume can be figured
out from meta info. (the m_providers)
List objectsToLookup = getObjectsToLookup()
for (Iterator i = objectsToLookup){
String objectName = (String)i.next();
Object object = manager.lookup(objectName);
// PropertyUtils from BeanUtils.. Slow..
PropertyUtils.setSimpleProperty(instance,objectName,object)
}
So, if my instance was defined like this:
/**
* Assignment of the service by the container.
* @avalon.dependency
*/
public void setRabbitWarren( RabbitWarren rabitWarren )
{
m_warren = rabitWarren;
}
And when I hit this, I would get back from the getObjectsToLookup the string
"rabbitWarren". It would the lookup the object with the name
"rabbitWarren".
and then call setRabbitWarrent(object).
At least this is my thinking.. Now, if someone can give me some pointers it
seems to me that this change could be handled either by an alternate
implementation of the DefaultAppliance. Or, and I'm not sure about this,
could it be done with a custom lifecyle? Looking at the
tutorial/lifecyle/excalibur example, it seems like when you actually access
the object would be the time to do this:
public void access( Object target, Context context ) throws Exception
{
getLogger().info( "invoking access on target" );
List objectsToLookup =
getObjectsToLookupFromContextForTarget(target,context)
ServiceManager manager = (ServiceManager)context.get("manager");
for (Iterator i = objectsToLookup){
String objectName = (String)i.next();
Object object = manager.lookup(objectName);
// PropertyUtils from BeanUtils.. Slow..
PropertyUtils.setSimpleProperty(target,objectName,object)
}
}
At any rate, I'd love your feedback. The level of discussion on this list
definitly requires me to sit and think a bit! The reason I want to get away
from implementing interfaces is because of what Stephen mentioned, people
don't want to rely on a community until they have been there for a while,
and establishing interfaces means they have to rely on the community before
the get to know it. Additionlly, I want to be able to write compoenents
that can run inside my container, with all the advantages of the container,
but also run outside, with no container at all..
Eric
[1]
http://cglib.sourceforge.net/apidocs/net/sf/cglib/reflect/MethodDelegate.htm
l
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]