Ok, most of this makes sense. To be precise, this doesn't apply exactly to my situation. The difference is that ServiceA and ServiceB must NOT be dependent. They must be completely independent.
So, the "master" component should do something like this: Fire ServiceA Wait for ServiceA to complete Faire ServiceB The way I've been attempting to wait for the completion of ServiceA is simply by using a listener/observer. This should work, right? Well, there's a problem, because the component won't wait for anything. I even tried a very basic case of what you described below. I made the component Runnable and started a new thread with a simple while loop. The component cleaned itself up before it was finished! If it did continue, then the logger got washed away in the process, which is not good. So, either this should not be done (and your suggestion was wrong) or there is a bug. (Or I'm really tired and I'm overlooking something really obvious.) Here's a simple component. The sample output is below. public class Component extends AbstractLogEnabled implements Initializable, Serviceable, Startable, Disposable, Runnable { private ServiceA m_serviceA = null; private ServiceB m_serviceB = null; private Thread m_thread; /** * Servicing of the component by the container during * which service dependencies declared under the component * can be resolved using the supplied service manager. * * @param manager the service manager * @avalon.dependency type="ServiceA:1.0" key="serviceA" * @avalon.dependency type="ServiceB:1.0" key="serviceB" */ public void service( ServiceManager manager ) throws ServiceException { m_serviceA = (ServiceA) manager.lookup( "serviceAProvider" ); m_serviceB = (ServiceB) manager.lookup( "serviceBProvider" ); } public void initialize() { m_thread = new Thread(this); } public void start() { m_thread.start(); } public void run() { long i = 0; while(i < 500) { getLogger().info("Loop # " + i++); } } public void stop() { } public void dispose() { } } And a part of the output: <snip/> [DEBUG ] (project.Component.lifecycle): applying initialization [DEBUG ] (project.Component.lifecycle): applying startup [DEBUG ] (project.Component.lifecycle): component startup completed [DEBUG ] (project.Component.lifecycle): incarnation complete [DEBUG ] (project): commissioning of [Component] completed in 120 milliseconds [INFO ] (project.Component): Loop # 0 [INFO ] (project.Component): Loop # 1 [INFO ] (project.Component): Loop # 2 <snip/> [INFO ] (project.Component): Loop # 30 [INFO ] (project.Component): Loop # 31 [DEBUG ] (): commissioning of [project] completed in 320 milliseconds [INFO ] (project.Component): Loop # 32 [INFO ] (project.Component): Loop # 33 <snip/> [INFO ] (project.Component): Loop # 153 [INFO ] (project.Component): Loop # 154 [INFO ] (project.Component): Loop # 155 [DEBUG ] (kernel): state: started [INFO ] (project.Component): Loop # 156 [INFO ] (project.Component): Loop # 157 [INFO ] (project.Component): Loop # 158 [INFO ] (project.Component): Loop # 159 <snip/> [INFO ] (project.Component): Loop # 197 [INFO ] (project.Component): Loop # 198 [INFO ] (project.Component): Loop # 199 [DEBUG ] (kernel): shutdown event [DEBUG ] (kernel): state: stopping [DEBUG ] (kernel): state: decommissioning [DEBUG ] (): decommissioning [DEBUG ] (project): decommissioning [DEBUG ] (project.Component.lifecycle): etherialization [INFO ] (project.Component): Loop # 200 [INFO ] (project.Component): Loop # 201 [INFO ] (project.Component): Loop # 202 [INFO ] (project.Component): Loop # 203 <snip/> [INFO ] (project.Component): Loop # 281 [INFO ] (project.Component): Loop # 282 [INFO ] (project.Component): Loop # 283 [INFO ] (project.Component): Loop # 284 [INFO ] (project.Component): Loop # 285 [DEBUG ] (project.Component.lifecycle): applying shutdown [DEBUG ] (project.Component.lifecycle): applying disposal [DEBUG ] (kernel): state: stopped [DEBUG ] (kernel): disposal [INFO ] (project.Component): Loop # 286 [INFO ] (project.Component): Loop # 287 [INFO ] (project.Component): Loop # 288 [INFO ] (project.Component): Loop # 289 [INFO ] (project.Component): Loop # 290 [INFO ] (project.Component): Loop # 291 [INFO ] (project.Component): Loop # 292 [INFO ] (project.Component): Loop # 293 [INFO ] (project.Component): Loop # 294 [INFO ] (project.Component): Loop # 295 [INFO ] (project.Component): Loop # 296 [INFO ] (project.Component): Loop # 297 And this is where it ends. As you can see, we don't get to the end!! > -----Original Message----- > From: Niclas Hedhman [mailto:[EMAIL PROTECTED] > Sent: July 31, 2004 10:55 > To: Avalon framework users > Subject: Re: Using time-consuming services from a component > > > On Saturday 31 July 2004 03:32, David Leangen wrote: > > Hello! > > > > I have created a component, as explained in the tutorials. Let's call it > > "Component". Component has two services, ServiceA and ServiceB. Both of > > these services take a while to complete, and should be executed in > > sequence, since ServiceB depends on the completion of ServiceA. > > > > I declare my services like this: > > You need to get your capitalization right !!! :o) > > > > 1. When I was using only ServiceA, I only had to make a call to > > getStuff() in initialize(). At that time, I didn't really > > stop to think about the mechanism. I would like to know > > what actually fires off the service. > > Not sure what you are asking here. > Merlin will go through the life cycle methods of all components with the > activation set to 'startup', PLUS all the components that those > depends on. > For each component that are 'continuous' in the running, they > need to create > a thread (typically in initialize() ) and start the thread (typically in > start() ). > > > 2. How can I get Component to wait for the completion of > > ServiceA so I can fire ServiceB? > > You should most probably declare a dependendency. If the ServiceB > instance > depends on ServiceA, then you are guaranteed that they are made > available in > correct order. > > > I tried making a direct call to serviceA.start(), but that > didn't work. I > > don't think that I should be making my service providers Runnable. > > Agreed. The service shouldn't be made a sub-interface of > Runnable. You can > make the component implement Runnable, and create a thread with > the component > instance as the Runnable. > > > So, there's something I'm not getting here... > > You will probably need something simple like this; > > /** > * @avalon.component name="Comp1" > * lifestyle="singleton" > * @avalon.service type="org.hedhman.niclas.demo.ServiceA" > */ > public class Comp1 > implements Initializable, Startable, ServiceA, > Runnable, ServiceB > { > private Thread m_Thread; > private Stuff m_Stuff; > > public void initialize() > { > m_Stuff = ... // initialized through conf or params? > > m_Thread = new Thread( this ); > // potentially more code, long time to complete > // if too long, the deployment timeout needs to > // be extended > }. > > public void start() > { > m_Thread.start(); > } > > public void run() > { > // continuously running code > } > > public Stuff getStuff() > { > return m_Stuff; > } > } > > > /** > * @avalon.component name="Comp2" > * lifestyle="singleton" > * @avalon.service type="org.hedhman.niclas.demo.ServiceB" > */ > public class Comp2 > implements Serviceable, Initializable, ServiceB > { > private ServiceA m_ServiceA; > > /** > * @avalon.dependency type="org.hedhman.niclas.demo.ServiceA" > * key="serviceA" > */ > public void service( ServiceManager man ) > { > m_ServiceA = (ServiceA) man.lookup( "serviceA" ); > } > > public void initialize() > { > // At this point, Merlin will guarantee that the > // Comp1 has been initialized and there is Stuff that > // can be retrieved. > Stuff stuff = m_ServiceA.getStuff(); > } > } > > > I think this will help you on your way. > > > Niclas > -- > +------//-------------------+ > / http://www.bali.ac / > / http://niclas.hedhman.org / > +------//-------------------+ > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]