Index: docs/reference/src/main/docbook/en-US/content/developers/tools.xml
===================================================================
--- docs/reference/src/main/docbook/en-US/content/developers/tools.xml (revision 1997)
+++ docs/reference/src/main/docbook/en-US/content/developers/tools.xml (working copy)
@@ -342,13 +342,23 @@
ModeShape clustering uses JGroups for communication between members of a cluster, and some of our
- unit and integration tests test this clustering capability. The JGroups configurations used in these tests attempt to use a network
- stack that supports both IPv4 and IPv6 addresses. However, these may fail if your machine is configured only for IPv4 or IPv6.
+ unit and integration tests test this clustering capability. There are two common issues that you may run into when building
+ and testing ModeShape.
+
+
+ Firstly, the JGroups configurations used in these tests attempt to use a network
+ stack that supports both IPv4 and IPv6 addresses. However, these may fail (by the various engines failing to find other members
+ in the cluster) if your machine is configured only for IPv4 or IPv6.
We've defined two Maven profiles ("preferIpv4
" and "preferIpv6
") that you may need to use to say
whether IPv4 or IPv6 (respectively) is preferred, and you can enable these on the Maven command line by adding
"-PpreferIpv4
" or "-PpreferIpv6
". Of course, if your command already specifies other profiles,
just combine the profile names with a comma (e.g., "mvn clean install -Pintegration,preferIpv4
").
+
+ Secondly, as with all network communications, your firewall may be blocking incoming connections to Java. If test tests
+ fail (again, where each engine fails to find other members in the cluster), check your firewall settings. Temporarily
+ disabling your firewall and rerunning the tests may help determine if your firewall is involved.
+
Index: modeshape-integration-tests/src/test/java/org/modeshape/test/integration/ClusteringTest.java
===================================================================
--- modeshape-integration-tests/src/test/java/org/modeshape/test/integration/ClusteringTest.java (revision 1997)
+++ modeshape-integration-tests/src/test/java/org/modeshape/test/integration/ClusteringTest.java (working copy)
@@ -44,6 +44,7 @@ import javax.jcr.observation.EventListener;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.modeshape.common.collection.Problem;
import org.modeshape.common.util.FileUtil;
import org.modeshape.connector.store.jpa.JpaSource;
import org.modeshape.jcr.JcrConfiguration;
@@ -97,7 +98,16 @@ public class ClusteringTest {
// Create an engine and use it to populate the source ...
engine1 = configuration.build();
- engine1.start();
+ try {
+ engine1.start();
+ } catch (RuntimeException e) {
+ // There was a problem starting the engine ...
+ System.err.println("There were problems starting the engine:");
+ for (Problem problem : engine1.getProblems()) {
+ System.err.println(problem);
+ }
+ throw e;
+ }
Repository repository = engine1.getRepository("cars");
Index: modeshape-repository/src/main/java/org/modeshape/repository/ModeShapeEngine.java
===================================================================
--- modeshape-repository/src/main/java/org/modeshape/repository/ModeShapeEngine.java (revision 1997)
+++ modeshape-repository/src/main/java/org/modeshape/repository/ModeShapeEngine.java (working copy)
@@ -55,6 +55,7 @@ import org.modeshape.graph.mimetype.ExtensionBasedMimeTypeDetector;
import org.modeshape.graph.mimetype.MimeTypeDetector;
import org.modeshape.graph.mimetype.MimeTypeDetectorConfig;
import org.modeshape.graph.mimetype.MimeTypeDetectors;
+import org.modeshape.graph.observe.ObservationBus;
import org.modeshape.graph.property.Name;
import org.modeshape.graph.property.Path;
import org.modeshape.graph.property.PathExpression;
@@ -355,6 +356,12 @@ public class ModeShapeEngine {
* configuration repository into the services.
*/
protected class ConfigurationScanner {
+ /**
+ * The name of the {@link ObservationBus} implementation class that will be used when clustering. This class will be
+ * loaded reflectively (so that this library doesn't always require the clustering dependencies).
+ */
+ protected static final String CLUSTERED_OBSERVATION_BUS_CLASSNAME = "org.modeshape.clustering.ClusteredObservationBus";
+
private final Problems problems;
private final ExecutionContext context;
private final ModeShapeConfiguration.ConfigurationDefinition configurationRepository;
@@ -431,11 +438,16 @@ public class ModeShapeEngine {
Node clusterNode = subgraph.getRoot();
String name = stringValueOf(clusterNode);
+ String clusterName = stringValueOf(clusterNode, ModeShapeLexicon.CLUSTER_NAME);
String desc = stringValueOf(clusterNode, ModeShapeLexicon.DESCRIPTION);
String classname = stringValueOf(clusterNode, ModeShapeLexicon.CLASSNAME);
String[] classpath = stringValuesOf(clusterNode, ModeShapeLexicon.CLASSPATH);
if (classname == null || classname.trim().length() == 0) {
- classname = "org.modeshape.clustering.ClusteredObservationBus";
+ classname = CLUSTERED_OBSERVATION_BUS_CLASSNAME;
+ }
+ if (clusterName == null || clusterName.trim().length() == 0) {
+ problems.addError(RepositoryI18n.clusteringConfigurationRequiresClusterName);
+ return null;
}
Map properties = new HashMap();
@@ -449,7 +461,7 @@ public class ModeShapeEngine {
properties.put(propertyName.getLocalName(), property.getValuesAsArray());
}
}
- return new ClusteringConfig(name, desc, properties, classname, classpath);
+ return new ClusteringConfig(clusterName, desc, properties, classname, classpath);
} catch (PathNotFoundException e) {
// no detectors registered ...
}
@@ -530,7 +542,11 @@ public class ModeShapeEngine {
private String stringValueOf( Node node,
Name propertyName ) {
Property property = node.getProperty(propertyName);
- if (property == null) return null;
+ if (property == null) {
+ // Check whether the property exists with no namespace ...
+ property = node.getProperty(context.getValueFactories().getNameFactory().create(propertyName.getLocalName()));
+ if (property == null) return null;
+ }
if (property.isEmpty()) return null;
return context.getValueFactories().getStringFactory().create(property.getFirstValue());
}
@@ -538,7 +554,11 @@ public class ModeShapeEngine {
private String[] stringValuesOf( Node node,
Name propertyName ) {
Property property = node.getProperty(propertyName);
- if (property == null) return null;
+ if (property == null) {
+ // Check whether the property exists with no namespace ...
+ property = node.getProperty(context.getValueFactories().getNameFactory().create(propertyName.getLocalName()));
+ if (property == null) return null;
+ }
return context.getValueFactories().getStringFactory().create(property.getValuesAsArray());
}
Index: modeshape-repository/src/main/java/org/modeshape/repository/RepositoryI18n.java
===================================================================
--- modeshape-repository/src/main/java/org/modeshape/repository/RepositoryI18n.java (revision 1997)
+++ modeshape-repository/src/main/java/org/modeshape/repository/RepositoryI18n.java (working copy)
@@ -60,6 +60,7 @@ public final class RepositoryI18n {
// Clustering service ...
public static I18n clusteringServiceName;
+ public static I18n clusteringConfigurationRequiresClusterName;
public static I18n unableToRegisterObserverOnUnstartedClusteringService;
public static I18n unableToUnregisterObserverOnUnstartedClusteringService;
public static I18n unableToNotifyObserversOnUnstartedClusteringService;
Index: modeshape-repository/src/main/resources/org/modeshape/repository/RepositoryI18n.properties
===================================================================
--- modeshape-repository/src/main/resources/org/modeshape/repository/RepositoryI18n.properties (revision 1997)
+++ modeshape-repository/src/main/resources/org/modeshape/repository/RepositoryI18n.properties (working copy)
@@ -43,6 +43,7 @@ errorFindingPropertyNameInPropertyRemovedEvent = Error finding the name of the r
repositoryServiceName = Repository Service
clusteringServiceName = Clustering Service
+clusteringConfigurationRequiresClusterName = Clustering configuration requires a non-blank 'clusterName' attribute
unableToRegisterObserverOnUnstartedClusteringService = Unable to register an observer until the clustering service is started
unableToUnregisterObserverOnUnstartedClusteringService = Unable to unregister an observer until the clustering service is started
unableToNotifyObserversOnUnstartedClusteringService = Unable to notify observers until the clustering service is started