|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objectorg.jvnet.hk2.component.internal.runlevel.DefaultRunLevelService
public class DefaultRunLevelService
The default RunLevelService implementation for Hk2. See the
RunLevelService javadoc for general details regarding this service.
Here is a brief example of the behavior of this service:
Imagine services ServiceA, ServiceB, and ServiceC are all in the same RunLevel X and the
dependencies are ServiceA -> ServiceB -> ServiceC:
@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 DefaultRunLevelService is asked to proceedTo(X), the
expected start order is: ServiceC, ServiceB, ServiceA, and the expected shutdown
order is: ServiceA, ServiceB, ServiceC
RunLevel-annotated services correspond to RunLevelInhabitant's and they
hook into the PostConstruct activation sequence to record the activation order
of inhabitants within each RunLevel.
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 Inhabitant.get() 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 DefaultRunLevelService
implementation mode is pre-configured to be synchronous. The
DefaultRunLevelService 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 DefaultRunLevelService in
synchronous mode.
proceedTo invocations from a PostConstruct callback are discouraged. Consider
using RunLevelListener instead.
Important Note:DefaultRunLevelService.Interrupt if it detects that it is being called
reentrantly in synchronous mode. Callers should be careful NOT to swallow exceptions
of this type as shown in the following example:
try {
rls.proceedTo(x);
} catch (Exception e) {
// swallow exception
}
~~~
All calls to the 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. ~~~ This service implements contractsInhabitantSorter as well as
InhabitantActivator. The implementation will first attempt to find a
habitat resident singleton for each of these contracts respectively, and failing to find an
implementation will handle each itself. This lookup occurs iteratively just prior to a
run level progression event. Note, however, that InhabitantSorter is only used
as part of activations since the Recorder is chiefly responsible for ensuring
release of the inhabitants occur in a consistent order. See earlier notes on this subject.
RunLevelService| Nested Class Summary | |
|---|---|
static class |
DefaultRunLevelService.Interrupt
|
| Nested classes/interfaces inherited from interface org.jvnet.hk2.component.InhabitantListener |
|---|
InhabitantListener.EventType |
| Nested classes/interfaces inherited from interface org.jvnet.hk2.component.HabitatListener |
|---|
HabitatListener.EventType |
| Field Summary | |
|---|---|
static int |
INITIAL_RUNLEVEL
|
static int |
KERNEL_RUNLEVEL
|
protected java.lang.String |
name
|
static java.lang.String |
NAME
|
| Constructor Summary | |
|---|---|
|
DefaultRunLevelService(Habitat habitat)
|
protected |
DefaultRunLevelService(Habitat habitat,
boolean async,
java.lang.String name,
java.lang.Class<?> targetEnv,
java.util.HashMap<java.lang.Integer,org.jvnet.hk2.component.internal.runlevel.Recorder> recorders)
|
| Method Summary | |
|---|---|
protected boolean |
accept(Inhabitant<?> i,
RunLevel rl,
int activeRunLevel)
Returns true if the RunLevel for the given inhabitant in question should be processed by this RunLevelService instance. |
void |
activate(Inhabitant inhabitant)
Called when we are responsible for handling the InhabitantActivator work. |
void |
deactivate(Inhabitant inhabitant)
Called when we are responsible for handling the InhabitantActivator work. |
void |
enable(boolean enabled)
Toggle the enabled state. |
protected void |
event(org.jvnet.hk2.component.internal.runlevel.DefaultRunLevelService.Worker worker,
org.jvnet.hk2.component.internal.runlevel.DefaultRunLevelService.ListenerEvent event,
ServiceContext context,
java.lang.Throwable error)
|
protected void |
event(org.jvnet.hk2.component.internal.runlevel.DefaultRunLevelService.Worker worker,
org.jvnet.hk2.component.internal.runlevel.DefaultRunLevelService.ListenerEvent event,
ServiceContext context,
java.lang.Throwable error,
boolean isHardInterrupt)
|
java.lang.Integer |
getActivatingRunLevel()
|
java.lang.Integer |
getCurrentRunLevel()
The current run level state. |
java.lang.String |
getDescription(boolean extended)
|
java.lang.Class |
getEnvironment()
The environment value for this state. |
protected InhabitantActivator |
getInhabitantActivator()
Obtains the "best" InhabitantActivator, first looking up out of the habitat any service registered under the same name as ourself, then defaulting to the first one registered by type alone, followed by ourself. |
protected InhabitantSorter |
getInhabitantSorter()
Obtains the "best" InhabitantSorter, first looking up out of the habitat any service registered under the same name as ourself, then defaulting to the first one registered by type alone, followed by ourself. |
java.lang.String |
getName()
|
java.lang.Integer |
getPlannedRunLevel()
The planned run level state. |
protected java.util.List<java.lang.Integer> |
getRecordersToRelease(java.util.HashMap<java.lang.Integer,org.jvnet.hk2.component.internal.runlevel.Recorder> list,
int runLevel)
|
RunLevelState<java.lang.Void> |
getState()
Returns the current state of this RunLevelService instance. |
boolean |
inhabitantChanged(HabitatListener.EventType eventType,
Habitat habitat,
Inhabitant<?> inhabitant)
Once habitat is initialized we can proceed to boot through to kernel level (-1) |
boolean |
inhabitantChanged(InhabitantListener.EventType eventType,
Inhabitant<?> inhabitant)
Called when the inhabitant has changed. |
boolean |
inhabitantIndexChanged(HabitatListener.EventType eventType,
Habitat habitat,
Inhabitant<?> inhabitant,
java.lang.String index,
java.lang.String name,
java.lang.Object service)
Called when the habitat index has changed. |
void |
interrupt()
Causes this RunLevelService to attempt to stop any in-flight proceedTo() operation. |
void |
interrupt(int runLevel)
Same as RunLevelService.interrupt(), with the option to immediately perform
a RunLevelService.proceedTo(int) following the interrupt. |
boolean |
isEnabled()
|
void |
proceedTo(int runLevel)
Causes this RunLevelService to move to the specified run level for all RunLevel instances (identified by environment), orchestrating the appropriate lifecycle events based on the given implementation strategy. |
protected void |
proceedTo(java.lang.Integer runLevel,
boolean isHardInterrupt)
|
protected ServiceContext |
serviceContext(java.lang.Exception e,
Inhabitant<?> i)
|
java.util.List<Inhabitant<?>> |
sort(java.util.List<Inhabitant<?>> inhabitants)
Called when we are responsible for handling the InhabitantSorter work. |
java.lang.String |
toString()
|
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
| Field Detail |
|---|
public static final int INITIAL_RUNLEVEL
public static final int KERNEL_RUNLEVEL
public static final java.lang.String NAME
protected final java.lang.String name
| Constructor Detail |
|---|
public DefaultRunLevelService(Habitat habitat)
protected DefaultRunLevelService(Habitat habitat,
boolean async,
java.lang.String name,
java.lang.Class<?> targetEnv,
java.util.HashMap<java.lang.Integer,org.jvnet.hk2.component.internal.runlevel.Recorder> recorders)
| Method Detail |
|---|
public java.lang.String toString()
toString in class java.lang.Objectpublic java.lang.String getDescription(boolean extended)
public java.lang.String getName()
public RunLevelState<java.lang.Void> getState()
RunLevelService
getState in interface RunLevelService<java.lang.Void>public java.lang.Class getEnvironment()
RunLevelState
getEnvironment in interface RunLevelState<java.lang.Void>public java.lang.Integer getCurrentRunLevel()
RunLevelState
getCurrentRunLevel in interface RunLevelState<java.lang.Void>public java.lang.Integer getPlannedRunLevel()
RunLevelState
getPlannedRunLevel in interface RunLevelState<java.lang.Void>RunLevelService.proceedTo(int).public java.lang.Integer getActivatingRunLevel()
public void enable(boolean enabled)
throws java.lang.IllegalStateException
Enableable
enable in interface Enableableenabled - true to enable, and false to disable
java.lang.IllegalStateExceptionpublic boolean isEnabled()
isEnabled in interface Enableable
protected boolean accept(Inhabitant<?> i,
RunLevel rl,
int activeRunLevel)
i - the inhabitantrl - the inhabitan'ts runLevelactiveRunLevel - the current runLevel
protected java.util.List<java.lang.Integer> getRecordersToRelease(java.util.HashMap<java.lang.Integer,org.jvnet.hk2.component.internal.runlevel.Recorder> list,
int runLevel)
protected void event(org.jvnet.hk2.component.internal.runlevel.DefaultRunLevelService.Worker worker,
org.jvnet.hk2.component.internal.runlevel.DefaultRunLevelService.ListenerEvent event,
ServiceContext context,
java.lang.Throwable error)
protected void event(org.jvnet.hk2.component.internal.runlevel.DefaultRunLevelService.Worker worker,
org.jvnet.hk2.component.internal.runlevel.DefaultRunLevelService.ListenerEvent event,
ServiceContext context,
java.lang.Throwable error,
boolean isHardInterrupt)
public boolean inhabitantChanged(InhabitantListener.EventType eventType,
Inhabitant<?> inhabitant)
InhabitantListener
inhabitantChanged in interface InhabitantListener
public boolean inhabitantChanged(HabitatListener.EventType eventType,
Habitat habitat,
Inhabitant<?> inhabitant)
inhabitantChanged in interface HabitatListener
public boolean inhabitantIndexChanged(HabitatListener.EventType eventType,
Habitat habitat,
Inhabitant<?> inhabitant,
java.lang.String index,
java.lang.String name,
java.lang.Object service)
HabitatListener
inhabitantIndexChanged in interface HabitatListenerpublic void proceedTo(int runLevel)
RunLevelServiceIf the RunLevel specified is the same as the current RunLevel then the RunLevelService 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. Again, see the javadoc for each implementation for details.
proceedTo in interface RunLevelService<java.lang.Void>runLevel - the run level to move to.public void interrupt()
RunLevelServiceSee the javadoc for each implementation for specific details
interrupt in interface RunLevelService<java.lang.Void>public void interrupt(int runLevel)
RunLevelServiceRunLevelService.interrupt(), with the option to immediately perform
a RunLevelService.proceedTo(int) following the interrupt.
interrupt in interface RunLevelService<java.lang.Void>runLevel - the run level to move to following the interrupt
protected void proceedTo(java.lang.Integer runLevel,
boolean isHardInterrupt)
public java.util.List<Inhabitant<?>> sort(java.util.List<Inhabitant<?>> inhabitants)
InhabitantSorter work.
The implementation returns the inhabitants argument as-is .
sort in interface InhabitantSorterinhabitants - the inhabitants to sort. This may possibly be an
unmodifiable list. Implementors are therefore cautioned to handle
this case accordingly.
public void activate(Inhabitant inhabitant)
InhabitantActivator work.
activate in interface InhabitantActivatorinhabitant - the inhabitant to activatepublic void deactivate(Inhabitant inhabitant)
InhabitantActivator work.
deactivate in interface InhabitantActivatorinhabitant - the inhabitant to releaseprotected InhabitantSorter getInhabitantSorter()
protected InhabitantActivator getInhabitantActivator()
protected ServiceContext serviceContext(java.lang.Exception e,
Inhabitant<?> i)
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||