You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2018/08/22 02:05:41 UTC

[2/3] activemq-artemis git commit: ARTEMIS-2047 Compatible option for ActiveMQJMSClient

ARTEMIS-2047 Compatible option for ActiveMQJMSClient


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/55b0d5b0
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/55b0d5b0
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/55b0d5b0

Branch: refs/heads/master
Commit: 55b0d5b0ea00f7eae6bdbf7391f03dd586d7924c
Parents: 281cff3
Author: Clebert Suconic <cl...@apache.org>
Authored: Tue Aug 21 11:50:34 2018 -0400
Committer: Clebert Suconic <cl...@apache.org>
Committed: Tue Aug 21 22:05:29 2018 -0400

----------------------------------------------------------------------
 .../artemis/utils/ClassloadingUtil.java         |  32 +++-
 .../artemis/api/core/client/ActiveMQClient.java |   2 -
 .../artemis/api/jms/ActiveMQJMSClient.java      |  48 +++++-
 .../jms/client/ActiveMQConnectionFactory.java   |   3 +-
 .../ConnectionFactoryConfigurationImpl.java     |   5 +-
 .../validateClient.groovy                       |  28 ++++
 .../ActiveMQJMSClientCompatibilityTest.java     |  92 +++++++++++
 .../tests/compatibility/ClasspathBaseTest.java  | 152 +++++++++++++++++++
 ...onFactoryConfigurationSerializationTest.java |   2 +-
 .../tests/compatibility/ExportImportTest.java   |   2 +-
 .../compatibility/JournalCompatibilityTest.java |   2 +-
 .../artemis/tests/compatibility/MeshTest.java   |   2 +-
 .../tests/compatibility/SendAckTest.java        |   2 +-
 .../tests/compatibility/SerializationTest.java  |   2 +-
 .../tests/compatibility/VersionedBaseTest.java  | 137 ++---------------
 15 files changed, 371 insertions(+), 140 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ClassloadingUtil.java
----------------------------------------------------------------------
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ClassloadingUtil.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ClassloadingUtil.java
index e27ce0c..9ea1b61 100644
--- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ClassloadingUtil.java
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/ClassloadingUtil.java
@@ -17,6 +17,9 @@
 package org.apache.activemq.artemis.utils;
 
 import java.net.URL;
+import java.util.Properties;
+
+import org.jboss.logging.Logger;
 
 /**
  * This class will be used to perform generic class-loader operations,
@@ -27,6 +30,8 @@ import java.net.URL;
 
 public final class ClassloadingUtil {
 
+   private static final Logger logger = Logger.getLogger(ClassloadingUtil.class);
+
    private static final String INSTANTIATION_EXCEPTION_MESSAGE = "Your class must have a constructor without arguments. If it is an inner class, it must be static!";
 
    public static Object newInstanceFromClassLoader(final String className) {
@@ -84,7 +89,10 @@ public final class ClassloadingUtil {
    }
 
    public static URL findResource(final String resourceName) {
-      ClassLoader loader = ClassloadingUtil.class.getClassLoader();
+      return findResource(ClassloadingUtil.class.getClassLoader(), resourceName);
+   }
+
+   public static URL findResource(ClassLoader loader, final String resourceName) {
       try {
          URL resource = loader.getResource(resourceName);
          if (resource != null)
@@ -98,4 +106,26 @@ public final class ClassloadingUtil {
 
       return loader.getResource(resourceName);
    }
+
+
+   public static String loadProperty(ClassLoader loader, String propertiesFile, String name) {
+      Properties properties = loadProperties(loader, propertiesFile);
+
+      return (String)properties.get(name);
+   }
+
+   public static Properties loadProperties(ClassLoader loader, String propertiesFile) {
+      Properties properties = new Properties();
+
+      try {
+         URL url = findResource(loader, propertiesFile);
+         if (url != null) {
+            properties.load(url.openStream());
+         }
+      } catch (Throwable ignored) {
+         logger.warn(ignored);
+      }
+      return properties;
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/ActiveMQClient.java
----------------------------------------------------------------------
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/ActiveMQClient.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/ActiveMQClient.java
index ab647a3..f4de508 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/ActiveMQClient.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/client/ActiveMQClient.java
@@ -137,8 +137,6 @@ public final class ActiveMQClient {
 
    public static final boolean DEFAULT_USE_TOPOLOGY_FOR_LOADBALANCING = true;
 
-   public static final boolean DEFAULT_ENABLE_1X_PREFIXES = false;
-
    public static final String THREAD_POOL_MAX_SIZE_PROPERTY_KEY = "activemq.artemis.client.global.thread.pool.max.size";
 
    public static final String SCHEDULED_THREAD_POOL_SIZE_PROPERTY_KEY = "activemq.artemis.client.global.scheduled.thread.pool.core.size";

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/artemis-jms-client/src/main/java/org/apache/activemq/artemis/api/jms/ActiveMQJMSClient.java
----------------------------------------------------------------------
diff --git a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/api/jms/ActiveMQJMSClient.java b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/api/jms/ActiveMQJMSClient.java
index 9cf0c4d..0119e35 100644
--- a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/api/jms/ActiveMQJMSClient.java
+++ b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/api/jms/ActiveMQJMSClient.java
@@ -21,14 +21,42 @@ import javax.jms.Topic;
 
 import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration;
 import org.apache.activemq.artemis.api.core.TransportConfiguration;
+import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
 import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
 import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
 import org.apache.activemq.artemis.uri.ConnectionFactoryParser;
+import org.apache.activemq.artemis.utils.ClassloadingUtil;
+import org.jboss.logging.Logger;
 
 /**
  * A utility class for creating ActiveMQ Artemis client-side JMS managed resources.
  */
 public class ActiveMQJMSClient {
+   private static final Logger logger = Logger.getLogger(ActiveMQJMSClient.class);
+
+   public static final boolean DEFAULT_ENABLE_1X_PREFIXES;
+
+
+   static {
+
+      String value1X = System.getProperty(ActiveMQJMSClient.class.getName() + ".enable1xPrefixes");
+
+      if (value1X == null) {
+         value1X = ClassloadingUtil.loadProperty(ActiveMQJMSClient.class.getClassLoader(), ActiveMQJMSClient.class.getName() + ".properties", "enable1xPrefixes");
+      }
+
+      boolean prefixes = false;
+
+
+      if (value1X != null) {
+         try {
+            prefixes = Boolean.parseBoolean(value1X);
+         } catch (Throwable e) {
+            logger.warn(e);
+         }
+      }
+      DEFAULT_ENABLE_1X_PREFIXES = prefixes;
+   }
 
    /**
     * Creates an ActiveMQConnectionFactory;
@@ -115,21 +143,37 @@ public class ActiveMQJMSClient {
    /**
     * Creates a client-side representation of a JMS Topic.
     *
+    * This method is deprecated. Use {@link org.apache.activemq.artemis.jms.client.ActiveMQSession#createTopic(String)} as that method will know the proper
+    * prefix used at the target server.
+    *
     * @param name the name of the topic
     * @return The Topic
     */
+   @Deprecated
    public static Topic createTopic(final String name) {
-      return ActiveMQDestination.createTopic(name);
+      if (DEFAULT_ENABLE_1X_PREFIXES) {
+         return ActiveMQDestination.createTopic(PacketImpl.OLD_TOPIC_PREFIX + name, name);
+      } else {
+         return ActiveMQDestination.createTopic(name);
+      }
    }
 
    /**
     * Creates a client-side representation of a JMS Queue.
     *
+    * This method is deprecated. Use {@link org.apache.activemq.artemis.jms.client.ActiveMQSession#createQueue(String)} (String)} as that method will know the proper
+    * prefix used at the target server.
+    * *
     * @param name the name of the queue
     * @return The Queue
     */
+   @Deprecated
    public static Queue createQueue(final String name) {
-      return ActiveMQDestination.createQueue(name);
+      if (DEFAULT_ENABLE_1X_PREFIXES) {
+         return ActiveMQDestination.createQueue(PacketImpl.OLD_QUEUE_PREFIX + name, name);
+      } else {
+         return ActiveMQDestination.createQueue(name);
+      }
    }
 
    private ActiveMQJMSClient() {

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionFactory.java
----------------------------------------------------------------------
diff --git a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionFactory.java b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionFactory.java
index 17ee6fe..a0d036c 100644
--- a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionFactory.java
+++ b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionFactory.java
@@ -48,6 +48,7 @@ import org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory;
 import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
 import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
 import org.apache.activemq.artemis.api.core.client.ServerLocator;
+import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
 import org.apache.activemq.artemis.api.jms.ActiveMQJMSConstants;
 import org.apache.activemq.artemis.api.jms.JMSFactoryType;
 import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
@@ -94,7 +95,7 @@ public class ActiveMQConnectionFactory extends JNDIStorable implements Connectio
 
    private boolean ignoreJTA;
 
-   private boolean enable1xPrefixes = ActiveMQClient.DEFAULT_ENABLE_1X_PREFIXES;
+   private boolean enable1xPrefixes = ActiveMQJMSClient.DEFAULT_ENABLE_1X_PREFIXES;
 
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/config/impl/ConnectionFactoryConfigurationImpl.java
----------------------------------------------------------------------
diff --git a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/config/impl/ConnectionFactoryConfigurationImpl.java b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/config/impl/ConnectionFactoryConfigurationImpl.java
index c2ac0b6..e1718bd 100644
--- a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/config/impl/ConnectionFactoryConfigurationImpl.java
+++ b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/config/impl/ConnectionFactoryConfigurationImpl.java
@@ -23,6 +23,7 @@ import java.util.List;
 import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
 import org.apache.activemq.artemis.api.core.SimpleString;
 import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
+import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
 import org.apache.activemq.artemis.api.jms.JMSFactoryType;
 import org.apache.activemq.artemis.jms.server.config.ConnectionFactoryConfiguration;
 import org.apache.activemq.artemis.utils.BufferHelper;
@@ -124,7 +125,7 @@ public class ConnectionFactoryConfigurationImpl implements ConnectionFactoryConf
 
    private int initialMessagePacketSize = ActiveMQClient.DEFAULT_INITIAL_MESSAGE_PACKET_SIZE;
 
-   private boolean enable1xPrefixes = ActiveMQClient.DEFAULT_ENABLE_1X_PREFIXES;
+   private boolean enable1xPrefixes = ActiveMQJMSClient.DEFAULT_ENABLE_1X_PREFIXES;
 
    private boolean enableSharedClientID = ActiveMQClient.DEFAULT_ENABLED_SHARED_CLIENT_ID;
 
@@ -640,7 +641,7 @@ public class ConnectionFactoryConfigurationImpl implements ConnectionFactoryConf
 
       deserializationWhiteList = BufferHelper.readNullableSimpleStringAsString(buffer);
 
-      enable1xPrefixes = buffer.readableBytes() > 0 ? buffer.readBoolean() : ActiveMQClient.DEFAULT_ENABLE_1X_PREFIXES;
+      enable1xPrefixes = buffer.readableBytes() > 0 ? buffer.readBoolean() : ActiveMQJMSClient.DEFAULT_ENABLE_1X_PREFIXES;
 
       enableSharedClientID = buffer.readableBytes() > 0 ? buffer.readBoolean() : ActiveMQClient.DEFAULT_ENABLED_SHARED_CLIENT_ID;
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/main/resources/ActiveMQJMSClientCompatibilityTest/validateClient.groovy
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/main/resources/ActiveMQJMSClientCompatibilityTest/validateClient.groovy b/tests/compatibility-tests/src/main/resources/ActiveMQJMSClientCompatibilityTest/validateClient.groovy
new file mode 100644
index 0000000..400a69e
--- /dev/null
+++ b/tests/compatibility-tests/src/main/resources/ActiveMQJMSClientCompatibilityTest/validateClient.groovy
@@ -0,0 +1,28 @@
+import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient
+import org.apache.activemq.artemis.jms.client.ActiveMQQueue
+import org.apache.activemq.artemis.jms.client.ActiveMQTopic
+import org.apache.activemq.artemis.tests.compatibility.GroovyRun
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+ActiveMQQueue queue = (ActiveMQQueue) ActiveMQJMSClient.createQueue("q1");
+GroovyRun.assertEquals("jms.queue.q1", queue.getAddress());
+GroovyRun.assertEquals("q1", queue.getQueueName());
+ActiveMQTopic topic = (ActiveMQTopic) ActiveMQJMSClient.createTopic("t1");
+GroovyRun.assertEquals("jms.topic.t1", topic.getAddress());
+GroovyRun.assertEquals("t1", topic.getTopicName());

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ActiveMQJMSClientCompatibilityTest.java
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ActiveMQJMSClientCompatibilityTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ActiveMQJMSClientCompatibilityTest.java
new file mode 100644
index 0000000..91e0e22
--- /dev/null
+++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ActiveMQJMSClientCompatibilityTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.activemq.artemis.tests.compatibility;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+
+import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
+import org.apache.activemq.artemis.jms.client.ActiveMQQueue;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.SNAPSHOT;
+import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.ONE_FIVE;
+
+public class ActiveMQJMSClientCompatibilityTest extends ClasspathBaseTest {
+
+   @Test
+   public void testActiveMQJMSCompatibility_1XPrefix_SNAPSHOT() throws Exception {
+
+      Assert.assertFalse(ActiveMQJMSClient.DEFAULT_ENABLE_1X_PREFIXES);
+      ActiveMQQueue queue = (ActiveMQQueue)ActiveMQJMSClient.createQueue("t1");
+      // this step is to guarantee the class is not affected when there's no property in place
+      Assert.assertEquals("t1", queue.getAddress());
+
+      ClassLoader loader = getClasspath(SNAPSHOT, true);
+
+      System.setProperty(ActiveMQJMSClient.class.getName() + ".enable1xPrefixes", "true");
+
+      try {
+
+         evaluate(loader, "ActiveMQJMSClientCompatibilityTest/validateClient.groovy");
+
+      } finally {
+         System.clearProperty(ActiveMQJMSClient.class.getName() + ".enable1xPrefixes");
+      }
+
+   }
+
+   @Test
+   public void testActiveMQJMSCompatibility_1XPrefix_SNAPSHOT_with_properties() throws Exception {
+
+      Assert.assertFalse(ActiveMQJMSClient.DEFAULT_ENABLE_1X_PREFIXES);
+      ActiveMQQueue queue = (ActiveMQQueue)ActiveMQJMSClient.createQueue("t1");
+      // this step is to guarantee the class is not affected when there's no property in place
+      Assert.assertEquals("t1", queue.getAddress());
+
+      File file = serverFolder.newFile(ActiveMQJMSClient.class.getName() + ".properties");
+
+      FileOutputStream fileOutputStream = new FileOutputStream(file);
+      PrintStream stream = new PrintStream(fileOutputStream);
+      stream.println("enable1xPrefixes=true");
+      stream.close();
+
+      String snapshotPath = System.getProperty(SNAPSHOT);
+      Assume.assumeNotNull(snapshotPath);
+
+      String path = serverFolder.getRoot().getAbsolutePath() + File.pathSeparator + snapshotPath;
+
+
+      ClassLoader loader = defineClassLoader(path);
+
+      evaluate(loader, "ActiveMQJMSClientCompatibilityTest/validateClient.groovy");
+
+   }
+
+   @Test
+
+   // The purpose here is just to validate the test itself. Nothing to be fixed here
+   public void testActiveMQJMSCompatibility_1XPrefix_ONE_FIVE() throws Exception {
+      ClassLoader loader = getClasspath(ONE_FIVE, false);
+
+      evaluate(loader, "ActiveMQJMSClientCompatibilityTest/validateClient.groovy");
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ClasspathBaseTest.java
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ClasspathBaseTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ClasspathBaseTest.java
new file mode 100644
index 0000000..d2a4b50
--- /dev/null
+++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ClasspathBaseTest.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.activemq.artemis.tests.compatibility;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.junit.Assume;
+import org.junit.ClassRule;
+import org.junit.rules.TemporaryFolder;
+
+import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.SNAPSHOT;
+
+public class ClasspathBaseTest {
+
+
+   @ClassRule
+   public static TemporaryFolder serverFolder;
+
+   static {
+      File parent = new File("./target/tmp");
+      parent.mkdirs();
+      serverFolder = new TemporaryFolder(parent);
+   }
+
+   protected static Map<String, ClassLoader> loaderMap = new HashMap<>();
+
+   private static HashSet<String> printed = new HashSet<>();
+
+   protected static ClassLoader defineClassLoader(String classPath) throws MalformedURLException {
+      String[] classPathArray = classPath.split(File.pathSeparator);
+      URL[] elements = new URL[classPathArray.length];
+      for (int i = 0; i < classPathArray.length; i++) {
+         elements[i] = new File(classPathArray[i]).toPath().toUri().toURL();
+      }
+
+      return new URLClassLoader(elements, null);
+   }
+
+   public static ClassLoader getClasspath(String name) throws Exception {
+      return getClasspath(name, false);
+   }
+
+   public static ClassLoader getClasspath(String name, boolean forceNew) throws Exception {
+
+      if (!forceNew) {
+         if (name.equals(SNAPSHOT)) {
+            return VersionedBaseTest.class.getClassLoader();
+         }
+
+         ClassLoader loader = loaderMap.get(name);
+         if (loader != null && !forceNew) {
+            return loader;
+         }
+      }
+
+      String value = System.getProperty(name);
+
+      if (!printed.contains(name)) {
+         boolean ok = value != null && !value.trim().isEmpty();
+         if (!ok) {
+            System.out.println("Add \"-D" + name + "=\'CLASSPATH\'\" into your VM settings");
+            System.out.println("You will see it in the output from mvn install at the compatibility-tests");
+            System.out.println("... look for output from dependency-scan");
+
+            // our dependency scan used at the pom under compatibility-tests/pom.xml will generate these, example:
+            // [INFO] dependency-scan setting: -DARTEMIS-140="/Users/someuser/....."
+            // copy that into your IDE setting and you should be able to debug it
+         }
+         Assume.assumeTrue("Cannot run these tests, no classpath found", ok);
+      }
+
+      ClassLoader loader = defineClassLoader(value);
+      if (!forceNew) {
+         // if we are forcing a new one, there's no point in caching it
+         loaderMap.put(name, loader);
+      }
+
+      return loader;
+   }
+
+   protected static Object evaluate(ClassLoader loader, String script, String... arguments) throws Exception {
+      return tclCall(loader, () -> {
+         Class clazz = loader.loadClass(GroovyRun.class.getName());
+         Method method = clazz.getMethod("evaluate", String.class, String[].class);
+         return method.invoke(null, script, arguments);
+      });
+   }
+
+   protected static void setVariable(ClassLoader loader, String name, Object object) throws Exception {
+      tclCall(loader, () -> {
+         Class clazz = loader.loadClass(GroovyRun.class.getName());
+         Method method = clazz.getMethod("setVariable", String.class, Object.class);
+         method.invoke(null, name, object);
+         return null;
+      });
+   }
+
+   protected static Object setVariable(ClassLoader loader, String name) throws Exception {
+      return tclCall(loader, () -> {
+         Class clazz = loader.loadClass(GroovyRun.class.getName());
+         Method method = clazz.getMethod("getVariable", String.class);
+         return method.invoke(null, name);
+      });
+   }
+
+   protected static Object execute(ClassLoader loader, String script) throws Exception {
+      return tclCall(loader, () -> {
+         Class clazz = loader.loadClass(GroovyRun.class.getName());
+         Method method = clazz.getMethod("execute", String.class);
+         return method.invoke(null, script);
+      });
+   }
+
+   protected static Object tclCall(ClassLoader loader, CallIt run) throws Exception {
+
+      ClassLoader original = Thread.currentThread().getContextClassLoader();
+      Thread.currentThread().setContextClassLoader(loader);
+      try {
+         return run.run();
+      } finally {
+         Thread.currentThread().setContextClassLoader(original);
+      }
+   }
+
+   public interface CallIt {
+
+      Object run() throws Exception;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ConnectionFactoryConfigurationSerializationTest.java
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ConnectionFactoryConfigurationSerializationTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ConnectionFactoryConfigurationSerializationTest.java
index 9b7dab8..9389452 100644
--- a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ConnectionFactoryConfigurationSerializationTest.java
+++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ConnectionFactoryConfigurationSerializationTest.java
@@ -39,7 +39,7 @@ import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.TWO_FOUR
  * cd /compatibility-tests
  * mvn install -Ptests | tee output.log
  *
- * on the output.log you will see the output generated by {@link #getClasspathProperty(String)}
+ * on the output.log you will see the output generated by {@link #getClasspath(String)}
  *
  * On your IDE, edit the Run Configuration to your test and add those -D as parameters to your test.
  * On Idea you would do the following:

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ExportImportTest.java
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ExportImportTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ExportImportTest.java
index e70d02c..854ef1e 100644
--- a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ExportImportTest.java
+++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/ExportImportTest.java
@@ -37,7 +37,7 @@ import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.SNAPSHOT
  * cd /compatibility-tests
  * mvn install -Ptests | tee output.log
  *
- * on the output.log you will see the output generated by {@link #getClasspathProperty(String)}
+ * on the output.log you will see the output generated by {@link #getClasspath(String)}
  *
  * On your IDE, edit the Run Configuration to your test and add those -D as parameters to your test.
  * On Idea you would do the following:

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/JournalCompatibilityTest.java
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/JournalCompatibilityTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/JournalCompatibilityTest.java
index e63f70b..27ebdd0 100644
--- a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/JournalCompatibilityTest.java
+++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/JournalCompatibilityTest.java
@@ -39,7 +39,7 @@ import org.junit.runners.Parameterized;
  * cd /compatibility-tests
  * mvn install -Ptests | tee output.log
  *
- * on the output.log you will see the output generated by {@link #getClasspathProperty(String)}
+ * on the output.log you will see the output generated by {@link #getClasspath(String)}
  *
  * On your IDE, edit the Run Configuration to your test and add those -D as parameters to your test.
  * On Idea you would do the following:

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/MeshTest.java
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/MeshTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/MeshTest.java
index 8d4939e..3721979 100644
--- a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/MeshTest.java
+++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/MeshTest.java
@@ -42,7 +42,7 @@ import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.TWO_FOUR
  * cd /compatibility-tests
  * mvn install -Ptests | tee output.log
  *
- * on the output.log you will see the output generated by {@link #getClasspathProperty(String)}
+ * on the output.log you will see the output generated by {@link #getClasspath(String)}
  *
  * On your IDE, edit the Run Configuration to your test and add those -D as parameters to your test.
  * On Idea you would do the following:

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SendAckTest.java
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SendAckTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SendAckTest.java
index 7fe9eb4..168a56f 100644
--- a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SendAckTest.java
+++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SendAckTest.java
@@ -36,7 +36,7 @@ import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.ONE_FIVE
  * cd /compatibility-tests
  * mvn install -Ptests | tee output.log
  *
- * on the output.log you will see the output generated by {@link #getClasspathProperty(String)}
+ * on the output.log you will see the output generated by {@link #getClasspath(String)}
  *
  * On your IDE, edit the Run Configuration to your test and add those -D as parameters to your test.
  * On Idea you would do the following:

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SerializationTest.java
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SerializationTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SerializationTest.java
index cd7daf2..bb23816 100644
--- a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SerializationTest.java
+++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/SerializationTest.java
@@ -38,7 +38,7 @@ import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.SNAPSHOT
  * cd /compatibility-tests
  * mvn install -Ptests | tee output.log
  *
- * on the output.log you will see the output generated by {@link #getClasspathProperty(String)}
+ * on the output.log you will see the output generated by {@link #getClasspath(String)}
  *
  * On your IDE, edit the Run Configuration to your test and add those -D as parameters to your test.
  * On Idea you would do the following:

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/55b0d5b0/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/VersionedBaseTest.java
----------------------------------------------------------------------
diff --git a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/VersionedBaseTest.java b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/VersionedBaseTest.java
index 19bafd0..ab5331d 100644
--- a/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/VersionedBaseTest.java
+++ b/tests/compatibility-tests/src/test/java/org/apache/activemq/artemis/tests/compatibility/VersionedBaseTest.java
@@ -18,24 +18,12 @@
 package org.apache.activemq.artemis.tests.compatibility;
 
 import java.io.File;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 import org.junit.AfterClass;
-import org.junit.Assume;
-import org.junit.ClassRule;
-import org.junit.rules.TemporaryFolder;
 
-import static org.apache.activemq.artemis.tests.compatibility.GroovyRun.SNAPSHOT;
-
-public abstract class VersionedBaseTest {
+public abstract class VersionedBaseTest extends ClasspathBaseTest {
 
    protected final String server;
    protected final String sender;
@@ -45,8 +33,6 @@ public abstract class VersionedBaseTest {
    protected ClassLoader senderClassloader;
    protected ClassLoader receiverClassloader;
 
-   protected static Map<String, ClassLoader> loaderMap = new HashMap<>();
-
    public VersionedBaseTest(String server, String sender, String receiver) throws Exception {
       if (server == null) {
          server = sender;
@@ -54,25 +40,9 @@ public abstract class VersionedBaseTest {
       this.server = server;
       this.sender = sender;
       this.receiver = receiver;
-      this.serverClassloader = getClasspathProperty(server);
-      this.senderClassloader = getClasspathProperty(sender);
-      this.receiverClassloader = getClasspathProperty(receiver);
-   }
-
-   // This is a test optimization..
-   // if false it will span a new VM for each classLoader used.
-   // this can be a bit faster
-   public static final boolean USE_CLASSLOADER = true;
-
-   private static HashSet<String> printed = new HashSet<>();
-
-   @ClassRule
-   public static TemporaryFolder serverFolder;
-
-   static {
-      File parent = new File("./target/tmp");
-      parent.mkdirs();
-      serverFolder = new TemporaryFolder(parent);
+      this.serverClassloader = getClasspath(server);
+      this.senderClassloader = getClasspath(sender);
+      this.receiverClassloader = getClasspath(receiver);
    }
 
    @AfterClass
@@ -80,97 +50,6 @@ public abstract class VersionedBaseTest {
       loaderMap.clear();
    }
 
-   protected static Object evaluate(ClassLoader loader, String script, String... arguments) throws Exception {
-      return tclCall(loader, () -> {
-         Class clazz = loader.loadClass(GroovyRun.class.getName());
-         Method method = clazz.getMethod("evaluate", String.class, String[].class);
-         return method.invoke(null, script, arguments);
-      });
-   }
-
-   protected static void setVariable(ClassLoader loader, String name, Object object) throws Exception {
-      tclCall(loader, () -> {
-         Class clazz = loader.loadClass(GroovyRun.class.getName());
-         Method method = clazz.getMethod("setVariable", String.class, Object.class);
-         method.invoke(null, name, object);
-         return null;
-      });
-   }
-
-   protected static Object setVariable(ClassLoader loader, String name) throws Exception {
-      return tclCall(loader, () -> {
-         Class clazz = loader.loadClass(GroovyRun.class.getName());
-         Method method = clazz.getMethod("getVariable", String.class);
-         return method.invoke(null, name);
-      });
-   }
-
-   protected static Object execute(ClassLoader loader, String script) throws Exception {
-      return tclCall(loader, () -> {
-         Class clazz = loader.loadClass(GroovyRun.class.getName());
-         Method method = clazz.getMethod("execute", String.class);
-         return method.invoke(null, script);
-      });
-   }
-
-   protected static Object tclCall(ClassLoader loader, CallIt run) throws Exception {
-
-      ClassLoader original = Thread.currentThread().getContextClassLoader();
-      Thread.currentThread().setContextClassLoader(loader);
-      try {
-         return run.run();
-      } finally {
-         Thread.currentThread().setContextClassLoader(original);
-      }
-   }
-
-   public interface CallIt {
-      Object run() throws Exception;
-   }
-
-   protected static ClassLoader defineClassLoader(String classPath) throws MalformedURLException {
-      String[] classPathArray = classPath.split(File.pathSeparator);
-      URL[] elements = new URL[classPathArray.length];
-      for (int i = 0; i < classPathArray.length; i++) {
-         elements[i] = new File(classPathArray[i]).toPath().toUri().toURL();
-      }
-
-      return new URLClassLoader(elements, null);
-   }
-
-   protected static ClassLoader getClasspathProperty(String name) throws Exception {
-
-      if (name.equals(SNAPSHOT)) {
-         return VersionedBaseTest.class.getClassLoader();
-      }
-
-      ClassLoader loader = loaderMap.get(name);
-      if (loader != null) {
-         return loader;
-      }
-
-      String value = System.getProperty(name);
-
-      if (!printed.contains(name)) {
-         boolean ok = value != null && !value.trim().isEmpty();
-         if (!ok) {
-            System.out.println("Add \"-D" + name + "=\'CLASSPATH\'\" into your VM settings");
-            System.out.println("You will see it in the output from mvn install at the compatibility-tests");
-            System.out.println("... look for output from dependency-scan");
-
-            // our dependency scan used at the pom under compatibility-tests/pom.xml will generate these, example:
-            // [INFO] dependency-scan setting: -DARTEMIS-140="/Users/someuser/....."
-            // copy that into your IDE setting and you should be able to debug it
-         }
-         Assume.assumeTrue("Cannot run these tests, no classpath found", ok);
-      }
-
-      loader = defineClassLoader(value);
-      loaderMap.put(name, loader);
-
-      return loader;
-   }
-
    protected static List<Object[]> combinatory(Object[] rootSide, Object[] sideLeft, Object[] sideRight) {
       LinkedList<Object[]> combinations = new LinkedList<>();
 
@@ -193,7 +72,12 @@ public abstract class VersionedBaseTest {
       startServer(folder, loader, serverName, globalMaxSize, false);
 
    }
-   public void startServer(File folder, ClassLoader loader, String serverName, String globalMaxSize, boolean setAddressSettings) throws Throwable {
+
+   public void startServer(File folder,
+                           ClassLoader loader,
+                           String serverName,
+                           String globalMaxSize,
+                           boolean setAddressSettings) throws Throwable {
       folder.mkdirs();
 
       String scriptToUse;
@@ -208,6 +92,7 @@ public abstract class VersionedBaseTest {
       setVariable(loader, "setAddressSettings", setAddressSettings);
       evaluate(loader, scriptToUse, folder.getAbsolutePath(), serverName, server, sender, receiver, globalMaxSize);
    }
+
    public void stopServer(ClassLoader loader) throws Throwable {
       execute(loader, "server.stop()");
    }