|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectorg.glassfish.hk2.runlevel.utilities.RunLevelControllerImpl
@Service public class RunLevelControllerImpl
The default RunLevelController
implementation for Hk2. See the
RunLevelController
javadoc for general details regarding this service.
@RunLevel(X)
@Service
public class ServiceA {
@Inject ServiceB b;
}
@RunLevel(X)
@Service
public class ServiceB {
@Inject ServiceC c;
}
@RunLevel(X)
@Service
public class ServiceC {
}
When the DefaultRunLevelController is asked to proceedTo(X), the expected start
order is: ServiceC, ServiceB, ServiceA, and the expected shutdown order is:
ServiceA, ServiceB, ServiceC
Note that no model of dependencies between services are kept in the habitat
to make the implementation work. Any inhabitant in RunLevel X is arbitrarily
picked to start with upon activation, and ActiveDescriptor.create(org.glassfish.hk2.api.ServiceHandle)
is issued.
Consider the cases of possible activation orderings:
Case 1: A, B, then C by RLS. get ServiceA (called by RLS) Start ServiceA: get
ServiceB Start ServiceB: get ServiceC Start ServiceC wire ServiceC
PostConstruct ServiceC wire ServiceB PostConstruct ServiceB wire ServiceA
PostConstruct ServiceA get ServiceB (called by RLS) get ServiceC (called by
RLS)
Case 2: B, C, then A by RLS. get ServiceB (called by RLS) Start ServiceB: get
ServiceC Start ServiceC wire ServiceC PostConstruct ServiceC wire ServiceB
PostConstruct ServiceB get ServiceC (called by RLS) get ServiceA (called by
RLS) Start ServiceA: get ServiceB wire ServiceA PostConstruct ServiceA
Case 3: B, A, then C by RLS. get ServiceB (called by RLS) Start ServiceB: get
ServiceC Start ServiceC wire ServiceC PostConstruct ServiceC wire ServiceB
PostConstruct ServiceB get ServiceA (called by RLS) Start ServiceA: get
ServiceB wire ServiceA PostConstruct ServiceA get ServiceC (called by RLS)
Case 4: C, B, then A by RLS. get ServiceC (called by RLS) Start ServiceC:
wire ServiceC PostConstruct ServiceC get ServiceB (called by RLS) Start
ServiceB: get ServiceC wire ServiceB PostConstruct ServiceB get ServiceA
(called by RLS) Start ServiceA: get ServiceB wire ServiceA PostConstruct
ServiceA get ServiceA (called by RLS)
You can see that the order is always correct without needing to keep the
model of dependencies.
~~~
Note that the implementation performs some level of constraint checking
during injection. For example,
- It is an error to have a RunLevel-annotated service at RunLevel X to depend
on (i.e., be injected with) a RunLevel-annotated service at RunLevel Y when Y
> X.
- It is an error to have a non-RunLevel-annotated service to depend on a
RunLevel-annotated service at any RunLevel.
Note that the implementation does not handle Holder and Collection injection
constraint validations.
~~~
The implementation will automatically proceedTo(-1) after the habitat has
been initialized. The value of "-1" is symbolic of the kernel run level.
Note that all RunLevel values less than -1 will be ignored.
~~~
The implementation is written to support two modes of operation, asynchronous
/ threaded, and synchronous / single threaded. The DefaultRunLevelController
implementation mode is pre-configured to be synchronous. The
DefaultRunLevelController is thread safe.
In the synchronous mode, calls can be made to proceedTo() to interrupt
processing of any currently executing proceedTo() operation. This might
occur: in another thread, in the RunLevelListener
handlers, or in a
RunLevel
annotated service's PostConstruct
method call.
Note, however, that even in synchronous mode the proceedTo() operation may
exhibit asynchronous behavior. This is the case when the caller has two
threads calling proceedTo(), where the second thread is canceling the
operation of the first (perhaps due to timeout of a service's PostConstruct,
etc.). In this case, an interrupt will be sent to the first running thread to
cancel the previous operation, and proceedTo the run level from the second
thread's request. This presumes that the first thread is capable of being
interrupted. In such a situation, the second proceedTo() call returns
immediately and the first proceedTo() is interrupted to continue to the new
runLevel requested from the second thread's interrupt.
For this reason, it is strongly advised that InterruptedException
is
not swallowed by services that can be driven by the DefaultRunLevelController in
synchronous mode.
proceedTo invocations from a PostConstruct
callback are discouraged.
Consider using RunLevelListener
instead.
Important Note:
try {
rls.proceedTo(x);
} catch (Exception e) {
// swallow exception
}
~~~
All calls to the RunLevelListener
happens synchronously on the
same thread that caused the Inhabitant to be activated. Therefore,
implementors of this interface should be careful and avoid calling long
operations.
~~~
Nested Class Summary | |
---|---|
static class |
RunLevelControllerImpl.Interrupt
|
Field Summary | |
---|---|
static long |
DEFAULT_ASYNC_WAIT
The default timeout in milliseconds (to wait for async service types). |
Fields inherited from interface org.glassfish.hk2.runlevel.RunLevelController |
---|
RUNLEVEL_CONTROLLER_DEFAULT_NAME |
Constructor Summary | |
---|---|
RunLevelControllerImpl()
|
Method Summary | |
---|---|
protected boolean |
accept(Descriptor descriptor,
int activeRunLevel)
Returns true if the RunLevel for the given descriptor in question should be processed by this RunLevelController instance. |
void |
activate(ActiveDescriptor<?> descriptor)
Activate the run level service associated with given descriptor. |
void |
awaitCompletion()
Wait for completion of run level progression. |
void |
awaitCompletion(long timeout,
TimeUnit unit)
Wait for completion of run level progression. |
void |
deactivate(ActiveDescriptor<?> descriptor)
Deactivate the run level service associated with given descriptor. |
protected void |
event(org.glassfish.hk2.runlevel.utilities.RunLevelControllerImpl.Worker worker,
org.glassfish.hk2.runlevel.utilities.RunLevelControllerImpl.ListenerEvent event,
Throwable error,
boolean isHardInterrupt)
|
protected Activator |
getActivator()
Get the best Activator . |
Integer |
getCurrentRunLevel()
The current run level state. |
String |
getDescription(boolean extended)
|
protected Collection<RunLevelListener> |
getListeners()
Get all of the RunLevelListener s. |
String |
getName()
Get the name of this RunLevelController. |
Integer |
getPlannedRunLevel()
The planned run level state. |
HashMap<Integer,Stack<ActiveDescriptor<?>>> |
getRecorders()
|
protected List<Integer> |
getRecordersToRelease(int runLevel)
|
protected Sorter |
getSorter()
Get the best Sorter . |
void |
interrupt()
Causes this RunLevelController to attempt to stop any in-flight proceedTo() operation. |
void |
postConstruct()
|
void |
proceedTo(int runLevel)
Causes this RunLevelController to move to the specified run level for all RunLevel instances (identified by
RunLevelControllerIndicator ), orchestrating the appropriate
lifecycle events. |
protected void |
proceedTo(Integer runLevel,
boolean isHardInterrupt)
Proceed to the given run level. |
void |
recordActivation(ActiveDescriptor<?> descriptor)
Record the activation the run level service associated with the given descriptor. |
String |
toString()
|
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Field Detail |
---|
public static final long DEFAULT_ASYNC_WAIT
Constructor Detail |
---|
public RunLevelControllerImpl()
Method Detail |
---|
@PostConstruct public void postConstruct()
public String getName()
RunLevelController
getName
in interface RunLevelController
public Integer getCurrentRunLevel()
RunLevelController
getCurrentRunLevel
in interface RunLevelController
public Integer getPlannedRunLevel()
RunLevelController
getPlannedRunLevel
in interface RunLevelController
public void recordActivation(ActiveDescriptor<?> descriptor)
RunLevelController
recordActivation
in interface RunLevelController
descriptor
- the descriptorpublic void proceedTo(int runLevel)
RunLevelController
RunLevel
instances (identified by
RunLevelControllerIndicator
), orchestrating the appropriate
lifecycle events.
If the run level specified is the same as the current run level then the RunLevelController may return immediately.
Note that the underlying implementation may perform this operation asynchronously. Implementors who choose the asynchronous approach are expected to treat a subsequent proceedTo(newRunLevel) call as an implicit cancellation of any currently running proceedTo() that is running on one or more managed threads.
proceedTo
in interface RunLevelController
runLevel
- the run level to move topublic void interrupt()
RunLevelController
interrupt
in interface RunLevelController
public void activate(ActiveDescriptor<?> descriptor)
Activator
activate
in interface Activator
descriptor
- the descriptorpublic void deactivate(ActiveDescriptor<?> descriptor)
Activator
deactivate
in interface Activator
descriptor
- the descriptorpublic void awaitCompletion() throws InterruptedException, ExecutionException, TimeoutException
Activator
awaitCompletion
in interface Activator
InterruptedException
- if the current thread was interrupted
while waiting
ExecutionException
- if the completion code threw an exception
TimeoutException
- if the wait timed outpublic void awaitCompletion(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException, ExecutionException
Activator
awaitCompletion
in interface Activator
timeout
- the timeout valueunit
- the time unit
InterruptedException
- if the current thread was interrupted
while waiting
TimeoutException
- if the wait timed out
ExecutionException
- if the completion code threw an exceptionpublic String toString()
toString
in class Object
public String getDescription(boolean extended)
public HashMap<Integer,Stack<ActiveDescriptor<?>>> getRecorders()
protected boolean accept(Descriptor descriptor, int activeRunLevel)
descriptor
- the descriptoractiveRunLevel
- the current runLevel
protected List<Integer> getRecordersToRelease(int runLevel)
protected void event(org.glassfish.hk2.runlevel.utilities.RunLevelControllerImpl.Worker worker, org.glassfish.hk2.runlevel.utilities.RunLevelControllerImpl.ListenerEvent event, Throwable error, boolean isHardInterrupt)
protected void proceedTo(Integer runLevel, boolean isHardInterrupt)
runLevel
- the run levelisHardInterrupt
- indicates a hard interruptprotected Activator getActivator()
Activator
.
protected Collection<RunLevelListener> getListeners()
RunLevelListener
s.
protected Sorter getSorter()
Sorter
.
|
||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |