Class LazyCreationServiceImpl
- java.lang.Object
-
- com.composum.sling.core.concurrent.LazyCreationServiceImpl
-
- All Implemented Interfaces:
LazyCreationService
public class LazyCreationServiceImpl extends Object implements LazyCreationService
Implementation of theLazyCreationService
. UsesSequencerService
to at least locally avoid conflicts by locking the parent of the created resource. If two nodes of a cluster try to create the same resource, anyway, one of the transactions is rolled back. It will just be logged and ignored.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interface
LazyCreationServiceImpl.Configuration
-
Nested classes/interfaces inherited from interface com.composum.sling.core.concurrent.LazyCreationService
LazyCreationService.CreationStrategy, LazyCreationService.InitializationStrategy, LazyCreationService.ParentCreationStrategy, LazyCreationService.RetrievalStrategy<T>
-
-
Field Summary
Fields Modifier and Type Field Description protected LazyCreationServiceImpl.Configuration
config
protected org.apache.sling.api.resource.ResourceResolverFactory
resolverFactory
protected SequencerService
sequencer
-
Fields inherited from interface com.composum.sling.core.concurrent.LazyCreationService
IDENTITY_RETRIEVER
-
-
Constructor Summary
Constructors Constructor Description LazyCreationServiceImpl()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description protected void
activate(LazyCreationServiceImpl.Configuration config)
protected org.apache.sling.api.resource.ResourceResolver
createAdministrativeResolver()
Make administrative resolver with the necessary permissions to create stuff.protected org.apache.sling.api.resource.Resource
createUninitializedResource(org.apache.sling.api.resource.ResourceResolver adminResolver, org.apache.sling.api.resource.Resource parentResource, String path, LazyCreationService.CreationStrategy creator)
protected void
deactivate()
protected @NotNull LazyCreationServiceImpl.Configuration
getConfiguration()
<T> T
getOrCreate(org.apache.sling.api.resource.ResourceResolver resolver, String path, LazyCreationService.RetrievalStrategy<T> getter, LazyCreationService.CreationStrategy creator, LazyCreationService.InitializationStrategy initializer, LazyCreationService.ParentCreationStrategy parentCreationStrategy)
Retrieves a resource or applies a creation and initialization strategy to be carried out with an admin resolver to create it, for resource intensive initialization processes that should not performed twice in the cluster.<T> T
getOrCreate(org.apache.sling.api.resource.ResourceResolver resolver, String path, LazyCreationService.RetrievalStrategy<T> getter, LazyCreationService.CreationStrategy creator, LazyCreationService.InitializationStrategy initializer, Map<String,Object> parentProperties)
Retrieves a resource or applies a creation and initialization strategy to be carried out with an admin resolver to create it, for resource intensive initialization processes that should not performed twice in the cluster.<T> T
getOrCreate(org.apache.sling.api.resource.ResourceResolver resolver, String path, LazyCreationService.RetrievalStrategy<T> getter, LazyCreationService.CreationStrategy creator, LazyCreationService.ParentCreationStrategy parentCreationStrategy)
Retrieves a resource or applies a creation strategy to be carried out with an admin resolver to create it.<T> T
getOrCreate(org.apache.sling.api.resource.ResourceResolver resolver, String path, LazyCreationService.RetrievalStrategy<T> getter, LazyCreationService.CreationStrategy creator, Map<String,Object> parentProperties)
Retrieves a resource or applies a creation strategy to be carried out with an admin resolver to create it.protected void
initializeResource(org.apache.sling.api.resource.ResourceResolver adminResolver, String path, LazyCreationService.InitializationStrategy initializer, javax.jcr.lock.LockManager lockManager)
boolean
isInitialized(org.apache.sling.api.resource.Resource resource)
For resources created byLazyCreationService.getOrCreate(ResourceResolver, String, RetrievalStrategy, CreationStrategy, InitializationStrategy, ParentCreationStrategy)
orLazyCreationService.getOrCreate(ResourceResolver, String, RetrievalStrategy, CreationStrategy, InitializationStrategy, Map)
, this returns true when the initialization process is finished.protected void
refreshSession(org.apache.sling.api.resource.ResourceResolver resolver, boolean keepChanges)
Resets unmodified resources to the currently saved state.protected boolean
resourceIsInitialized(org.apache.sling.api.resource.ResourceResolver resolver, String path)
protected org.apache.sling.api.resource.Resource
safeCreateParent(org.apache.sling.api.resource.ResourceResolver adminResolver, String path, int level, LazyCreationService.ParentCreationStrategy parentCreationStrategy)
Tries to create the parent while catching exceptions that could be triggered by someone having created it in parallel in the meantime.protected javax.jcr.lock.Lock
tryToLockResource(String path, org.apache.sling.api.resource.ResourceResolver adminResolver)
If it is not initialized, try to lock it for up toLazyCreationServiceImpl.Configuration.lazycreation_maximumlockwait()
.org.apache.sling.api.resource.Resource
waitForInitialization(org.apache.sling.api.resource.ResourceResolver resolver, String path)
For resources created byLazyCreationService.getOrCreate(ResourceResolver, String, RetrievalStrategy, CreationStrategy, InitializationStrategy, ParentCreationStrategy)
orLazyCreationService.getOrCreate(ResourceResolver, String, RetrievalStrategy, CreationStrategy, InitializationStrategy, Map)
, this returns the resource when the initialization process is finished.
-
-
-
Field Detail
-
resolverFactory
protected org.apache.sling.api.resource.ResourceResolverFactory resolverFactory
-
sequencer
protected SequencerService sequencer
-
config
protected volatile LazyCreationServiceImpl.Configuration config
-
-
Method Detail
-
getOrCreate
public <T> T getOrCreate(org.apache.sling.api.resource.ResourceResolver resolver, String path, LazyCreationService.RetrievalStrategy<T> getter, LazyCreationService.CreationStrategy creator, Map<String,Object> parentProperties) throws javax.jcr.RepositoryException
Description copied from interface:LazyCreationService
Retrieves a resource or applies a creation strategy to be carried out with an admin resolver to create it.It is an error if getter still returns null after creator is executed.
- Specified by:
getOrCreate
in interfaceLazyCreationService
- Type Parameters:
T
- the type theLazyCreationService.RetrievalStrategy
returns.- Parameters:
resolver
- the users resolver. If the resource needed to be created, that is getter returns null, we create it and call aSession.refresh(boolean)
(true) on this session before we call getter again. Passed as a parameter to getter.path
- the absolute path at which the creator creates the resource. Passed as a parameter to getter and creator.getter
- side effect free function to retrieve the resource. This can be executed several times in this process.creator
- a strategy to create the resource. Only called when the resource doesn't exist. Is only called after the parent of path is created.parentProperties
- properties with which non-existing parents of path are created (ResourceResolver.create(Resource, String, Map)
).- Returns:
- the object.
- Throws:
javax.jcr.RepositoryException
-
getOrCreate
public <T> T getOrCreate(org.apache.sling.api.resource.ResourceResolver resolver, String path, LazyCreationService.RetrievalStrategy<T> getter, LazyCreationService.CreationStrategy creator, LazyCreationService.InitializationStrategy initializer, Map<String,Object> parentProperties) throws javax.jcr.RepositoryException, org.apache.sling.api.resource.PersistenceException
Description copied from interface:LazyCreationService
Retrieves a resource or applies a creation and initialization strategy to be carried out with an admin resolver to create it, for resource intensive initialization processes that should not performed twice in the cluster. The resource is locked for the cluster withLockManager
during that time.It is an error if getter still returns null after creator is executed.
- Specified by:
getOrCreate
in interfaceLazyCreationService
- Type Parameters:
T
- the type theLazyCreationService.RetrievalStrategy
returns.- Parameters:
resolver
- the users resolver. If the resource needed to be created, that is getter returns null, we create it and call aSession.refresh(boolean)
(true) on this session before we call getter again. Passed as a parameter to getter.path
- the absolute path at which the creator creates the resource. Passed as a parameter to getter and creator.getter
- side effect free function to retrieve the resource. This can be executed several times in this process.creator
- a strategy to create the resource. Only called when the resource doesn't exist. Is only called after the parent of path is created. This should not perform any resource intensive actions - these should be done in initializer.initializer
- the resource intensive part of the resource creationparentProperties
- properties with which non-existing parents of path are created (ResourceResolver.create(Resource, String, Map)
).- Returns:
- the object.
- Throws:
javax.jcr.RepositoryException
org.apache.sling.api.resource.PersistenceException
-
getOrCreate
public <T> T getOrCreate(org.apache.sling.api.resource.ResourceResolver resolver, String path, LazyCreationService.RetrievalStrategy<T> getter, LazyCreationService.CreationStrategy creator, LazyCreationService.ParentCreationStrategy parentCreationStrategy) throws javax.jcr.RepositoryException
Description copied from interface:LazyCreationService
Retrieves a resource or applies a creation strategy to be carried out with an admin resolver to create it.It is an error if getter still returns null after creator is executed.
- Specified by:
getOrCreate
in interfaceLazyCreationService
- Type Parameters:
T
- the type theLazyCreationService.RetrievalStrategy
returns.- Parameters:
resolver
- the users resolver. If the resource needed to be created, that is getter returns null, we create it and call aSession.refresh(boolean)
(true) on this session before we call getter again. Passed as a parameter to getter.path
- the absolute path at which the creator creates the resource. Passed as a parameter to getter and creator.getter
- side effect free function to retrieve the resource. This can be executed several times in this process.creator
- a strategy to create the resource. Only called when the resource doesn't exist. Is only called after the parent of path is created.parentCreationStrategy
- strategy with which non-existing parents of path are created.- Returns:
- the object.
- Throws:
javax.jcr.RepositoryException
-
getOrCreate
public <T> T getOrCreate(org.apache.sling.api.resource.ResourceResolver resolver, String path, LazyCreationService.RetrievalStrategy<T> getter, LazyCreationService.CreationStrategy creator, LazyCreationService.InitializationStrategy initializer, LazyCreationService.ParentCreationStrategy parentCreationStrategy) throws javax.jcr.RepositoryException, org.apache.sling.api.resource.PersistenceException
Retrieves a resource or applies a creation and initialization strategy to be carried out with an admin resolver to create it, for resource intensive initialization processes that should not performed twice in the cluster. The resource is locked for the cluster withLockManager
during that time.It is an error if getter still returns null after creator is executed.
We create the item in two steps. First, it is created and JCR-locked. Then it is initialized and JCR-unlocked. So, when trying to retrieve the item, we check that it is not locked, too, to verify that it is not in construction. The resource is assumed fully initialized if it exists and is not locked. We put the current time into lastupdatetime to keep track how long it is locked and whether the lock must be broken. Since we can only lock the item after the creation is committed, we set jcr:lastModified only after locking and check this must be set when retrieving the item.
If the item exists but is locked, we wait until it is unlocked and then return what's there. If we exceed the
LazyCreationServiceImpl.Configuration.lazycreation_maximumlockwait()
when waiting for the lock, we break the lock and create it ourselves.- Specified by:
getOrCreate
in interfaceLazyCreationService
- Type Parameters:
T
- the type theLazyCreationService.RetrievalStrategy
returns.- Parameters:
resolver
- the users resolver. If the resource needed to be created, that is getter returns null, we create it and call aSession.refresh(boolean)
(true) on this session before we call getter again. Passed as a parameter to getter.path
- the absolute path at which the creator creates the resource. Passed as a parameter to getter and creator.getter
- side effect free function to retrieve the resource. This can be executed several times in this process.creator
- a strategy to create the resource. Only called when the resource doesn't exist. Is only called after the parent of path is created.initializer
- the resource intensive part of the resource creationparentCreationStrategy
- strategy with which non-existing parents of path are created.- Returns:
- the object.
- Throws:
javax.jcr.RepositoryException
org.apache.sling.api.resource.PersistenceException
-
createUninitializedResource
protected org.apache.sling.api.resource.Resource createUninitializedResource(org.apache.sling.api.resource.ResourceResolver adminResolver, org.apache.sling.api.resource.Resource parentResource, String path, LazyCreationService.CreationStrategy creator)
-
tryToLockResource
protected javax.jcr.lock.Lock tryToLockResource(String path, org.apache.sling.api.resource.ResourceResolver adminResolver) throws javax.jcr.RepositoryException, org.apache.sling.api.resource.PersistenceException
If it is not initialized, try to lock it for up toLazyCreationServiceImpl.Configuration.lazycreation_maximumlockwait()
.- Returns:
- the lock it is locked, null if it is already initialized by someone else
- Throws:
javax.jcr.lock.LockException
- if we couldn't get a lockjavax.jcr.RepositoryException
org.apache.sling.api.resource.PersistenceException
-
initializeResource
protected void initializeResource(org.apache.sling.api.resource.ResourceResolver adminResolver, String path, LazyCreationService.InitializationStrategy initializer, javax.jcr.lock.LockManager lockManager)
-
resourceIsInitialized
protected boolean resourceIsInitialized(org.apache.sling.api.resource.ResourceResolver resolver, String path) throws javax.jcr.RepositoryException
- Throws:
javax.jcr.RepositoryException
-
isInitialized
public boolean isInitialized(org.apache.sling.api.resource.Resource resource) throws javax.jcr.RepositoryException
Description copied from interface:LazyCreationService
For resources created byLazyCreationService.getOrCreate(ResourceResolver, String, RetrievalStrategy, CreationStrategy, InitializationStrategy, ParentCreationStrategy)
orLazyCreationService.getOrCreate(ResourceResolver, String, RetrievalStrategy, CreationStrategy, InitializationStrategy, Map)
, this returns true when the initialization process is finished.- Specified by:
isInitialized
in interfaceLazyCreationService
- Throws:
javax.jcr.RepositoryException
-
waitForInitialization
public org.apache.sling.api.resource.Resource waitForInitialization(org.apache.sling.api.resource.ResourceResolver resolver, String path) throws javax.jcr.RepositoryException
Description copied from interface:LazyCreationService
For resources created byLazyCreationService.getOrCreate(ResourceResolver, String, RetrievalStrategy, CreationStrategy, InitializationStrategy, ParentCreationStrategy)
orLazyCreationService.getOrCreate(ResourceResolver, String, RetrievalStrategy, CreationStrategy, InitializationStrategy, Map)
, this returns the resource when the initialization process is finished. If the resource is in creation, this waits a while.- Specified by:
waitForInitialization
in interfaceLazyCreationService
- Returns:
- the initialized resource, or null if we couldn't find it or it took too long.
- Throws:
javax.jcr.RepositoryException
-
safeCreateParent
protected org.apache.sling.api.resource.Resource safeCreateParent(org.apache.sling.api.resource.ResourceResolver adminResolver, String path, int level, LazyCreationService.ParentCreationStrategy parentCreationStrategy) throws javax.jcr.RepositoryException
Tries to create the parent while catching exceptions that could be triggered by someone having created it in parallel in the meantime. Includes commit and locks path on this node.- Throws:
javax.jcr.RepositoryException
-
refreshSession
protected void refreshSession(org.apache.sling.api.resource.ResourceResolver resolver, boolean keepChanges)
Resets unmodified resources to the currently saved state.
-
createAdministrativeResolver
protected org.apache.sling.api.resource.ResourceResolver createAdministrativeResolver()
Make administrative resolver with the necessary permissions to create stuff. Remember to close it!
-
activate
protected void activate(LazyCreationServiceImpl.Configuration config)
-
deactivate
protected void deactivate()
-
getConfiguration
@NotNull protected @NotNull LazyCreationServiceImpl.Configuration getConfiguration()
-
-