You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Eric Pugh <ep...@upstate.com> on 2003/11/04 10:59:29 UTC

Alternative to Serviceable interface?

Hi all,

Over the past 6 months I have been really getting into the COP approach.
Starting with Excaliber, a brief foray over to XWork, and now the porting of
Turbine and Fulcrum to Merlin.  And over the past month's I have had to
explain repeatedly why I am interested in using a container and components
in my applications.

And most of the ususual reasons make sense to people.  The easy
configuration of components.  The reliance on the container to start things
up in the correct order, etc..

And of course, the number one complaint/concern:  "I don't want to implement
somebodies interfaces..  Isn't that like EJB?"  To which I typically respond
that implementing a Startable/Stoppable/Configurable interface is no
different then what you would be doing anyway if you needed that
functionality.  And you are implementing well understood, widespread
interfaces.  Especially the Startable/Stoppable interfaces, that makes
complete sense.  Some people people do point out that instead of a
Configurable interface, they would set a series of javabean properties.  To
which I respond that eventually, if you have too many, you end up with a
config object, so you might as well start out with Configurable.  And you
can always do it by hand via JavaBeans.  And this satifies most people..

Which brings me to the one thing people really don't get..   Why do I have
to implement Serviceable to get a hook into other components?  Why can't the
container just give me the components?  I mean, in my java code inside the
component I have to pick what I want.  Why not define it outside and have
the container set it?  And I get all balled up in explanations..  Of which I
can think of many, like at run time I can pick and choose my components I
need..  If I have setting X, I get component X.  If I have setting Y, I get
component Y.  However, this did kinda make me wonder...   Why can't I just
expose the components I need and provide a setter?  Most of the time, I
always want an instance of component X.  In fact, often, because of unit
testing, if I have a dependency on component Y, then I just provide a
setter, so that at unit test time I can pass in my MockY component, versus
having to use a custom test configuration loaded through avalon.

I looked at the /tutorial/composition/application/impl/../Application.java
class, and it does precisily what I want it to do..  It implements
Serviceable, and it looks up objects named "locator" and "publisher".
Admittedly, in the example, it then does something, but for my purposes, I
would be happy to just know that when I loaded up the Application component
I had a locator and publisher objects.  Now, both of these objects were
defined for me in my block.xml:

     <include name="location" id="merlin-tutorial:locator-impl"
version="1.0"/>
     <include name="publisher" id="merlin-tutorial:publisher-impl"
version="1.0"/>

Including all the info to resolve them!  So, what would be involved in
having a something that did the servicable for me?  If Application.java has
a setLocation() and setPublisher() methods, and something was set in the
block.xml, then Application.java could skip the serviceable method and
Merlin could just populate the setters for me.  In the XML below, I just
added an autoset="true" to the component declaration that would be the key
to Merlin to just create the darn objects and pass them in...

<container name="application">
     <classloader>
       <classpath>
         <repository>
           <resource id="avalon-framework:avalon-framework-api"
version="4.1.5"/>
           <resource id="avalon-framework:avalon-framework-impl"
version="4.1.5"/>
           <resource id="merlin-tutorial:locator-api" version="1.0"/>
           <resource id="merlin-tutorial:publisher-api" version="1.0"/>
           <resource id="merlin-tutorial:application-impl" version="1.0"/>
         </repository>
       </classpath>
     </classloader>

     <include name="location" id="merlin-tutorial:locator-impl"
version="1.0" />
     <include name="publisher" id="merlin-tutorial:publisher-impl"
version="1.0"/>

     <component name="application"
        class="tutorial.application.Application" autoset="true">
     </component>

</container>

I can see issues where location maybe wanted some other objects as well.
However, those dependencis could be setup in here to, correct?  Via more
<component> tags?

The reason I bring this up is because I have been reviewing, under prodding,
other frameworks.  The nice thing about the SpringFramework is that your
components don't have to implement interfaces (other then a
startable/stoppable one) to be used in Spring.  And they don't have to
implement a Serviceable type interface.

