You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Niclas Hedhman <ni...@hedhman.org> on 2003/12/13 12:01:25 UTC

Re: When use ServiceManager.release(obj)?

Stephen and I have discussed this further on ICQ, and the issue basically 
grows into something more sinister... ;o)

My argument is based on;
* External resources can in some instances not be held onto as long as it 
takes for the GC to come around and release them.
* Therefor, an explicit release() should in these case be required from the 
user code.
* If that release() is not called, the user code developer must get notified 
(fail early), otherwise it will go undetected until deployment.


Stephen's argument is;
* User code developers are "lazy" and never play by rules.
* Automatic reclamation is therefor desireable, as it can solve a lot of this 
behaviour.
* Code looks nicer without the release(). It is sometimes troublesome to 
manage the release() call, just as it is troublesome to manage the 
destructors in C++.
* The container should help as much as possible.
* The behaviour (automatic reclamation) is not default, and must be declared 
explicitly.


I then raised the issue that there is currently no way for the User code to 
know that a release() is required for some troublesome services, as 
Disposable is declared at the implementation, which may not be known when the 
user code is written.

My conclusion, therefor, is either the release() is enforced or it should be 
deprecated altogether.

Since I DO realize that my use-cases are somewhat exceptional, there are 
possible solutions to them.
public interface ReleaseRequirement
{
    /** Releases external resource that may be held by the service.
     *  Failure to call this method may cause fatal errors later in code
     *  execution.
    */
    void release():
}

public interface MyService extends ReleaseRequirement
{
    // whatever
}


And the implementation can create Reports on failure to do release() by 
implementing Disposable and declaring the auto reclamation policy.

This is a solution without container involvement, and I can do with that.


Bottom-line Q;
Either release() is a requirement or it shouldn't exist. Which?

Niclas



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


Re: When use ServiceManager.release(obj)?

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Tuesday 16 December 2003 00:06, Leo Simons wrote:
> Leo Sutic wrote:
> > I agree - you can use the GC to catch user errors: I once did a
> > stack snapshot (created an Exception) when a component was lookup():ed.
> > When the component was released, I cleared the snapshot. When the
> > component
> > was finalized it would check for the Exception - if found, it would
> > scream at the console / user (in effect):
> >
> >   I HAVE NOT BEEN RELEASED!!!! I was lookuped from:
> >
> >       ... stack trace follows here ...
> >
> > Worked quite nicely.
>
> LOL! I love it! Perhaps we could add a feature like this to
> excalibur-testcase, merlin-testcase, etc :D

I love that too !!!  Just place it under isDebugEnabled() and all set...

Cheers
Niclas

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


Re: When use ServiceManager.release(obj)?

Posted by Leo Simons <le...@apache.org>.
Leo Sutic wrote:
> I agree - you can use the GC to catch user errors: I once did a
> stack snapshot (created an Exception) when a component was lookup():ed.
> When the component was released, I cleared the snapshot. When the
> component
> was finalized it would check for the Exception - if found, it would
> scream at the console / user (in effect):
> 
>   I HAVE NOT BEEN RELEASED!!!! I was lookuped from:
> 
>       ... stack trace follows here ...
> 
> Worked quite nicely.

LOL! I love it! Perhaps we could add a feature like this to 
excalibur-testcase, merlin-testcase, etc :D

- LSD



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


RE: When use ServiceManager.release(obj)?

Posted by Leo Sutic <le...@inspireinfrastructure.com>.
Use the finalize() method of the proxy.

Alternatively, do this in the component manager:

   HashMap objectsOutput = new HashMap ();

   public Object lookup (String role) {
       Object component = ... however you look it up ...

       Exception snapshot = new Exception ();
       objectsOutput.put (component, snapshot);

       return component;
   }

   public void release (Object o) {
       objectsOutput.remove (o);

       ... normal release ...
   }

   public void dispose () {
       // Print out anything in objectsOutput - 
       // those are the components that were looked up
       // but never released.
   }

ThreadSafe components are trickier, as you keep returning 
different instances, but also not as ciritcal to test.

Then again, if you always wrap the component you return
from lookup() in a proxy, then you use a new proxy every
time, and the above should work.

/LS

> From: Niclas Hedhman [mailto:niclas@hedhman.org] 


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


Re: When use ServiceManager.release(obj)?

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Monday 15 December 2003 23:44, Leo Sutic wrote:
> I agree - you can use the GC to catch user errors: I once did a
> stack snapshot (created an Exception) when a component was lookup():ed.
> When the component was released, I cleared the snapshot. When the
> component
> was finalized it would check for the Exception - if found, it would
> scream at the console / user (in effect):

