|
||||||||||
| 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 boolean |
DEFAULT_ASYNC_ENABLED
|
static long |
DEFAULT_ASYNC_WAIT
|
static String |
DEFAULT_NAME
|
static Class<?> |
DEFAULT_SCOPE
|
static int |
INITIAL_RUNLEVEL
|
protected String |
name
|
| Constructor Summary | |
|---|---|
DefaultRunLevelService(SimpleServiceLocator habitat)
|
|
DefaultRunLevelService(SimpleServiceLocator habitat,
boolean async,
String name,
Class<?> targetScope,
HashMap<Integer,org.jvnet.hk2.component.internal.runlevel.Recorder> recorders)
|
|
| Method Summary | ||
|---|---|---|
protected boolean |
accept(AbstractInhabitantImpl<?> i,
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 |
awaitCompletion()
Await completion for all AsyncPostConstruct service types |
|
void |
awaitCompletion(long timeout,
TimeUnit unit)
No-op, since we are not a MultiThreadedInhabitantActivator |
|
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,
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,
Throwable error,
boolean isHardInterrupt)
|
|
Integer |
getActivatingRunLevel()
|
|
Integer |
getCurrentRunLevel()
The current run level state. |
|
String |
getDescription(boolean extended)
|
|
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. |
|
protected Collection<RunLevelListener> |
getListeners()
|
|
String |
getName()
|
|
RunLevelService<?> |
getParent()
|
|
Integer |
getPlannedRunLevel()
The planned run level state. |
|
protected List<Integer> |
getRecordersToRelease(HashMap<Integer,org.jvnet.hk2.component.internal.runlevel.Recorder> list,
int runLevel)
|
|
protected Integer |
getRunLevel(AbstractInhabitantImpl<?> i)
Attempts to obtain the RunLevel value from the metadata() instead of from the annotation which requires a class load. |
|
String |
getScopeName()
The scope value for this state. |
|
RunLevelState<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,
String index,
String name,
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 |
isDefault()
|
|
boolean |
isEnabled()
|
|
protected
|
narrow(Collection<Inhabitant<T>> inhabs)
narrow down and return the collection for those runLevelScopes that match |
|
void |
proceedTo(int runLevel)
Causes this RunLevelService to move to the specified run level for all RunLevel instances (identified by scope), orchestrating the appropriate lifecycle events based on the given implementation strategy. |
|
protected void |
proceedTo(Integer runLevel,
boolean isHardInterrupt)
|
|
protected ServiceContext |
serviceContext(Exception e,
Inhabitant<?> i)
|
|
void |
setInhabitantActivator(InhabitantActivator activator)
Overrides the default behavior of getting the inhabitant activator from the habitat to use a stand-in activator instead. |
|
void |
setInhabitantSorter(InhabitantSorter sorter)
Overrides the default behavior of getting the inhabitant sorter from the habitat to use a stand-in sorter instead. |
|
void |
setListener(RunLevelListener listener)
Overrides the default behavior of getting all listeners from the habitat to use a stand-in listener instead. |
|
void |
setParent(RunLevelService<?> parent)
|
|
List<Inhabitant<?>> |
sort(List<Inhabitant<?>> inhabitants)
Called when we are responsible for handling the InhabitantSorter
work. |
|
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 String DEFAULT_NAME
public static final boolean DEFAULT_ASYNC_ENABLED
public static final long DEFAULT_ASYNC_WAIT
public static final Class<?> DEFAULT_SCOPE
protected final String name
| Constructor Detail |
|---|
public DefaultRunLevelService(SimpleServiceLocator habitat)
public DefaultRunLevelService(SimpleServiceLocator habitat,
boolean async,
String name,
Class<?> targetScope,
HashMap<Integer,org.jvnet.hk2.component.internal.runlevel.Recorder> recorders)
| Method Detail |
|---|
public String toString()
toString in class Objectpublic boolean isDefault()
public String getDescription(boolean extended)
public void setParent(RunLevelService<?> parent)
public RunLevelService<?> getParent()
public String getName()
public RunLevelState<Void> getState()
RunLevelService
getState in interface RunLevelService<Void>public String getScopeName()
RunLevelState
getScopeName in interface RunLevelState<Void>public Integer getCurrentRunLevel()
RunLevelState
getCurrentRunLevel in interface RunLevelState<Void>public Integer getPlannedRunLevel()
RunLevelState
getPlannedRunLevel in interface RunLevelState<Void>RunLevelService.proceedTo(int).public Integer getActivatingRunLevel()
public void enable(boolean enabled)
throws IllegalStateException
Enableable
enable in interface Enableableenabled - true to enable, and false to disable
IllegalStateExceptionpublic boolean isEnabled()
isEnabled in interface Enableable
protected boolean accept(AbstractInhabitantImpl<?> i,
int activeRunLevel)
i - the inhabitantactiveRunLevel - the current runLevel
protected List<Integer> getRecordersToRelease(HashMap<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,
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,
Throwable error,
boolean isHardInterrupt)
public void setListener(RunLevelListener listener)
listener - the alternative, stand-in listenerprotected Collection<RunLevelListener> getListeners()
protected <T> Collection<T> narrow(Collection<Inhabitant<T>> inhabs)
public boolean inhabitantChanged(InhabitantListener.EventType eventType,
Inhabitant<?> inhabitant)
InhabitantListener
inhabitantChanged in interface InhabitantListenerprotected Integer getRunLevel(AbstractInhabitantImpl<?> i)
i - the inhabitant to get the runLevel for
public boolean inhabitantChanged(HabitatListener.EventType eventType,
Habitat habitat,
Inhabitant<?> inhabitant)
inhabitantChanged in interface HabitatListener
public boolean inhabitantIndexChanged(HabitatListener.EventType eventType,
Habitat habitat,
Inhabitant<?> inhabitant,
String index,
String name,
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<Void>runLevel - the run level to move to.public void interrupt()
RunLevelServiceSee the javadoc for each implementation for specific details
interrupt in interface RunLevelService<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<Void>runLevel - the run level to move to following the interrupt
protected void proceedTo(Integer runLevel,
boolean isHardInterrupt)
public List<Inhabitant<?>> sort(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 release
public void awaitCompletion()
throws InterruptedException,
ExecutionException,
TimeoutException
AsyncPostConstruct service types
awaitCompletion in interface InhabitantActivatorInterruptedException
ExecutionException
TimeoutException
public void awaitCompletion(long timeout,
TimeUnit unit)
throws InterruptedException,
TimeoutException,
ExecutionException
MultiThreadedInhabitantActivator
awaitCompletion in interface InhabitantActivatorInterruptedException
TimeoutException
ExecutionExceptionpublic void setInhabitantSorter(InhabitantSorter sorter)
sorter - the alternative, stand-in sorterprotected InhabitantSorter getInhabitantSorter()
public void setInhabitantActivator(InhabitantActivator activator)
activator - the alternative, stand-in activatorprotected InhabitantActivator getInhabitantActivator()
protected ServiceContext serviceContext(Exception e,
Inhabitant<?> i)
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||