The problem has always been what does mean to be "STARTED" when
components can be hot deployed.
The current mechanism is to send a notification after the initial install of
conf/jboss-service.xml which means you only get the started once
and there is no notion of stopping.
A better implementation to my mind would be to have a separate MBean
at the end of conf/jboss-service.xml which some services can depend upon.
i.e. the services that bind server sockets or deal with some form of inbound
communication or timer events.
The case of TxRecovery shows that there needs to be some ordering to
these services, e.g. a priority.
This would have the additional advantage that the server can be manually
suspended just by clicking STOP on that MBean.
As you can see, it doesn't need to be inside the container/kernel
it is just an additional service (with a well known name).
Which also makes its implementation more flexible/configurable.
Where the container does need to be involved is when you want
to suspend a service seamlessly (the valve).
i.e. don't unbind the server sockets, instead just hold the requests until
the service becomes available again.
What you could do is let the users define INIT levels and emit a notification when each of those is reached.
This gives you pre-determined notification, even based on hot-deployed services.
As Adrian said, this does not work very well. Tomcat waits for that 'server started' notification, but if you hot deploy it, it doesn't know that the server is already started.
Depending on another service that represents the server itself would propably be better.
So just keep the init level around as state somewhere.
can you point to a detailed description of the Tomcat use case?
Wouldn't it make sense to have independent binding services for TCP/IP and JNDI? They can have the "reverse-dependency" with the actual service that serves the user requests (Tomcat for port 8080).
<bean name="Tomcat"> ... <reverse-inject name="portManager"> <method="addListener" startup-level="created"/> <method="activateRequestsToListener" startup-level="started"/> <method="suspendRequestsToListener" startup-level="stopped"/> <method="removeListener" startup-level="destroyed"/> </reverse-inject> </bean>
related to the lifecycle API thread:
To avoid the verbosity of this for each service that binds to a port, a binding interceptor might be appropriate.
The more generic issue here is that there is often the desire to have a dependency on a collection of services with some quality. Examples include:
Services with network endpoints
Services which interact with the filesystem access
Services which write to the filesystem
Its not always that there should be a true start/stop type of dependency on the services.
If there was a snapshot service which periodically backedup the contents of serveral directories when the filesystem had no active writers, its not that the services which wrote to the filesystem need to be stopped. They simply need to be in a state that has no writers. Its more of a lock the snapshot service wishes to acquire and will wait until its notified that its the sole holder of the lock.
The problem with trying to introduce this notion is that services are not generally written with sufficient granularity to allow facets of their behavior to be micromanged. The existing JNDI service and a desire to control when network interfaces are established is an example. The JNDI service can operation fine without an external interface, but the way its coded today, if it were to depend on a network interface barrier service to delay the creation of its remote JNDI access endpoint, the local operation mode would also be unavailable and the server startup would fail horribly as numerous services failed to access JNDI via the default InitialContext.