Class ImmediateHelper
- java.lang.Object
-
- org.glassfish.hk2.internal.ImmediateHelper
-
- All Implemented Interfaces:
java.lang.Runnable
,DynamicConfigurationListener
,ErrorService
,ImmediateController
,ValidationService
,Validator
@Singleton @Visibility(LOCAL) public class ImmediateHelper extends java.lang.Object implements DynamicConfigurationListener, java.lang.Runnable, ValidationService, ErrorService, Validator, ImmediateController
The implementation of the immediate context. This should NOT be added automatically, and hence is not annotated withService
This implementation uses a lot of facilities of hk2, so lets explain each one.
The thing that makes Immediate services immediate is that they are started as soon as they are noticed. This is done by implementing the DynamicConfigurationListener, as it will get notified when a configuration has changed. However, since the creation of user services can take an arbitrarily long time it is better to do that work on a separate thread, which is why we implement Runnable. The run method is the method that will pull from the queue of work and instantiate (and destroy) the immediate services.
However, there is also a desire to be highly efficient. This means we should not be creating this thread if there is no work for the thread to do. For this to work we need to know which configuration changes have added or removed an Immediate service. To know this we have implemented the Validation service and Validator. The validation service records the thread id of a configuration operation that is adding or removing services. This thread id goes into a map. But we have to be sure that the map does not grow without bound. To do this we clear the map both when the configuration service has succeeded (in the DynamicConfigurationListener) and when the configuration service has failed (in the ErrorService). This is why we have implemented the ErrorService.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static class
ImmediateHelper.ImmediateThread
private static class
ImmediateHelper.ImmediateThreadFactory
-
Nested classes/interfaces inherited from interface org.glassfish.hk2.api.ImmediateController
ImmediateController.ImmediateServiceState
-
-
Field Summary
Fields Modifier and Type Field Description private java.util.concurrent.Executor
currentExecutor
private ImmediateController.ImmediateServiceState
currentState
private long
decayTime
private static java.util.concurrent.Executor
DEFAULT_EXECUTOR
private boolean
firstTime
private ImmediateContext
immediateContext
private ServiceLocator
locator
private boolean
outstandingJob
private java.lang.Object
queueLock
private static java.util.concurrent.ThreadFactory
THREAD_FACTORY
private boolean
threadAvailable
private java.util.HashSet<java.lang.Long>
tidsWithWork
private boolean
waitingForWork
-
Constructor Summary
Constructors Modifier Constructor Description private
ImmediateHelper(ServiceLocator serviceLocator, ImmediateContext immediateContext)
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
configurationChanged()
This method is called when the set of descriptors in this service locator has been changed.private void
doWorkIfWeHaveSome()
Must have queueLock heldjava.util.concurrent.Executor
getExecutor()
Returns the executor that is currently in use by the Immediate subsystemprivate java.util.List<ActiveDescriptor<?>>
getImmediateServices()
ImmediateController.ImmediateServiceState
getImmediateState()
Returns the state the system is currently running underFilter
getLookupFilter()
This filter will be run at least once per descriptor at the point that the descriptor is being looked up, either with theServiceLocator
API or due to an @Inject resolution.long
getThreadInactivityTimeout()
Returns the time in milliseconds a thread will wait for new Immediate services before dyingValidator
getValidator()
Returns theValidator
that will be run whenever aDescriptor
that passed the filter is to be looked up with the API or injected into an injection point, or on any bind or unbind operation.private boolean
hasWork()
Must have queueLock heldvoid
onFailure(ErrorInformation errorInformation)
This method is called when a failure occurs in the system.void
run()
This thread will wait twenty seconds for new work to come in, and then kill itselfvoid
setExecutor(java.util.concurrent.Executor executor)
Sets the executor to be used by the Immediate subsystem.void
setImmediateState(ImmediateController.ImmediateServiceState state)
Sets the state the system is currently running undervoid
setThreadInactivityTimeout(long timeInMillis)
Sets the time in milliseconds a thread will wait for new Immediate services before dyingboolean
validate(ValidationInformation info)
This method is called whenever it has been determined that a validating class is to be injected into an injection point, or when a descriptor is being looked up explicitly with the API, or a descriptor is being bound or unbound into the registry.
-
-
-
Field Detail
-
THREAD_FACTORY
private static final java.util.concurrent.ThreadFactory THREAD_FACTORY
-
DEFAULT_EXECUTOR
private static final java.util.concurrent.Executor DEFAULT_EXECUTOR
-
locator
private final ServiceLocator locator
-
immediateContext
private final ImmediateContext immediateContext
-
tidsWithWork
private final java.util.HashSet<java.lang.Long> tidsWithWork
-
queueLock
private final java.lang.Object queueLock
-
threadAvailable
private boolean threadAvailable
-
outstandingJob
private boolean outstandingJob
-
waitingForWork
private boolean waitingForWork
-
firstTime
private boolean firstTime
-
currentState
private ImmediateController.ImmediateServiceState currentState
-
currentExecutor
private java.util.concurrent.Executor currentExecutor
-
decayTime
private long decayTime
-
-
Constructor Detail
-
ImmediateHelper
@Inject private ImmediateHelper(ServiceLocator serviceLocator, ImmediateContext immediateContext)
-
-
Method Detail
-
hasWork
private boolean hasWork()
Must have queueLock held- Returns:
- true if there is work to be done
-
doWorkIfWeHaveSome
private void doWorkIfWeHaveSome()
Must have queueLock held
-
configurationChanged
public void configurationChanged()
Description copied from interface:DynamicConfigurationListener
This method is called when the set of descriptors in this service locator has been changed. Changes to parent service locators descriptors will not be reported. These services are called back on the thread doing theDynamicConfiguration.commit()
so care should be taken to do any work quickly. Any exception thrown from this method will be ignored. A commit that failed will not be reported to this method- Specified by:
configurationChanged
in interfaceDynamicConfigurationListener
-
getLookupFilter
public Filter getLookupFilter()
Description copied from interface:ValidationService
This filter will be run at least once per descriptor at the point that the descriptor is being looked up, either with theServiceLocator
API or due to an @Inject resolution. The decision made by this filter will be cached and used every time that Descriptor is subsequently looked up. No validation checks should be done in the returned filter, it is purely meant to limit theDescriptor
s that are passed into the validator.Descriptors passed to this filter may or may not be reified. The filter should try as much as possible to do its work without reifying the descriptor.
The filter may be run more than once on a descriptor if some condition caused the cache of results per descriptor to become invalidated.
- Specified by:
getLookupFilter
in interfaceValidationService
- Returns:
- The filter to be used to determine if the validators associated with this
service should be called when the passed in
Descriptor
is looked up
-
getValidator
public Validator getValidator()
Description copied from interface:ValidationService
Returns theValidator
that will be run whenever aDescriptor
that passed the filter is to be looked up with the API or injected into an injection point, or on any bind or unbind operation. If this method returns false then the operation will not proceed.- Specified by:
getValidator
in interfaceValidationService
- Returns:
- A non-null validator
-
onFailure
public void onFailure(ErrorInformation errorInformation) throws MultiException
Description copied from interface:ErrorService
This method is called when a failure occurs in the system. This method may use anyServiceLocator
api. For example, an implementation of this method might want to remove a descriptor from the registry if the error can be determined to be a permanent failure.- Specified by:
onFailure
in interfaceErrorService
- Parameters:
errorInformation
- Information about the error that occurred- Throws:
MultiException
- if this method throws an exception that exception will be thrown back to the caller wrapped in another MultiException if the error is of typeErrorType.FAILURE_TO_REIFY
. If the error is of typeErrorType.DYNAMIC_CONFIGURATION_FAILURE
orErrorType.SERVICE_CREATION_FAILURE
orErrorType.SERVICE_DESTRUCTION_FAILURE
then any exception thrown from this method is ignored and the original exception is thrown back to the caller
-
validate
public boolean validate(ValidationInformation info)
Description copied from interface:Validator
This method is called whenever it has been determined that a validating class is to be injected into an injection point, or when a descriptor is being looked up explicitly with the API, or a descriptor is being bound or unbound into the registry.The candidate descriptor being passed in may not have yet been reified. If possible, this method should do its work without reifying the descriptor. However, if it is necessary to reify the descriptor, it should be done with the ServiceLocator.reifyDescriptor method.
The operation will determine what operation is being performed. In the BIND or UNBIND cases the Injectee will be null. In the LOOKUP case the Injectee will be non-null if this is being done as part of an injection point. In the LOOKUP case the Injectee will be null if this is being looked up directly from the
ServiceLocator
API, in which case the caller of the lookup method will be on the call frame.
-
run
public void run()
This thread will wait twenty seconds for new work to come in, and then kill itself- Specified by:
run
in interfacejava.lang.Runnable
-
getExecutor
public java.util.concurrent.Executor getExecutor()
Description copied from interface:ImmediateController
Returns the executor that is currently in use by the Immediate subsystem- Specified by:
getExecutor
in interfaceImmediateController
- Returns:
- The current executor in use by the controller. Will not return null since a default executor is used and returned by this call even if setExecutor is called with null
-
setExecutor
public void setExecutor(java.util.concurrent.Executor executor) throws java.lang.IllegalStateException
Description copied from interface:ImmediateController
Sets the executor to be used by the Immediate subsystem. If set to null a default executor will be used. This may only be called when the Immediate service is suspended- Specified by:
setExecutor
in interfaceImmediateController
- Parameters:
executor
- The executor to be used when scheduling work. If null a default executor implementation will be used- Throws:
java.lang.IllegalStateException
- if this is called when the Immediate service is not in suspended state
-
getThreadInactivityTimeout
public long getThreadInactivityTimeout()
Description copied from interface:ImmediateController
Returns the time in milliseconds a thread will wait for new Immediate services before dying- Specified by:
getThreadInactivityTimeout
in interfaceImmediateController
- Returns:
- The time in milliseconds a thread will wait for new Immediate service before dying
-
setThreadInactivityTimeout
public void setThreadInactivityTimeout(long timeInMillis) throws java.lang.IllegalStateException
Description copied from interface:ImmediateController
Sets the time in milliseconds a thread will wait for new Immediate services before dying- Specified by:
setThreadInactivityTimeout
in interfaceImmediateController
- Parameters:
timeInMillis
- The time in milliseconds a thread will wait for new Immediate service before dying- Throws:
java.lang.IllegalStateException
-
getImmediateState
public ImmediateController.ImmediateServiceState getImmediateState()
Description copied from interface:ImmediateController
Returns the state the system is currently running under- Specified by:
getImmediateState
in interfaceImmediateController
- Returns:
- The current state of the ImmediateService
-
setImmediateState
public void setImmediateState(ImmediateController.ImmediateServiceState state)
Description copied from interface:ImmediateController
Sets the state the system is currently running under- Specified by:
setImmediateState
in interfaceImmediateController
- Parameters:
state
- The new state of the ImmediateService
-
getImmediateServices
private java.util.List<ActiveDescriptor<?>> getImmediateServices()
-
-