diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/ResponseCorrelator.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/ResponseCorrelator.java
new file mode 100644
index 0000000000..99383c88e9
--- /dev/null
+++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/ResponseCorrelator.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002-2008 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.
+ */
+
+package org.springframework.integration.handler;
+
+import org.springframework.integration.message.Message;
+import org.springframework.integration.message.MessageHandlingException;
+import org.springframework.integration.message.RetrievalBlockingMessageStore;
+import org.springframework.util.Assert;
+
+/**
+ * A handler for receiving messages from a "reply channel". Any component that
+ * is expecting a response can poll by providing the correlation identifier.
+ *
+ * @author Mark Fisher
+ */
+public class ResponseCorrelator implements MessageHandler {
+
+ private volatile long defaultTimeout = 5000;
+
+ private final RetrievalBlockingMessageStore messageStore;
+
+
+ public ResponseCorrelator(int capacity) {
+ this.messageStore = new RetrievalBlockingMessageStore(capacity);
+ }
+
+
+ public void setDefaultTimeout(long defaultTimeout) {
+ Assert.isTrue(defaultTimeout >= 0, "'defaultTimeout' must not be negative");
+ this.defaultTimeout = defaultTimeout;
+ }
+
+ public Message> handle(Message> message) {
+ Object correlationId = this.getCorrelationId(message);
+ if (correlationId == null) {
+ throw new MessageHandlingException("unable to handle response, message has no correlationId: " + message);
+ }
+ this.messageStore.put(correlationId, message);
+ return null;
+ }
+
+ public Message> getResponse(Object correlationId) {
+ return this.getResponse(correlationId, this.defaultTimeout);
+ }
+
+ public Message> getResponse(Object correlationId, long timeout) {
+ Assert.notNull(correlationId, "'correlationId' must not be null");
+ return this.messageStore.remove(correlationId, timeout);
+ }
+
+ /**
+ * Retrieve the correlation identifier from the provided message.
+ *
+ * This method may be overridden by subclasses. The default implementation
+ * returns the 'correlationId' from the message header.
+ */
+ protected Object getCorrelationId(final Message> message) {
+ return message.getHeader().getCorrelationId();
+ }
+
+}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/message/RetrievalBlockingMessageStore.java b/spring-integration-core/src/main/java/org/springframework/integration/message/RetrievalBlockingMessageStore.java
new file mode 100644
index 0000000000..a0b7099378
--- /dev/null
+++ b/spring-integration-core/src/main/java/org/springframework/integration/message/RetrievalBlockingMessageStore.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2002-2008 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.
+ */
+
+package org.springframework.integration.message;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link MessageStore} implementation whose get and
+ * remove methods block until a message is available.
+ *
+ * Alternative methods that accept an explicit timeout value are also available.
+ *
+ * @author Mark Fisher
+ */
+public class RetrievalBlockingMessageStore extends SimpleMessageStore implements MessageStore {
+
+ private final ConcurrentMap