Sunday, December 14, 2003, 6:08:39 AM, Niclas Hedhman wrote:
> On Sunday 14 December 2003 07:26, Daniel Dekany wrote:
>> Saturday, December 13, 2003, 12:01:25 PM, Niclas Hedhman wrote:
>>
>> [snip]
>>
>> > Bottom-line Q;
>> > Either release() is a requirement or it shouldn't exist. Which?
>
>> So, I think that components that are accessible for app. code developers
>> should have lifestyle that requires *no* explicit releasing,
>
> Discriminatory behaviour?
> I don't feel comfortable with "weak contracts", as that IMHO is the root-cause
> of most bad code out there.
>
>> container should still support the usage of lifestyles that do need
>> explicit releasing, for programmers who work on lower lever systems
>> (e.g. on a Web app. framework). The default would be that "Don't use
>> release()!", with a the foot note "Except if you hack the guts of
>> something, and you *know* that a component requires release(). Don't
>> expose such object for user code developers.".
>
> Let's compare with
>
> FileInputStream in = new FileInputStream( filename );
>
> Do you mean that the "web application developer" should be Ok not to close the
> stream?
He should of course. The situation with components is a bit different.
Since for the code that uses the component (looks it up and invoke its
methods), the lifestyle (~implementation) specific details (as
lifestyle) should be transparent (i.e. the same code should work
whatever lifestyle is used by the used component), you end up with
choosing between: either user should *always* do explicit releasing, or
*never* do explicit releasing. This is where it differs from the case of
InputStream. An InputStream has to be "released" explicitly, but not
because its implementation details, but because its semantic, which is
specific for InputStream-s. Most other Java object (as a StringBuffer)
need not such explicit releasing. And it's natural so. However, in a
component management system, *all* kind of widgets are "component"-s,
regardless of the high-level semantic of that widget. For example,
programmer will easily accept that he has to explicitly release a
component that embody a DB connection, but he will find it idiot when he
has to explicitly release a component that formats messages...
> And that the "framework" should "somehow" handle it (especially since there is
> a separate debate whether it is possible to safe guard through the GC at
> all)...
>
> If you have N x 1000 request coming in over a short period of time, you could
> be running out of file handles, for no real reason (other than bad code). The
> "web application developer" don't want this, but "has forgotten" about it,
> which leads to my "Report inappropriate use.", so he can find out about it
> before it is in a production system.
You mean that it is detected when a component is collected with the GC,
which was not released()? If so, I think that such testing will too
often fail to detect the programmer's mistakes. For example, consider
that you release the object, but outside finally{...}. Thus, your code
will produce unreleased objects only when the release(...) call is not
reached because of an exception. It's hard to point out such errors,
even with thorough testing.
But the real problem with "release always" is that explicitly releasing
all components is a big PITA. try{...}finally{release},
try{...}finally{release}, try{...}finally{release}... not just tiresome,
but I'm pretty sure that somewhere I will miss one of them, since there
is so many of them. Yes, I can forget it for an InputStream as well, and
this *is* a risk, so I would like to reduce the number of such objects
in my apps.
OTOH, never releasing components seems to me a too big restriction for
people who are writing low-level code (framework), or parts that are
highly performance optimized.
I see a possible solution (which *is* a compromise):
Break the rule about lifestyle transparency discussed above: the
programmer who uses the object must know if the component returned for a
certain Role has to be explicitly released or not. For example, you say
that component returned for Role "databaseConnection" must be explicitly
released, always. This setting of the Role (i.e. if it requires manual
releasing or not) can't be changed later without breaking the user code,
and this has to be stated clearly.
How to point out programmer mistakes, when the programmer forgets if the
role requires manual releasing or not? ServiceManager.lookup(role)
should be allowed for "normal" Roles only (i.e. for Roles that do not
require manual releasing). For "manually released" Roles it throws
exception. For "manually released" Roles, user must use
ServiceManager.lookupAndHold(role) and ServiceManager.release(Object).
These two methods will throw exception if you try to use them for normal
Roles.
I have to emphasize: If a component is "manually released" or "normal"
should not be bound to the component implementation (in the case of
Merlin, shouldn't be stored in the .xinfo attached to the class), but to
the "role". A component with any lifestyle can be used as "manually
released", but the component implementations that use certain
sophisticated lifestyles can be dispatched only for "manually released"
roles, because of the requirements of the lifestyle. So in practice,
people should use "normal" roles, but if they find that for a certain
role they really will need more fancy lifestyles, they can define the
role as "manually released", and write those try{...}finally{release}-s
for the components returned for that role only.
--
Best regards,
Daniel Dekany
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]