Return-Path: Delivered-To: apmail-jakarta-avalon-dev-archive@jakarta.apache.org Received: (qmail 73935 invoked by uid 500); 12 Apr 2001 16:14:30 -0000 Mailing-List: contact avalon-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Reply-To: "Avalon Development" Delivered-To: mailing list avalon-dev@jakarta.apache.org Received: (qmail 73882 invoked from network); 12 Apr 2001 16:14:28 -0000 From: "Stephen McConnell" To: "Avalon Development" Subject: RE: [vote] lifecycle exceptions Date: Thu, 12 Apr 2001 18:14:14 +0200 Message-ID: <000401c0c36b$9e026d10$0a01a8c0@osm.net> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0005_01C0C37C.618B3D10" X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook 8.5, Build 4.71.2173.0 Importance: Normal In-Reply-To: <3AD5BD31.CD1248A0@apache.org> X-MimeOLE: Produced By Microsoft MimeOLE V5.00.0810.800 X-Spam-Rating: h31.sny.collab.net 1.6.2 0/1000/N ------=_NextPart_000_0005_01C0C37C.618B3D10 Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: 7bit Borin: In you last (excelent) message you proposed the following interface defintions which are very close to something I think would work well in our environment. Borin wrote: > So my final proposal for the runtime interfaces is this: > > interface Executable { > void start(); > void stop(); > } > > interface Interruptable extends Executable { > void suspend(); // should this be interrupt()? > void resume(); > } So, including the relevant exceptions we would end up with the following interfaces: interface Executable { void start() throws StartException; void stop() throws StopException; } interface Interruptable extends Executable { void suspend() throws SuspendException; void resume() throws ResumeException; } interface Suspendable { // better name, anyone? void suspend() throws SuspendException; void resume() throws ResumeException; } +1 I would just like to add an additional exception, extending StartException that can be thrown by a component when an attempt is made to start it and it cannot start for reasons of conflict between its own internal startup-mechanism and the explicit instruction to start. I.e. this would allow a manager to catch the explicit exception case of an autonomous startup. AutonomyConflictException : StartException Cheers, Steve. ------=_NextPart_000_0005_01C0C37C.618B3D10 Content-Type: message/rfc822 Content-Transfer-Encoding: 7bit Content-Disposition: attachment Reply-To: "Avalon Development" From: "Berin Loritsch" To: "Avalon Development" References: <003d01c0c356$178108b0$0a01a8c0@osm.net> Subject: Re: [vote] lifecycle exceptions Date: Thu, 12 Apr 2001 16:35:29 +0200 Message-ID: <3AD5BD31.CD1248A0@apache.org> MIME-Version: 1.0 Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Mozilla 4.75 [en] (Windows NT 5.0; U) List-Help: List-Unsubscribe: List-Subscribe: X-Accept-Language: en X-Spam-Rating: h31.sny.collab.net 1.6.2 0/1000/N Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V5.00.0810.800 Stephen McConnell wrote: > > >From Pete: > -1 Some things are startable without being stoppable and vice versa. Please read my entire message below. I will provide a separate pattern that we could/should adopt for startable() but not stoppable(). It just doesn't make any sense to stop something you never started, so the stoppable really shouldn't be alone. > >From Steve: > > startable but not stoppable == dangerous, -1 > > stoppable but not startable == autonomous and manageable, 0 > > > > We could define this as: > > > > interface Stoppable > > { > > void stop() throws StopException; > > } > > > > interface Startable : Stoppable > > { > > void start() throws StartException; > > } Ok. This is my best stab to voice arguments and provide a possible direction. The approach Steve is using for his Components is somewhat like the "Composite" pattern described in Addison-Wesley's book on design patterns. Basically, it is easier to have all managed components controled by a managing component to use the same interface (Stoppable) and simply call the stop() method that is guaranteed to be there for all managed components. This is a very valid approach, and makes things like constructing new Compound Composites (Composites that include Composites) very easy to do. Our interfaces should strive to allow an implementation neutral view of the world (as much as is possible). Peter's approach is that he has some components that he has designed execute for a specific amount of time, and then die naturally. I think there is a different approach for this that would be beneficial. So we have to decide pros and cons for separating start() and stop() interfaces. Interface Pros Cons ---------------------------------------------------------------------------- ----- start() without stop() (1) Allows for letting a (1) Not very manageable, thread run until it the thread is still dies naturally running when the manging component is stopped() ---------------------------------------------------------------------------- ----- stop() without start() (1) Easily allows for (1) No practical cons, only Composites to cleanliness of API issues propogate the stop() to all children ---------------------------------------------------------------------------- ----- stop() and start() (1) Allows for any kind (1) Does not guarantee separated creational or manageability behavioral pattern ---------------------------------------------------------------------------- ----- start() and stop() (1) Guarantees (1) These two actions are combined manageability inextricably tied to (2) Easily allows for each other Composites to propogate the events to all children ---------------------------------------------------------------------------- ----- Given the pros and cons, I beleive in the end that it is MOST correct to tie the start() and stop() methods together. In a server environment, predictability and maintainability are very strong concerns. There is another pattern that better suits Peter's needs. In fact, when looking at the possible needs for the runtime interfaces (Startable, Stoppable, Suspendable, Resumable), they should be natural pairs. 1) Startable and Stoppable should be combined for maintenance and management reasons. 2) Suspendable and Resumable are another natural pair. 3) Conceptually speaking, you can't have Suspendable/Resumable without Startable/Stoppable. So my final proposal for the runtime interfaces is this: interface Executable { void start(); void stop(); } interface Interruptable extends Executable { void suspend(); // should this be interrupt()? void resume(); } Regarding the case where something is "startable" with no direct control over when it stops, I want to promote the "Command" pattern. Basically you have an object that acts as a proxy for an asynchronous process that must run to completion. The runtime interfaces are mainly for classes that will run for the entire duration that the Component allows it (i.e. the entire time between start() and stop() minus the times it is interrupted). This means that we must explicitly start and stop the process--it is an active component. The "Command" pattern encapsulates an action or set of actions in a command object that many times is run asynchronously (though not necessarily). The "Command" pattern has a real need in many contexts from servers to Servlets. In fact, the original Timer code that Federico committed used this pattern. Basically, we would have an interface for the Command object like this: interface Command { void execute(); } We would either provide a CommandQueue, or have that command object start after the Component it affects is fully set up. The main point of the Command object is that it is lightweight and it is tightly coupled to a Component. A component would have to expose, or register, this command object that would have access to protected members. I envision something like this: interface Commandable { Command[] getCommands(); } If a Component is Commandable, then the Commands can be executed between the time the Component is fully Initialized adn the time the Component is Disposed. --------------------------------------------------------------------- To unsubscribe, e-mail: avalon-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: avalon-dev-help@jakarta.apache.org ------=_NextPart_000_0005_01C0C37C.618B3D10 Content-Type: text/plain; charset=us-ascii --------------------------------------------------------------------- To unsubscribe, e-mail: avalon-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: avalon-dev-help@jakarta.apache.org ------=_NextPart_000_0005_01C0C37C.618B3D10--