However :o(  Need to resort to BCEL or something to rip away the finalize() 
method, which according to JLS and JVM docs are expensive (not as expensive 
as stack trace though)...

Niclas

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


RE: When use ServiceManager.release(obj)?

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Niclas Hedhman [mailto:niclas@hedhman.org] 
>
> P.S. I did not initiate the discussion of removing release(), 
> just that Stephen has this fancy "auto reclamation" which I argued 
> can not be dependent upon, but could help me to find user errors, 
> and with that came "my own" ReleaseRequirement interface to deal 
> with "my concerns in my domain".

Java GC isn't a strong contract - if it were, we'd not need close()
for InputStreams and so on (which is exactly what you say).

I agree - you can use the GC to catch user errors: I once did a
stack snapshot (created an Exception) when a component was lookup():ed.
When the component was released, I cleared the snapshot. When the
component
was finalized it would check for the Exception - if found, it would
scream at the console / user (in effect):

  I HAVE NOT BEEN RELEASED!!!! I was lookuped from:

      ... stack trace follows here ...

Worked quite nicely.

I think that's a great idea, although creation of snapshots *are*
expensive. Therefore it may be good to make this optional and only
turn it on during development.

/LS


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


Re: When use ServiceManager.release(obj)?

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Monday 15 December 2003 18:38, Leo Sutic wrote:
> > From: Niclas Hedhman [mailto:niclas@hedhman.org]
> >
> > Back to the bottom-line; What about
> > ServiceManager.release()?? Should it be
> > deprecated?
> > IMHO,
> > 1. Deprecated, or
> > 2. Enforced, or "soft enforced" (i.e. reported as a problem).
> >
> > I don't really care which one, but having a weak contract is not good.

> (I have seen this bottom line before.)

:o)

> basically, we've been here before. The sequence is usually that someone
> introduces the concept of no release. Then someone else pops up with
> a use case that *requires* a release. Then we get a marker interface
> or extension like ReleaseRequirement. 

My "ReleaseRequirement" interface was not intended as part of the 
Framework/Container, but only each service API that requires it.

> The only way out is to do a huge backwards-incompatible change: No
> relase() at all. All components are singletons. 
> If you want something else, you have
> to code it yourself. 

Singletons is a strong word, isn't it??  "Normal Java objects" - isn't that 
more natural. If the component requires releases (such as FileInputStream) it 
would expose a "close(), release()" or whatever...

No?

Regarding "back-incompatible"... You don't have to remove it altogether, 
people would freak, but deprecated and say "Merlin/Fortress is ignoring this 
method."

Anyway, I just "hate" weak contracts... No argument can change that.
If I need to live with weak contracts to satisfy legacy, I'll live miserably 
for a while... :o)


Cheers,
Niclas

P.S. I did not initiate the discussion of removing release(), just that 
Stephen has this fancy "auto reclamation" which I argued can not be dependent 
upon, but could help me to find user errors, and with that came "my own" 
ReleaseRequirement interface to deal with "my concerns in my domain".



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


RE: When use ServiceManager.release(obj)?

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> From: Niclas Hedhman [mailto:niclas@hedhman.org] 
>
> Back to the bottom-line; What about 
> ServiceManager.release()?? Should it be 
> deprecated? 
> IMHO, 
> 1. Deprecated, or
> 2. Enforced, or "soft enforced" (i.e. reported as a problem).
> 
> I don't really care which one, but having a weak contract is not good.

(I have seen this bottom line before.)

Niclas,

basically, we've been here before. The sequence is usually that someone
introduces the concept of no release. Then someone else pops up with
a use case that *requires* a release. Then we get a marker interface
or extension like ReleaseRequirement. Then someone remarks that you
have to test for this *all the time*. Then someone comes up with
something
like ReleaseUtils.maybeRelease (Object component), that will do the test
for you and release if needed. Then someone adds 1 and 1 and figures
that
since ReleaseUtils.maybeRelease must be called *all the time*, we might
as well use release() as we did in step 1.

The only way out is to do a huge backwards-incompatible change: No
relase() 
at all. All components are singletons. If you want something else, you
have 
to code it yourself. For example, instead of looking up SAXTransformers,
you do one lookup for a SAXTransformerFactory in the service() method,
and
then you use that factory.

/LS


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


Re: When use ServiceManager.release(obj)?

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Saturday 13 December 2003 20:31, Stephen McConnell wrote:
> Niclas Hedhman wrote:
> >public interface ReleaseRequirement
> >{
> >    /** Releases external resource that may be held by the service.
> >     *  Failure to call this method may cause fatal errors later in code
> >     *  execution.
> >    */
> >    void release():
> >}
> >
> >public interface MyService extends ReleaseRequirement
> >{
> >    // whatever
> >}
>
> How is this different from dispose?  As far as I can see what you are
> really saying is that you want a contract that forces commissioning,
> action and decommissioning within a particular controlled scope.

It's about explicitly exposing the requirement of release() to the client 
code! For a given Service, I typically have two to 20 implementations, and 
over time some types will grow continously.

You are not supposed to do a 
public interface MyService extends Disposable
{}

