INT-1863 added support for message removal from the MessageStore to ClaimCheckOutTransformer. Updated documentation.

This commit is contained in:
Oleg Zhurakousky
2011-04-15 16:08:54 -04:00
parent fea200997a
commit 6abadb134c
6 changed files with 88 additions and 3 deletions

View File

@@ -69,6 +69,20 @@
querying the Message store for a Message identified by the provided Claim Check. It then sends the newly checked-out Message to the
<code>output-channel</code>.
</para>
<para><emphasis>Claim Once</emphasis></para>
<para>
There are scenarios when a particular message must be claimed only once. Take the airplane luggage check-in/out process.
Checking-in your luggage on the departure and and then claiming it on the arrival is a classic example of such scenario.
Once the luggage was claimed it can no longer be claimed again without further check-in. To accommodate such cases we
introduced <code>remove-message</code> boolean attribute on <code>claim-check-out</code> transformer. This attribute is
set to <code>false</code> by default, however if set to <code>true</code>, the claimed Message will also be removed
from the MessageStore and can no longer be claimed again.
<programlisting language="xml"><![CDATA[<claim-check-out id="checkout"
input-channel="checkoutChannel"
message-store="testMessageStore"
output-channel="output"
remove-message="true"/>]]></programlisting>
</para>
</section>
<para>
Although we rarely care about the details of the claim checks as long as they work, it is still worth knowing that

View File

@@ -26,6 +26,7 @@ import org.springframework.util.Assert;
* Parser for the &lt;claim-check-out/&gt; element.
*
* @author Mark Fisher
* @author Oleg Zhurakousky
* @since 2.0
*/
public class ClaimCheckOutParser extends AbstractTransformerParser {
@@ -39,6 +40,7 @@ public class ClaimCheckOutParser extends AbstractTransformerParser {
protected void parseTransformer(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String messageStoreRef = element.getAttribute("message-store");
Assert.hasText(messageStoreRef, "The 'message-store' attribute is required.");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "remove-message");
builder.addConstructorArgReference(messageStoreRef);
}

View File

@@ -29,11 +29,14 @@ import org.springframework.util.Assert;
* that ID can be retrieved from the given MessageStore.
*
* @author Mark Fisher
* @author Oleg Zhurakousky
* @since 2.0
*/
public class ClaimCheckOutTransformer extends AbstractTransformer {
private final MessageStore messageStore;
private volatile boolean removeMessage = false;
/**
@@ -43,7 +46,10 @@ public class ClaimCheckOutTransformer extends AbstractTransformer {
Assert.notNull(messageStore, "MessageStore must not be null");
this.messageStore = messageStore;
}
public void setRemoveMessage(boolean removeMessage) {
this.removeMessage = removeMessage;
}
@Override
protected Object doTransform(Message<?> message) throws Exception {
@@ -53,6 +59,10 @@ public class ClaimCheckOutTransformer extends AbstractTransformer {
Message<?> retrievedMessage = this.messageStore.getMessage(id);
Assert.notNull(retrievedMessage, "unable to locate Message for ID: " + id
+ " within MessageStore [" + this.messageStore + "]");
if (this.removeMessage){
this.messageStore.removeMessage(id);
logger.debug("Message with claim-check '" + id + "' was removed from MessageStore");
}
MessageBuilder<?> responseBuilder = MessageBuilder.fromMessage(retrievedMessage);
// headers on the 'current' message take precedence
responseBuilder.copyHeaders(message.getHeaders());

View File

@@ -1896,7 +1896,7 @@ endpoint itself is a Polling Consumer for a channel with a queue.
</xsd:annotation>
</xsd:element>
<xsd:element name="claim-check-out" type="claimCheckTransformerType">
<xsd:element name="claim-check-out">
<xsd:annotation>
<xsd:documentation>
Defines a Transformer that accepts a Message whose payload is a UUID and
@@ -1905,6 +1905,20 @@ endpoint itself is a Polling Consumer for a channel with a queue.
available (else null).
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="claimCheckTransformerType">
<xsd:attribute name="remove-message" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation>
If set to 'true' the Message will be removed from the MessageStore by
this transformer. Useful when Message can be 'claimed' only once. DFAULT is 'false'
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="claimCheckTransformerType">

View File

@@ -25,6 +25,24 @@
<claim-check-out id="checkout"
input-channel="checkoutChannel"
message-store="testMessageStore"/>
<!-- claim with remove test -->
<claim-check-in id="checkinA"
input-channel="checkinChannelA"
message-store="testMessageStore"
output-channel="checkoutChannelA"/>
<channel id="checkoutChannelA">
<interceptors>
<wire-tap channel="wiretap"/>
</interceptors>
</channel>
<claim-check-out id="checkoutWithRemove"
input-channel="checkoutChannelA"
message-store="testMessageStore"
remove-message="true"/>
<beans:bean id="testMessageStore"
class="org.springframework.integration.store.SimpleMessageStore"/>

View File

@@ -16,9 +16,12 @@
package org.springframework.integration.config.xml;
import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.UUID;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,6 +42,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mark Fisher
* @author Oleg Zhurakousky
* @since 2.0
*/
@ContextConfiguration
@@ -50,6 +54,9 @@ public class ClaimCheckParserTests {
@Autowired
private MessageChannel checkinChannel;
@Autowired
private MessageChannel checkinChannelA;
@Autowired
private PollableChannel wiretap;
@@ -59,6 +66,9 @@ public class ClaimCheckParserTests {
@Autowired
private EventDrivenConsumer checkout;
@Autowired
private MessageStore sampleMessageStore;
@Test
@@ -86,10 +96,27 @@ public class ClaimCheckParserTests {
checkinChannel.send(message);
Message<?> wiretapMessage = wiretap.receive(0);
assertNotNull(wiretapMessage);
assertEquals(message.getHeaders().getId(), wiretapMessage.getPayload());
UUID payload = (UUID) wiretapMessage.getPayload();
assertEquals(message.getHeaders().getId(), payload);
Message<?> resultMessage = replyChannel.receive(0);
assertNotNull(resultMessage);
assertEquals("test", resultMessage.getPayload());
assertNotNull(this.sampleMessageStore.getMessage(payload));
}
@Test
public void integrationTestWithRemoval() {
QueueChannel replyChannel = new QueueChannel();
Message<?> message = MessageBuilder.withPayload("test").setReplyChannel(replyChannel).build();
checkinChannelA.send(message);
Message<?> wiretapMessage = wiretap.receive(0);
assertNotNull(wiretapMessage);
UUID payload = (UUID) wiretapMessage.getPayload();
assertEquals(message.getHeaders().getId(), payload);
Message<?> resultMessage = replyChannel.receive(0);
assertNotNull(resultMessage);
assertEquals("test", resultMessage.getPayload());
assertNull(this.sampleMessageStore.getMessage(payload));
}
}