@Service public class RunLevelControllerImpl extends java.lang.Object implements RunLevelController
RunLevelController implementation for Hk2. See the
RunLevelController javadoc for general details regarding this service.
Here is a brief example of the behavior of 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 javax.annotation.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 javax.annotation.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.
~~~
| Modifier and Type | Class and Description |
|---|---|
static class |
RunLevelControllerImpl.Interrupt |
| Modifier and Type | Field and Description |
|---|---|
static long |
DEFAULT_ASYNC_WAIT
The default timeout in milliseconds (to wait for async service types).
|
| Constructor and Description |
|---|
RunLevelControllerImpl() |
| Modifier and Type | Method and Description |
|---|---|
protected void |
event(org.glassfish.hk2.runlevel.utilities.RunLevelControllerImpl.Worker worker,
org.glassfish.hk2.runlevel.utilities.RunLevelControllerImpl.ListenerEvent event,
java.lang.Throwable error,
boolean isHardInterrupt) |
java.lang.Integer |
getCurrentRunLevel()
The current run level state.
|
java.lang.String |
getDescription(boolean extended) |
java.lang.Integer |
getPlannedRunLevel()
The planned run level state.
|
java.util.HashMap<java.lang.Integer,java.util.Stack<ActiveDescriptor<?>>> |
getRecorders() |
protected java.util.List<java.lang.Integer> |
getRecordersToRelease(int runLevel) |
void |
interrupt()
Causes this RunLevelController to attempt to stop any in-flight
proceedTo() operation.
|
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. |
void |
recordActivation(ActiveDescriptor<?> descriptor)
Record the activation the run level service associated with the given
descriptor.
|
java.lang.String |
toString() |
public static final long DEFAULT_ASYNC_WAIT
public java.lang.Integer getCurrentRunLevel()
RunLevelControllergetCurrentRunLevel in interface RunLevelControllerpublic java.lang.Integer getPlannedRunLevel()
RunLevelControllergetPlannedRunLevel in interface RunLevelControllerpublic void recordActivation(ActiveDescriptor<?> descriptor)
RunLevelControllerrecordActivation in interface RunLevelControllerdescriptor - the descriptorpublic void proceedTo(int runLevel)
RunLevelControllerRunLevel 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.
This method will use the default activator which either starts or stops the services depending on whether or not the runLevel is coming up or going down
proceedTo in interface RunLevelControllerrunLevel - the run level to move topublic void interrupt()
RunLevelControllerinterrupt in interface RunLevelControllerpublic java.lang.String toString()
toString in class java.lang.Objectpublic java.lang.String getDescription(boolean extended)
public java.util.HashMap<java.lang.Integer,java.util.Stack<ActiveDescriptor<?>>> getRecorders()
protected java.util.List<java.lang.Integer> getRecordersToRelease(int runLevel)
protected void event(org.glassfish.hk2.runlevel.utilities.RunLevelControllerImpl.Worker worker,
org.glassfish.hk2.runlevel.utilities.RunLevelControllerImpl.ListenerEvent event,
java.lang.Throwable error,
boolean isHardInterrupt)
Copyright © 2013 Oracle Corporation. All Rights Reserved.