I think having Serviceable is very good in some situations.  But, in many,
it is overkill.  I just want to get a component, and have the X dependent
component already loaded, versus having to everytime do this:

        LocationService locator = null;
        Object object = manager.lookup( "locator" );
        if( object instanceof LocationService )
        {
            locator = (LocationService) object;
        }
        else
        {
            final String error =
              "Object " + object.getClass().getName()
              + " does not implement the LocatorService class.";
            throw new ServiceException( "locator", error );
        }


On a related note..  If you had this facade (?)/interface layer, then the
various Activity lifecyle interfaces wouldn't need to be implmented.  I
could instead provide a mapping file that said: For my component, I do
implement the Startable interface, I just didn't implement it, and my method
is called "begin()".  This would work for noarg methods especially well.
Actually, I guess would this be a proxy?

Eric Pugh


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Alternative to Serviceable interface?

Posted by Stephen McConnell <mc...@apache.org>.

Eric Pugh wrote:

>Hi all,
>
>Over the past 6 months I have been really getting into the COP approach.
>Starting with Excaliber, a brief foray over to XWork, and now the porting of
>Turbine and Fulcrum to Merlin.  And over the past month's I have had to
>explain repeatedly why I am interested in using a container and components
>in my applications.
>
>And most of the ususual reasons make sense to people.  The easy
>configuration of components.  The reliance on the container to start things
>up in the correct order, etc..
>
>And of course, the number one complaint/concern:  "I don't want to implement
>somebodies interfaces..  Isn't that like EJB?"  To which I typically respond
>that implementing a Startable/Stoppable/Configurable interface is no
>different then what you would be doing anyway if you needed that
>functionality.  And you are implementing well understood, widespread
>interfaces.  Especially the Startable/Stoppable interfaces, that makes
>complete sense.  Some people people do point out that instead of a
>Configurable interface, they would set a series of javabean properties.  To
>which I respond that eventually, if you have too many, you end up with a
>config object, so you might as well start out with Configurable.  And you
>can always do it by hand via JavaBeans.  And this satifies most people..
>

Just a point concerning "I don't want to implement somebodies interfaces.."

I think this is a totally valid concern.  As soon as you implement 
someones interface you create a dependence on the interface which means 
a dependence on the package which means a dependence on the project 
which means a dependence on that community.

Instead - we can look at the container <--> component contract with a 
little more flexibility and say - ok - what is you strategy for 
configuration?  We (Avalon) can provide a default strategy using the 
Configurable interface and Configuration artifact - and if you don't 
like that, then you can declare an alternative strategy using your own 
lifecycle stage handlers.  What this means is that a developer can 
eliminate any Avalon dependency from the component, providing the same 
developer provides a set of custom handlers.  This means that the 
developer completely isolates the component model contractual dependency 
to a small number of custom extensions.  Its more work for the developer 
- but in some cases its justified.

All of this is possible today.

>
>Which brings me to the one thing people really don't get..   Why do I have
>to implement Serviceable to get a hook into other components?  Why can't the
>container just give me the components?  I mean, in my java code inside the
>component I have to pick what I want.  Why not define it outside and have
>the container set it?  And I get all balled up in explanations..  Of which I
>can think of many, like at run time I can pick and choose my components I
>need..  If I have setting X, I get component X.  If I have setting Y, I get
>component Y.  However, this did kinda make me wonder...   Why can't I just
>expose the components I need and provide a setter?  Most of the time, I
>always want an instance of component X.  In fact, often, because of unit
>testing, if I have a dependency on component Y, then I just provide a
>setter, so that at unit test time I can pass in my MockY component, versus
>having to use a custom test configuration loaded through avalon.
>
>I looked at the /tutorial/composition/application/impl/../Application.java
>class, and it does precisily what I want it to do..  It implements
>Serviceable, and it looks up objects named "locator" and "publisher".
>Admittedly, in the example, it then does something, but for my purposes, I
>would be happy to just know that when I loaded up the Application component
>I had a locator and publisher objects.  Now, both of these objects were
>defined for me in my block.xml:
>
>     <include name="location" id="merlin-tutorial:locator-impl"
>version="1.0"/>
>     <include name="publisher" id="merlin-tutorial:publisher-impl"
>version="1.0"/>
>
>Including all the info to resolve them!  So, what would be involved in
>having a something that did the servicable for me?  If Application.java has
>a setLocation() and setPublisher() methods, and something was set in the
>block.xml, then Application.java could skip the serviceable method and
>Merlin could just populate the setters for me.  In the XML below, I just
>added an autoset="true" to the component declaration that would be the key
>to Merlin to just create the darn objects and pass them in...
>
><container name="application">
>     <classloader>
>       <classpath>
>         <repository>
>           <resource id="avalon-framework:avalon-framework-api"
>version="4.1.5"/>
>           <resource id="avalon-framework:avalon-framework-impl"
>version="4.1.5"/>
>           <resource id="merlin-tutorial:locator-api" version="1.0"/>
>           <resource id="merlin-tutorial:publisher-api" version="1.0"/>
>           <resource id="merlin-tutorial:application-impl" version="1.0"/>
>         </repository>
>       </classpath>
>     </classloader>
>
>     <include name="location" id="merlin-tutorial:locator-impl"
>version="1.0" />
>     <include name="publisher" id="merlin-tutorial:publisher-impl"
>version="1.0"/>
>
>     <component name="application"
>        class="tutorial.application.Application" autoset="true">
>     </component>
>
></container>
>
>I can see issues where location maybe wanted some other objects as well.
>However, those dependencis could be setup in here to, correct?  Via more
><component> tags?
>
>The reason I bring this up is because I have been reviewing, under prodding,
>other frameworks.  The nice thing about the SpringFramework is that your
>components don't have to implement interfaces (other then a
>startable/stoppable one) to be used in Spring.  And they don't have to
>implement a Serviceable type interface.
>

What you describing is an alternative strategy for the assignment of
services to a component.  Lets' forget about meta-data directive like 
autoset,
but instead think about how to declare an alternative assignment 
strategy at
the level of a component type. 

E.g.:

  /**
   * Assignment of the service by the container.
   * @avalon.dependency
   */
   public void setRabbitWarren( RabbitWarren warren )
   {
       m_warren = warren;
   }

It seems to me that there is sufficient information for a container to
resolve this.

>I think having Serviceable is very good in some situations.  But, in many,
>it is overkill.  I just want to get a component, and have the X dependent
>component already loaded, versus having to everytime do this:
>
>        LocationService locator = null;
>        Object object = manager.lookup( "locator" );
>        if( object instanceof LocationService )
>        {
>            locator = (LocationService) object;
>        }
>        else
>        {
>            final String error =
>              "Object " + object.getClass().getName()
>              + " does not implement the LocatorService class.";
>            throw new ServiceException( "locator", error );
>        }
>

If you using Merlin you don't need to do all of this. 
You only need to do the following:

    LocationService locator = (LocationService) manager.lookup( "locator" );

All of the checking has already been done before your object is even
instantiated.

>
>
>On a related note..  If you had this facade (?)/interface layer, then the
>various Activity lifecyle interfaces wouldn't need to be implmented.  I
>could instead provide a mapping file that said: For my component, I do
>implement the Startable interface, I just didn't implement it, and my method
>is called "begin()".  This would work for noarg methods especially well.
>Actually, I guess would this be a proxy?
>

Sorry - I don't understand the above para.  Every lifecycle interface in 
Avalon is optional. In fact is perfectly ok to have an component that 
implements no avalon lifecycle interfaces.  I figure I'm missing 
something - can you expand?

Cheers, Steve.


>
>Eric Pugh
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
>For additional commands, e-mail: dev-help@avalon.apache.org
>
>
>  
>

-- 

Stephen J. McConnell
mailto:mcconnell@apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Alternative to Serviceable interface?

Posted by Berin Loritsch <bl...@apache.org>.
Eric Pugh wrote:

> 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.

ECM has a number of issues which I can expose as time goes on.

> 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.

The fact that you never release your components means you have simple
requirements, and a simple setter would work well for you.

