8.3. Using Custom Lockers
Overview
If one of the provided lockers are not sufficient for your needs, you can implement a custom locker. All lockers are implementations of the Red Hat JBoss A-MQ
Locker
interface. They are attached to the persistence adapter as a spring bean in the locker
element.
Interface
All lockers are implementations of the
org.apache.activemq.broker.Locker
interface. Implementing the Locker
interface involves implementing seven methods:
boolean keepAlive()
throws IOException;Used by the lock's timer to ensure that the lock is still active. If this returns false, the broker is shutdown.void setLockAcquireSleepInterval(long lockAcquireSleepInterval);
Sets the delay, in milliseconds, between attempts to acquire the lock.lockAcquireSleepInterval
is typically supplied through the locker's XML configuration.public void setName(String name);
Sets the name of the lock.public void setFailIfLocked(boolean failIfLocked);
Sets the property that determines if the broker should fail if it cannot acquire the lock at start-up.failIfLocked
is typically supplied through the locker's XML configuration.public void configure(PersistenceAdapter persistenceAdapter)
throws IOException;Allows the locker to access the persistence adapter's configuration. This can be used to obtain the location of the message store.void start();
Executed when the locker is initialized by the broker. This is where the bulk of the locker's implementation logic should be placed.void stop();
Executed when the broker is shutting down. This method is useful for cleaning up any resources and ensuring that all of the locks are released before the broker is completely shutdown.
Using AbstractLocker
To simplify the implementation of lockers, Red Hat JBoss A-MQ includes a default locker implementation,
org.apache.activemq.broker.AbstractLocker
, that serves as the base for all of the provided lockers. It is recommended that all custom locker implementations also extand the AbstractLocker
class instead of implementing the plain Locker
interface.
AbstractLocker
provides default implementations for the following methods:
keepAlive()
—returnstrue
setLockAcquireSleepInterval()
—sets the parameter to the value of the locker beans'lockAcquireSleepInterval
if provided or to10000
if the parameter is not providedsetName()
setFailIfLocked()
—sets the parameter to the value of the locker beans'failIfLocked
if provided or tofalse
if the parameter is not providedstart()
—starts the locker after calling two additional methodsImportantThis method should not be overridden.stop()
—stops the locker and adds a method that is called before the locker is shutdown and one that is called after the locker is shutdownImportantThis method should not be overridden.
AbstractLocker
adds two methods that must be implemented:
void doStart()
throws Exception;Executed as the locker is started. This is where most of the locking logic is implemented.void doStop(ServiceStopper stopper)
throws Exception;Executed as the locker is stopped. This is where locks are released and resources are cleaned up.
In addition,
AbstractLocker
adds two methods that can be implemented to provide additional set up and clean up:
void preStart()
throws Exception;Executed before the locker is started. This method can be used to initialize resources needed by the lock. It can also be used to perform any other actions that need to be performed before the locks are created.void doStop(ServiceStopper stopper)
throws Exception;Executed after the locker is stopped. This method can be used to clean up any resources that are left over after the locker is stopped.
Configuration
Custom lockers are added to a persistence adapter by adding the bean configuration to the persistence adapter's
locker
element as shown in Example 8.6, “Adding a Custom Locker to a Persistence Adapter”.
Example 8.6. Adding a Custom Locker to a Persistence Adapter
<persistenceAdapter> <kahaDB directory = "target/activemq-data"> <locker> <bean class="my.custom.LockerImpl"> <property name="lockAcquireSleepInterval" value="5000" /> ... </bean </locker> </kahaDB> </persistenceAdapter>