+{
+ void onReceive(T message);
+}
diff --git a/source/java/org/alfresco/repo/cluster/MessageSendingException.java b/source/java/org/alfresco/repo/cluster/MessageSendingException.java
new file mode 100644
index 0000000000..60d34a3174
--- /dev/null
+++ b/source/java/org/alfresco/repo/cluster/MessageSendingException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.repo.cluster;
+
+/**
+ * Thrown when unable to send a message using a {@link Messenger}.
+ *
+ * @author Matt Ward
+ */
+public class MessageSendingException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ public MessageSendingException(Throwable e)
+ {
+ super("Unable to send message", e);
+ }
+}
diff --git a/source/java/org/alfresco/repo/cluster/Messenger.java b/source/java/org/alfresco/repo/cluster/Messenger.java
new file mode 100644
index 0000000000..0ef889c33f
--- /dev/null
+++ b/source/java/org/alfresco/repo/cluster/Messenger.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.repo.cluster;
+
+import java.io.Serializable;
+
+/**
+ * Provides facilities for peer-to-peer messaging within a cluster. This interface
+ * is intended to act as a facade, allowing the actual implementation (e.g. JGroups
+ * or Hazelcast) to be decoupled as much as possible from the Alfresco code base.
+ *
+ * Instances of this class are parameterised with the type of message payload
+ * to send and receive.
+ *
+ * @author Matt Ward
+ */
+public interface Messenger
+{
+ void send(T message);
+
+ void setReceiver(MessageReceiver receiver);
+
+ boolean isConnected();
+}
diff --git a/source/java/org/alfresco/repo/cluster/MessengerFactory.java b/source/java/org/alfresco/repo/cluster/MessengerFactory.java
new file mode 100644
index 0000000000..6ee3eeca3d
--- /dev/null
+++ b/source/java/org/alfresco/repo/cluster/MessengerFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.repo.cluster;
+
+import java.io.Serializable;
+
+/**
+ * Factory class responsible for creating instances of {@link Messenger} class.
+ *
+ * @author Matt Ward
+ */
+public interface MessengerFactory
+{
+ Messenger createMessenger();
+}
diff --git a/source/java/org/alfresco/repo/cluster/MessengerTestHelper.java b/source/java/org/alfresco/repo/cluster/MessengerTestHelper.java
new file mode 100644
index 0000000000..4cd9dcc85e
--- /dev/null
+++ b/source/java/org/alfresco/repo/cluster/MessengerTestHelper.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2005-2012 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+package org.alfresco.repo.cluster;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
+
+/**
+ * Helper class for testing Messenger related code.
+ *
+ * @author Matt Ward
+ */
+public class MessengerTestHelper
+{
+ private String receivedMsg;
+ private final static int SLEEP_MILLIS = 5;
+
+
+ public MessengerTestHelper()
+ {
+ setReceivedMsg(null);
+ }
+
+ /**
+ * Try to avoid intermitten test failures by trying multiple times. Hopefully the messge
+ * will have been received after the very first sleep, but in a slow environment it may take longer.
+ * This also allows the sleep time to be lower - rather than waiting for say 500 ms, we can try 10 times
+ * at 5 ms - with a chance that we can return after the initial 5 ms.
+ *
+ * @param expectedMsg
+ * @throws InterruptedException
+ */
+ public void checkMessageReceivedWas(String expectedMsg)
+ {
+ int tries = 0;
+
+ while (tries < 10)
+ {
+ try
+ {
+ Thread.sleep(SLEEP_MILLIS);
+ }
+ catch (InterruptedException e)
+ {
+ // Carry on
+ e.printStackTrace();
+ }
+ if (getReceivedMsg() != null)
+ {
+ assertEquals(expectedMsg, getReceivedMsg());
+ return;
+ }
+ tries++;
+ }
+ fail("No message received, tried " + tries +
+ " times, sleeping " + SLEEP_MILLIS + "ms each time.");
+ }
+
+ /**
+ * @return the receivedMsg
+ */
+ public String getReceivedMsg()
+ {
+ return this.receivedMsg;
+ }
+
+ /**
+ * @param receivedMsg the receivedMsg to set
+ */
+ public void setReceivedMsg(String receivedMsg)
+ {
+ this.receivedMsg = receivedMsg;
+ }
+}
diff --git a/source/test-resources/cluster-test/hazelcast-messenger-test.xml b/source/test-resources/cluster-test/hazelcast-messenger-test.xml
new file mode 100644
index 0000000000..b0425f1a0c
--- /dev/null
+++ b/source/test-resources/cluster-test/hazelcast-messenger-test.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/test-resources/cluster-test/jgroups-messenger-test.xml b/source/test-resources/cluster-test/jgroups-messenger-test.xml
new file mode 100644
index 0000000000..46f89844df
--- /dev/null
+++ b/source/test-resources/cluster-test/jgroups-messenger-test.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+ testcluster
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file