INT-3950: Fix Aggregator documentation

JIRA: https://jira.spring.io/browse/INT-3950

Previously there was a mention of the `MessageGroupStore.expireMessageGroup(groupId)` which just doesn't existing
in the Framework and never has been there.

* Fix the documentation for the existing `MessageGroupStore.expireMessageGroups(timeout)`.
Although the mention there of `Control Bus` requires to have `@ManagedOperation` on the method.

* Add `@ManagedOperation` for the `MessageGroupStore.expireMessageGroups(timeout)` and confirm with the test-case: `AggregatorWithMessageStoreParserTests`
* Fix the same docs in the XSD for `<aggregator>`
* Fix other typos in the `aggregator.adoc` and `resequencer.adoc`

Conflicts:
	spring-integration-core/src/main/java/org/springframework/integration/store/AbstractMessageGroupStore.java

Conflicts:
	spring-integration-core/src/main/java/org/springframework/integration/store/AbstractMessageGroupStore.java
	src/reference/asciidoc/aggregator.adoc
	src/reference/asciidoc/resequencer.adoc

Conflicts:
	spring-integration-core/src/main/java/org/springframework/integration/store/AbstractMessageGroupStore.java
	spring-integration-core/src/main/java/org/springframework/integration/store/MessageGroupStore.java
	spring-integration-mongodb/src/main/java/org/springframework/integration/mongodb/store/ConfigurableMongoDbMessageStore.java