In Merlin and Fortress this is not nearly as big a problem as it is with
ECM.  ECM stores references to that component in a list which grows over time.

The lookup/release issues are more important with ECM than anything else.
However keep in mind that for pooled components it is critical to release the
component when you are done, otherwise the pool grows out of hand.

We would like to move closer to a garbage-collecting policy for pooled
components, or simply remove that possibility.  We simply are not there yet.

> 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)

According to the contracts as outlined, that cannot happen until the release
is made.

> 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);
> 	}

We would like to make the garbage collection work for us, but you simply cannot
rely on it at this time.  If there are things to clean up, then you may or
may not have that happen.  Not even the JVM provides that guarantee--although
we might as well exploit what we can...

There are other issues in ECM with that loop.  ECM does some "book keeping"
and reference counting to ensure that everything is released so that it can
shut things down in a safe manner.  Both Fortress and Merlin have more advanced
ways of accounting for that so that they know the correct safe order to shut
down components without relying on components to do the releasing themselves.

Even though you don't like to release, it is a good practice to do so in the
dispose() method anyway.

> 
> 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();
> 	}

Maybe in Merlin/Fortress, but it never really does go away.  The container has
to account for that component, so it is tracking the component.  In the above
example the new EmailManager() allows the garbage collector to handle things,
and the compiler knows enough that the myEmailManager variable is never used
so the whole content of the loop does not have to be compiled at all.  Therefore
you won't see any build-up of memory because nothing is ever created.

> 
> 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.

Ok.



-- 

"They that give up essential liberty to obtain a little temporary safety
  deserve neither liberty nor safety."
                 - Benjamin Franklin


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


RE: Alternative to Serviceable interface?

Posted by Eric Pugh <ep...@upstate.com>.
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: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org


Re: Alternative to Serviceable interface?

Posted by Berin Loritsch <bl...@apache.org>.
Eric Pugh wrote:

> Hi all,
> 
> Over the past 6 months I have been really getting into the COP approach.
> Starting with Excaliber, a brief foray over to XWork, and now the porting of
> Turbine and Fulcrum to Merlin.  And over the past month's I have had to
> explain repeatedly why I am interested in using a container and components
> in my applications.

Sorry, I didn't want to ignore your message, but more info down low.

> And of course, the number one complaint/concern:  "I don't want to implement
> somebodies interfaces..  Isn't that like EJB?"  To which I typically respond
> that implementing a Startable/Stoppable/Configurable interface is no
> different then what you would be doing anyway if you needed that
> functionality.  And you are implementing well understood, widespread
> interfaces.  Especially the Startable/Stoppable interfaces, that makes
> complete sense.  Some people people do point out that instead of a
> Configurable interface, they would set a series of javabean properties.  To
> which I respond that eventually, if you have too many, you end up with a
> config object, so you might as well start out with Configurable.  And you
> can always do it by hand via JavaBeans.  And this satifies most people..

To tell the truth, alot of this complaint line falls under stylistic
differences.  I prefer to do JavaBean style components, or I NIH (Not Invented
Here) syndrome.  The thing about the interfaces is that you don't *have* to
implement any of them.  They just add some nice features that help make
writing the component easier.

Even how you obtain your services can fall under this approach.

It is a far cry from EJBs because EJBs force you to implement an interface
that mixes several concerns so your component has several empty methods, and
write a "key" object, and write a static "Home" class.


> Which brings me to the one thing people really don't get..   Why do I have
> to implement Serviceable to get a hook into other components?  Why can't the
> container just give me the components?  I mean, in my java code inside the
> component I have to pick what I want.  Why not define it outside and have
> the container set it?  And I get all balled up in explanations..  Of which I
> can think of many, like at run time I can pick and choose my components I
> need..  If I have setting X, I get component X.  If I have setting Y, I get
> component Y.  However, this did kinda make me wonder...   Why can't I just
> expose the components I need and provide a setter?  Most of the time, I
> always want an instance of component X.  In fact, often, because of unit
> testing, if I have a dependency on component Y, then I just provide a
> setter, so that at unit test time I can pass in my MockY component, versus
> having to use a custom test configuration loaded through avalon.

