Permalink
Browse files

Added attributes on <axon:annotation-config/> to skip unsubscribing

In some scenarios, it may not be desirable to explicitly unsubscribe handlers
from the command/event bus. A new (optional) attribute on the annotation config
element allows one to skip the unsubscribing, or set a phase in which it should
be done.

Issue #AXON-222 Fixed
  • Loading branch information...
abuijze committed Mar 31, 2014
1 parent 596f783 commit 3033e9f539ac64c1d8c6192de6a8e4649556fbd9
@@ -58,6 +58,8 @@
private ParameterResolverFactory parameterResolverFactory;
private ApplicationContext applicationContext;
private volatile boolean running = false;
+ private int phase = 0;
+ private boolean unsubscribeOnShutdown = true;
/**
* {@inheritDoc}
@@ -134,7 +136,7 @@ private Object createJavaProxyInvoker(Object javaProxy, Object target) {
* Note: this *must* be an interface. It may not be an (abstract) class.
*
* @return the interface that the adapter implements to connect the annotated method to the actual interface
- * definition
+ * definition
*/
protected abstract Class<I> getAdapterInterface();
@@ -167,8 +169,10 @@ public void start() {
@Override
public void stop() {
- for (Map.Entry<String, T> entry : managedAdapters.entrySet()) {
- unsubscribe(managedProxies.get(entry.getKey()), entry.getValue());
+ if (unsubscribeOnShutdown) {
+ for (Map.Entry<String, T> entry : managedAdapters.entrySet()) {
+ unsubscribe(managedProxies.get(entry.getKey()), entry.getValue());
+ }
}
running = false;
}
@@ -180,7 +184,16 @@ public boolean isRunning() {
@Override
public int getPhase() {
- return 0;
+ return phase;
+ }
+
+ /**
+ * Sets the phase in which handlers are subscribed and unsubscribed. Defaults to 0.
+ *
+ * @param phase The phase in which handlers are subsribed and unsubscribed
+ */
+ public void setPhase(int phase) {
+ this.phase = phase;
}
/**
@@ -190,7 +203,9 @@ public int getPhase() {
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
if (running && managedProxies.containsKey(beanName)) {
try {
- unsubscribe(managedProxies.get(beanName), managedAdapters.get(beanName));
+ if (unsubscribeOnShutdown) {
+ unsubscribe(managedProxies.get(beanName), managedAdapters.get(beanName));
+ }
} catch (Exception e) {
logger.error("An exception occurred while unsubscribing an event listener", e);
} finally {
@@ -258,6 +273,16 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
this.applicationContext = applicationContext;
}
+ /**
+ * Indicates whether handlers should be unsubscribed on shutdown. Defaults to <code>true</code>.
+ *
+ * @param unsubscribeOnShutdown <code>true</code> to unsubscribe beans explicitly from their command/event bus or
+ * <code>false</code> to shutdown without unsubscribing explicitly.
+ */
+ public void setUnsubscribeOnShutdown(boolean unsubscribeOnShutdown) {
+ this.unsubscribeOnShutdown = unsubscribeOnShutdown;
+ }
+
/**
* Sets the ParameterResolverFactory to create the Parameter Resolvers with that provide the parameter values for
* the handler methods.
@@ -57,6 +57,8 @@
* The bean name used for registering the {@link AnnotationCommandHandlerBeanPostProcessor}.
*/
private static final String COMMAND_HANDLER_BEAN_NAME = "__axon-annotation-command-handler-bean-post-processor";
+ private static final String PHASE_ATTRIBUTE = "phase";
+ private static final String UNSUBSCRIBE_ON_SHUTDOWN_ATTRIBUTE = "unsubscribe-handlers-on-shutdown";
/**
* {@inheritDoc}
@@ -79,8 +81,14 @@ private void registerAnnotationEventListenerBeanPostProcessor(Element element, P
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(AnnotationEventListenerBeanPostProcessor.class);
beanDefinition.getPropertyValues().add("parameterResolverFactory",
- getBeanReference(
- parserContext.getRegistry()));
+ getBeanReference(parserContext.getRegistry()));
+ if (element.hasAttribute(PHASE_ATTRIBUTE)) {
+ beanDefinition.getPropertyValues().add("phase", element.getAttribute(PHASE_ATTRIBUTE));
+ }
+ if (element.hasAttribute(UNSUBSCRIBE_ON_SHUTDOWN_ATTRIBUTE)) {
+ beanDefinition.getPropertyValues().add("unsubscribeOnShutdown",
+ element.getAttribute(UNSUBSCRIBE_ON_SHUTDOWN_ATTRIBUTE));
+ }
if (element.hasAttribute(EVENT_BUS_ATTRIBUTE)) {
String eventBusReference = element.getAttribute(EVENT_BUS_ATTRIBUTE);
RuntimeBeanReference beanReference = new RuntimeBeanReference(eventBusReference);
@@ -102,6 +110,14 @@ private void registerAnnotationCommandHandlerBeanPostProcessor(Element element,
beanDefinition.getPropertyValues().add("parameterResolverFactory",
getBeanReference(
parserContext.getRegistry()));
+ if (element.hasAttribute(PHASE_ATTRIBUTE)) {
+ beanDefinition.getPropertyValues().add("phase", element.getAttribute(PHASE_ATTRIBUTE));
+ }
+ if (element.hasAttribute(UNSUBSCRIBE_ON_SHUTDOWN_ATTRIBUTE)) {
+ beanDefinition.getPropertyValues().add("unsubscribeOnShutdown",
+ element.getAttribute(UNSUBSCRIBE_ON_SHUTDOWN_ATTRIBUTE));
+ }
+
if (element.hasAttribute(COMMAND_BUS_ATTRIBUTE)) {
String commandBusReference = element.getAttribute(COMMAND_BUS_ATTRIBUTE);
RuntimeBeanReference beanReference = new RuntimeBeanReference(commandBusReference);
@@ -520,8 +520,9 @@
<xsd:annotation>
<xsd:documentation>The strategy to use to claim positions in the CommandBus' buffer.
Defaults to a 'multi-threaded' strategy. If only a single thread ever produces commands
- for this Command Bus, consider using the 'single-threaded' strategy.<br/>
- Deprecated, use producer-type instead. Will be removed in AxonFramework 3.0.
+ for this Command Bus, consider using the 'single-threaded' strategy.
+ <br/>
+ Deprecated, use producer-type instead. Will be removed in AxonFramework 3.0.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
@@ -684,6 +685,20 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
+ <xsd:attribute name="unsubscribe-handlers-on-shutdown" type="xsd:boolean" use="optional" default="true">
+ <xsd:annotation>
+ <xsd:documentation>Indicates whether registered handlers should be unsubscribed from the
+ event/command bus when the application is shut down.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="phase" type="xsd:int" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Sets the Spring lifecycle phase in which the beans are subscribed and
+ unsubscribed. Defaults to 0.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
</xsd:element>
@@ -846,7 +861,7 @@
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="event-entry-store-ref" type="xsd:string">
- <xsd:annotation>
+ <xsd:annotation>
<xsd:documentation>
Reference to the Event Entry Store, which is responsible for storing the Events in the
database.
@@ -685,6 +685,20 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
+ <xsd:attribute name="unsubscribe-handlers-on-shutdown" type="xsd:boolean" use="optional" default="true">
+ <xsd:annotation>
+ <xsd:documentation>Indicates whether registered handlers should be unsubscribed from the
+ event/command bus when the application is shut down.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="phase" type="xsd:int" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>Sets the Spring lifecycle phase in which the beans are subscribed and
+ unsubscribed. Defaults to 0.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
</xsd:element>
@@ -19,7 +19,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:axon="http://www.axonframework.org/schema/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.axonframework.org/schema/core http://www.axonframework.org/schema/axon-core.xsd">
- <axon:annotation-config />
+ <axon:annotation-config unsubscribe-handlers-on-shutdown="true" phase="-200" />
<axon:event-sourcing-repository id="repository"
aggregate-type="org.axonframework.contextsupport.spring.AnnotationConfigurationBeanDefinitionParserTest_CustomParameterResolvers.StubAggregate"

0 comments on commit 3033e9f

Please sign in to comment.