This commit is contained in:
Artem Bilan
2016-02-05 11:08:14 -05:00
parent 32981ded89
commit 1f5f119442
5 changed files with 38 additions and 28 deletions

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
@@ -18,12 +18,13 @@ import java.util.LinkedHashSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
/**
* @author Dave Syer
* @author Oleg Zhurakousky
*
*
* @since 2.0
*
*/
@@ -32,11 +33,11 @@ public abstract class AbstractMessageGroupStore implements MessageGroupStore, It
protected final Log logger = LogFactory.getLog(getClass());
private Collection<MessageGroupCallback> expiryCallbacks = new LinkedHashSet<MessageGroupCallback>();
private volatile boolean timeoutOnIdle;
/**
*
*
*/
public AbstractMessageGroupStore() {
super();
@@ -45,7 +46,7 @@ public abstract class AbstractMessageGroupStore implements MessageGroupStore, It
/**
* Convenient injection point for expiry callbacks in the message store. Each of the callbacks provided will simply
* be registered with the store using {@link #registerMessageGroupExpiryCallback(MessageGroupCallback)}.
*
*
* @param expiryCallbacks the expiry callbacks to add
*/
public void setExpiryCallbacks(Collection<MessageGroupCallback> expiryCallbacks) {
@@ -53,14 +54,14 @@ public abstract class AbstractMessageGroupStore implements MessageGroupStore, It
registerMessageGroupExpiryCallback(callback);
}
}
public boolean isTimeoutOnIdle() {
return timeoutOnIdle;
}
/**
* Allows you to override the rule for the timeout calculation. Typical timeout is based from the time
* the {@link MessageGroup} was created. If you want the timeout to be based on the time
* the {@link MessageGroup} was created. If you want the timeout to be based on the time
* the {@link MessageGroup} was idling (e.g., inactive from the last update) invoke this method with 'true'.
* Default is 'false'.
*/
@@ -69,10 +70,11 @@ public abstract class AbstractMessageGroupStore implements MessageGroupStore, It
}
public void registerMessageGroupExpiryCallback(MessageGroupCallback callback) {
expiryCallbacks.add(callback);
this.expiryCallbacks.add(callback);
}
public int expireMessageGroups(long timeout) {
@ManagedOperation
public synchronized int expireMessageGroups(long timeout) {
int count = 0;
long threshold = System.currentTimeMillis() - timeout;
for (MessageGroup group : this) {
@@ -81,7 +83,7 @@ public abstract class AbstractMessageGroupStore implements MessageGroupStore, It
if (this.isTimeoutOnIdle() && group.getLastModified() > 0) {
timestamp = group.getLastModified();
}
if (timestamp <= threshold) {
count++;
expire(group);
@@ -109,9 +111,9 @@ public abstract class AbstractMessageGroupStore implements MessageGroupStore, It
}
private void expire(MessageGroup group) {
RuntimeException exception = null;
for (MessageGroupCallback callback : expiryCallbacks) {
try {
callback.execute(this, group);
@@ -122,10 +124,10 @@ public abstract class AbstractMessageGroupStore implements MessageGroupStore, It
logger.error("Exception in expiry callback", e);
}
}
if (exception != null) {
throw exception;
}
}
}
}

View File

@@ -16,6 +16,7 @@ import java.util.Iterator;
import org.springframework.integration.Message;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
/**
* Interface for storage operations on groups of messages linked by a group id.
@@ -104,6 +105,7 @@ public interface MessageGroupStore {
*
* @see #registerMessageGroupExpiryCallback(MessageGroupCallback)
*/
@ManagedOperation
int expireMessageGroups(long timeout);
/**
@@ -134,7 +136,7 @@ public interface MessageGroupStore {
/**
* Invoked when a MessageGroupStore expires a group.
*/
public interface MessageGroupCallback {
interface MessageGroupCallback {
void execute(MessageGroupStore messageGroupStore, MessageGroup group);

View File

@@ -14,10 +14,12 @@
<aggregator id="aggregator" ref="aggregatorBean"
input-channel="input" output-channel="output" message-store="messageStore" send-partial-result-on-expiry="true"/>
<beans:bean id="messageStore" class="org.springframework.integration.store.SimpleMessageStore"/>
<beans:bean id="aggregatorBean"
class="org.springframework.integration.config.TestAggregatorBean" />
<control-bus input-channel="controlBusChannel" output-channel="nullChannel"/>
</beans:beans>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,31 +26,36 @@ import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.store.MessageGroupStore;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.message.GenericMessage;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Dave Syer
* @author Artem Bilan
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class AggregatorWithMessageStoreParserTests {
@Autowired
@Qualifier("input")
private MessageChannel input;
@Autowired
private TestAggregatorBean aggregatorBean;
@Autowired
private MessageGroupStore messageGroupStore;
@Autowired
private MessageChannel controlBusChannel;
@Test
@DirtiesContext
public void testAggregation() {
input.send(createMessage("123", "id1", 3, 1, null));
assertEquals(1, messageGroupStore.getMessageGroup("id1").size());
input.send(createMessage("789", "id1", 3, 3, null));
@@ -67,12 +72,11 @@ public class AggregatorWithMessageStoreParserTests {
@Test
@DirtiesContext
public void testExpiry() {
input.send(createMessage("123", "id1", 3, 1, null));
assertEquals(1, messageGroupStore.getMessageGroup("id1").size());
input.send(createMessage("456", "id1", 3, 2, null));
assertEquals(2, messageGroupStore.getMessageGroup("id1").size());
messageGroupStore.expireMessageGroups(-10000);
this.controlBusChannel.send(new GenericMessage<Object>("@messageStore.expireMessageGroups(-10000)"));
assertEquals("One and only one message should have been aggregated", 1, aggregatorBean
.getAggregatedMessages().size());
Message<?> aggregatedMessage = aggregatorBean.getAggregatedMessages().get("id1");

View File

@@ -416,7 +416,7 @@ then you should simply provide an implementation of the <classname>ReleaseStrate
once their containing <classname>MessageGroup</classname> is expired (see <code>MessageGroupStore.expireMessageGroups(long)</code>).
One way of expiring <classname>MessageGroup</classname>s is by configuring a <classname>MessageGroupStoreReaper</classname>.
However <classname>MessageGroup</classname>s can alternatively be expired by simply calling
<code>MessageGroupStore.expireMessageGroup(groupId)</code>. That could be accomplished via a Control Bus operation
<code>MessageGroupStore.expireMessageGroups(timeout)</code>. That could be accomplished via a Control Bus operation
or by simply invoking that method if you have a reference to the <classname>MessageGroupStore</classname> instance.
Otherwise by itself this attribute has no behavior. It only serves as an indicator of what to do (discard or send to the output/reply
channel) with Messages that are still in the <classname>MessageGroup</classname> that is about to be expired.