From 6abadb134c3a50c7fe37d89641079b19071ce1bc Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 15 Apr 2011 16:08:54 -0400 Subject: [PATCH] INT-1863 added support for message removal from the MessageStore to ClaimCheckOutTransformer. Updated documentation. --- docs/src/reference/docbook/claim-check.xml | 14 +++++++++ .../config/xml/ClaimCheckOutParser.java | 2 ++ .../transformer/ClaimCheckOutTransformer.java | 12 +++++++- .../config/xml/spring-integration-2.0.xsd | 16 +++++++++- .../xml/ClaimCheckParserTests-context.xml | 18 ++++++++++++ .../config/xml/ClaimCheckParserTests.java | 29 ++++++++++++++++++- 6 files changed, 88 insertions(+), 3 deletions(-) diff --git a/docs/src/reference/docbook/claim-check.xml b/docs/src/reference/docbook/claim-check.xml index 585d65249c..9d9dad03ae 100644 --- a/docs/src/reference/docbook/claim-check.xml +++ b/docs/src/reference/docbook/claim-check.xml @@ -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 output-channel. + Claim Once + + 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 remove-message boolean attribute on claim-check-out transformer. This attribute is + set to false by default, however if set to true, the claimed Message will also be removed + from the MessageStore and can no longer be claimed again. + ]]> + Although we rarely care about the details of the claim checks as long as they work, it is still worth knowing that diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ClaimCheckOutParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ClaimCheckOutParser.java index 6ca5e3f719..43c95abf7a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ClaimCheckOutParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ClaimCheckOutParser.java @@ -26,6 +26,7 @@ import org.springframework.util.Assert; * Parser for the <claim-check-out/> 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); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ClaimCheckOutTransformer.java b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ClaimCheckOutTransformer.java index e57bbffda4..09aae080cb 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ClaimCheckOutTransformer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ClaimCheckOutTransformer.java @@ -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()); diff --git a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd index cd7b049fac..e120d76d11 100644 --- a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd +++ b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd @@ -1896,7 +1896,7 @@ endpoint itself is a Polling Consumer for a channel with a queue. - + 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). + + + + + + + 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' + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ClaimCheckParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ClaimCheckParserTests-context.xml index 430ebea0d3..c3c80b96c2 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ClaimCheckParserTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ClaimCheckParserTests-context.xml @@ -25,6 +25,24 @@ + + + + + + + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ClaimCheckParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ClaimCheckParserTests.java index bbcfa5b2bc..6267be6480 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ClaimCheckParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ClaimCheckParserTests.java @@ -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)); } }