What is the difference between the ServiceManager and JNDI, other than the
fact that it is a much lighter weight thing?

Many of these people can understand the use of JNDI, but they don't like the
ServiceManager because they have their own pet way of doing things.

That said, there are always valid points in every point of view.  Many times
it is a balance that must be struck for each project.  For example, systems
that are simple enough to have one instance of a component would be easier to
write if the component were passed in through a setter.  Systems that require
dynamically managed components where an instance can be disposed of and replaced
dynamically have a different set of requirements--hense they need a lookup
mechanism.

To be fair the ComponentManager/ServiceManager concept was cooked up way back
before J2EE and EJBs.  We discussed adopting JNDI, but at the time there were
disagreements over how to look up items bound to JNDI.  Would "Context" items,
"Configuration" values, and "Services" all be bound in there?

Avalon was born as a server side component framework, but it is perfectly
comfortable on the desktop as well.  Implementing a ServiceManager is very much
easier than implementing a JNDI service provider.

The idea of using setters as a way to provide components is a very new concept.
Personally, I don't like the approach because of the systems that I have had
to maintain that were done with static accessors all over the place and other
major set backs.  So my bias is based completely on those negative experiences.
I recognize that, and I see value in the setter approach as long as all your
components are set once.

The ServiceManager has the concept of a defined set of time that a client has
a hold of a component.  You lookup() and release() components.  This approach
has the advantage of letting the container know without a doubt when it is safe
to upgrade a component.  It gets us philisophically closer to the 0 downtime system.

With a setter based system, you don't have those contracts, so the only safe
thing is code for write-once.  Which also means that you have to take special
care to manage concurrency issues and balance the synchronization vs. stability
within the system.

Imagine if you had a component like this:

EmailManager {
     void logIn(String user, String password);
     Message[] getMessages();
     void sendMessage( Message message );
     void deleteMessage( Message message );
     void logOut();
}

This component makes certain assumptions about the order the methods will be
called.  Now, let's assume that we don't have any synchronization issues to
worry about.  If at any time the container chooses to update the component
implementation, we run the risk that it will be done in the middle of using
it.  For instance, we may have logged in, obtained our messages, and then
the server upgrades the component with the setEmailManager().  Not only have
we not logged out with the old component, we aren't logged in with the new
component.  When we call sendMessage() or deleteMessage() next, we will be
in an unknown state.

That at least is the argument against the setters.  Many systems are not that
complex, and make many assumptions about the type of environment that the
application will be run in.  For instance, one assumption is one user, one
thread, unchanging components.  In this case, whatever you choose is a matter
of personal taste.

If there is any potential for your system to grow into a mult-user,
multi-threaded, dynamic system--the setter approach will become a hindrance.
In fact there will need to be more esoteric magic that has to be performed
to maintain the health of the system.  The lookup approach of either
ServiceManager or JNDI will be easier to handle these demanding requirements.
JNDI doesn't make sense for smaller systems or embedded systems--so the
happy medium we have is the ServiceManager.

It is neither right nor wrong, it is just the solution we have come up with.
We are looking to make things work with other folk's component types such
as Nano/Pico/Spring container type components.  It is very possible to do
with the existing modern Avalon containers.  We just don't have a nice generic
way of incorporating those features.

<snip/>

> On a related note..  If you had this facade (?)/interface layer, then the
> various Activity lifecyle interfaces wouldn't need to be implmented.  I
> could instead provide a mapping file that said: For my component, I do
> implement the Startable interface, I just didn't implement it, and my method
> is called "begin()".  This would work for noarg methods especially well.
> Actually, I guess would this be a proxy?

This component proxy you are talking about is also a nice way to incorporate
interceptors which make it easier to add new functionality to all components
in the system.

-- 

"They that give up essential liberty to obtain a little temporary safety
  deserve neither liberty nor safety."
                 - Benjamin Franklin


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@avalon.apache.org
For additional commands, e-mail: dev-help@avalon.apache.org