Not only is it ugly, but it will easily be misconstrued.

> E.g.
>
>    MyService service = (MyService) manager.lookup( "my-service" );
>    service.executeTransactions( m_actions );
>
> The component MyComponent implemeting MyService can then aquire the
> actual service that does the work, apply a series of actions, then
> release the service before returning from the call.  This way your in
> control of the aquisition/release cycle. 

I guess so, but it will be an awful ugly looking piece of code, creating a set 
of anonymous classes/objects an passing in an array. Did I say I don;t like 
anonymous classes much?

lookup()
do1()
do2()
do3()
release()

is much better IMHO.

> Does your scenario does let you isolate the aquisition/release cycle to
> this level of granularity?

Not sure what you mean.
In any event, by doing the ReleaseRequirement (which I didn't really realize 
until we had this GC discussion), I can do what I need, without changing 
Framework nor Merlin. And by "harnessing" the "auto reclamation" call via 
dispose(), I can detect that it was reclaimed implicitly, but expected it to 
be released explicitly, and notify the project implementation developer 
during the development, and prevent a disaster later (my kind of apps are 
expected to run at least a year without problems, restarts or manual 
attention, so intermittent problems after commissioning of the code into a 
project is the worst kind, since they are not attended to, nor recreatable).


Back to the bottom-line; What about ServiceManager.release()?? Should it be 
deprecated? 
IMHO, 
1. Deprecated, or
2. Enforced, or "soft enforced" (i.e. reported as a problem).

I don't really care which one, but having a weak contract is not good.

Niclas




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


Re: When use ServiceManager.release(obj)?

Posted by Niclas Hedhman <ni...@hedhman.org>.
On Saturday 13 December 2003 20:31, Stephen McConnell wrote:
> Niclas Hedhman wrote:
> >Stephen and I have discussed this further on ICQ, and the issue basically
> >grows into something more sinister... ;o)
>
> I wish my ascii art was good enough to draw a little monster with a
> wicked grin!


    ^^^^^^^^^
   <  o   o  >
    \   %   /
     \ ,., /
      \___/
       

Mine is also no good !
Ugly!!

Never mind, never claimed any artistic talent...
Niclas

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


Re: When use ServiceManager.release(obj)?

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

Niclas Hedhman wrote:

>Stephen and I have discussed this further on ICQ, and the issue basically 
>grows into something more sinister... ;o)
>

I wish my ascii art was good enough to draw a little monster with a
wicked grin!

>
>My argument is based on;
>* External resources can in some instances not be held onto as long as it 
>takes for the GC to come around and release them.
>* Therefor, an explicit release() should in these case be required from the 
>user code.
>* If that release() is not called, the user code developer must get notified 
>(fail early), otherwise it will go undetected until deployment.
>
>
>Stephen's argument is;
>* User code developers are "lazy" and never play by rules.
>* Automatic reclamation is therefor desireable, as it can solve a lot of this 
>behaviour.
>* Code looks nicer without the release(). It is sometimes troublesome to 
>manage the release() call, just as it is troublesome to manage the 
>destructors in C++.
>* The container should help as much as possible.
>* The behaviour (automatic reclamation) is not default, and must be declared 
>explicitly.
>
>
>I then raised the issue that there is currently no way for the User code to 
>know that a release() is required for some troublesome services, as 
>Disposable is declared at the implementation, which may not be known when the 
>user code is written.
>
>My conclusion, therefor, is either the release() is enforced or it should be 
>deprecated altogether.
>
>Since I DO realize that my use-cases are somewhat exceptional, there are 
>possible solutions to them.
>public interface ReleaseRequirement
>{
>    /** Releases external resource that may be held by the service.
>     *  Failure to call this method may cause fatal errors later in code
>     *  execution.
>    */
>    void release():
>}
>
>public interface MyService extends ReleaseRequirement
>{
>    // whatever
>}
>

How is this different from dispose?  As far as I can see what you are 
really saying is that you want a contract that forces commissioning, 
action and decommissioning within a particular controlled scope.

E.g.

   MyService service = (MyService) manager.lookup( "my-service" );
   service.executeTransactions( m_actions );

The component MyComponent implemeting MyService can then aquire the 
actual service that does the work, apply a series of actions, then 
release the service before returning from the call.  This way your in 
control of the aquisition/release cycle. Alternatively you could declare 
the entire thign as a lifecycle extension and do something like:

   public void assign( ActionHandler handler )
   {
       handler.handle( m_actions );
   }

Does your scenario does let you isolate the aquisition/release cycle to 
this level of granularity?

Stephen.

-- 

Stephen J. McConnell
mailto:mcconnell@apache.org

|------------------------------------------------|
| Magic by Merlin                                |
| Production by Avalon                           |
|                                                |
| http://avalon.apache.org/merlin                |
| http://dpml.net/                               |
|------------------------------------------------|





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