From 82f1e7a50320cbc7b7d6da02c2794f1dd96a5e93 Mon Sep 17 00:00:00 2001 From: Martyn Taylor Date: Mon, 12 Jan 2015 15:52:38 +0000 Subject: [PATCH 1/8] ActiveMQ6-65 Examples updated: 3rd party CatX deps Removes any occurances of CatX deps from examples and removes a couple of other references to Cat X 3rd party deps. --- docs/user-manual/en/client-classpath.md | 4 ++-- examples/core/embedded-remote/pom.xml | 5 ----- examples/core/embedded/pom.xml | 5 ----- examples/core/perf/pom.xml | 10 ---------- examples/core/vertx-connector/pom.xml | 10 ++-------- examples/jms/activemq-ra-rar/pom.xml | 8 ++------ examples/jms/aerogear/pom.xml | 1 - examples/jms/applet/applet.html | 2 +- examples/jms/bridge/pom.xml | 2 -- examples/jms/ha-policy-autobackup/pom.xml | 2 -- examples/jms/jms-bridge/readme.html | 10 +++++++--- .../apache/activemq/jms/example/JMSBridgeExample.java | 4 +--- examples/jms/perf/pom.xml | 10 ++++------ examples/jms/proton-cpp/pom.xml | 10 ++-------- examples/jms/stop-server-failover/pom.xml | 2 -- examples/jms/xa-heuristic/pom.xml | 5 ----- examples/jms/xa-with-jta/pom.xml | 5 ----- .../apache/activemq/jms/example/XAwithJTAExample.java | 2 -- 18 files changed, 21 insertions(+), 76 deletions(-) diff --git a/docs/user-manual/en/client-classpath.md b/docs/user-manual/en/client-classpath.md index 51ee972212..120fce5e76 100644 --- a/docs/user-manual/en/client-classpath.md +++ b/docs/user-manual/en/client-classpath.md @@ -20,10 +20,10 @@ on your client classpath. ## JMS Client If you are using JMS on the client side, then you will also need to -include `activemq-jms-client.jar` and `jboss-jms-api.jar`. +include `activemq-jms-client.jar` and `geronimo-jms_2.0_spec.jar`. > **Note** > -> `jboss-jms-api.jar` just contains Java EE API interface classes needed +> `geronimo-jms_2.0_spec.jar` just contains Java EE API interface classes needed > for the `javax.jms.*` classes. If you already have a jar with these > interface classes on your classpath, you will not need it. diff --git a/examples/core/embedded-remote/pom.xml b/examples/core/embedded-remote/pom.xml index 73de0c279e..dc3cde2f00 100644 --- a/examples/core/embedded-remote/pom.xml +++ b/examples/core/embedded-remote/pom.xml @@ -52,11 +52,6 @@ under the License. io.netty netty-all - - org.jboss.javaee - jboss-jms-api - 1.1.0.GA - org.apache.geronimo.specs geronimo-jms_2.0_spec diff --git a/examples/core/embedded/pom.xml b/examples/core/embedded/pom.xml index 0319de763d..92fe4f1ed9 100644 --- a/examples/core/embedded/pom.xml +++ b/examples/core/embedded/pom.xml @@ -52,11 +52,6 @@ under the License. io.netty netty-all - - org.jboss.javaee - jboss-jms-api - 1.1.0.GA - org.apache.geronimo.specs geronimo-jms_2.0_spec diff --git a/examples/core/perf/pom.xml b/examples/core/perf/pom.xml index a3fe6431d3..131d424dab 100644 --- a/examples/core/perf/pom.xml +++ b/examples/core/perf/pom.xml @@ -48,11 +48,6 @@ under the License. netty-all ${netty.version} - - org.jboss.javaee - jboss-jms-api - 1.1.0.GA - org.apache.activemq.examples.jms activemq-jms-examples-common @@ -128,11 +123,6 @@ under the License. netty-all ${netty.version} - - org.jboss.javaee - jboss-jms-api - 1.1.0.GA - diff --git a/examples/core/vertx-connector/pom.xml b/examples/core/vertx-connector/pom.xml index c8d013f53a..f401739277 100644 --- a/examples/core/vertx-connector/pom.xml +++ b/examples/core/vertx-connector/pom.xml @@ -57,9 +57,8 @@ under the License. ${netty.version} - org.jboss.javaee - jboss-jms-api - 1.1.0.GA + org.apache.geronimo.specs + geronimo-jms_2.0_spec org.apache.geronimo.specs @@ -158,11 +157,6 @@ under the License. netty-all ${netty.version} - - org.jboss.javaee - jboss-jms-api - 1.1.0.GA - io.vertx vertx-core diff --git a/examples/jms/activemq-ra-rar/pom.xml b/examples/jms/activemq-ra-rar/pom.xml index 539272d4bc..cefa69a97b 100644 --- a/examples/jms/activemq-ra-rar/pom.xml +++ b/examples/jms/activemq-ra-rar/pom.xml @@ -51,12 +51,8 @@ under the License. geronimo-jms_2.0_spec - org.apache.geronimo.specs - geronimo-ejb_3.0_spec - - - jboss.jbossts.jts - jbossjts-jacorb + org.apache.geronimo.specs + geronimo-ejb_3.0_spec diff --git a/examples/jms/aerogear/pom.xml b/examples/jms/aerogear/pom.xml index 14063b5347..0004bc0f98 100644 --- a/examples/jms/aerogear/pom.xml +++ b/examples/jms/aerogear/pom.xml @@ -140,7 +140,6 @@ under the License. org.apache.geronimo.specs geronimo-jms_2.0_spec - ${geronimo.jms.2.spec.version} diff --git a/examples/jms/applet/applet.html b/examples/jms/applet/applet.html index e604076205..c3793d78da 100644 --- a/examples/jms/applet/applet.html +++ b/examples/jms/applet/applet.html @@ -30,7 +30,7 @@ under the License. diff --git a/examples/jms/bridge/pom.xml b/examples/jms/bridge/pom.xml index de646b5277..31fde74018 100644 --- a/examples/jms/bridge/pom.xml +++ b/examples/jms/bridge/pom.xml @@ -70,8 +70,6 @@ under the License. start - 1199 - 1198 ${basedir}/target/classes/activemq/server1 true diff --git a/examples/jms/ha-policy-autobackup/pom.xml b/examples/jms/ha-policy-autobackup/pom.xml index 369002279d..f8d0a4dfa2 100644 --- a/examples/jms/ha-policy-autobackup/pom.xml +++ b/examples/jms/ha-policy-autobackup/pom.xml @@ -71,8 +71,6 @@ under the License. start - 1199 - 1198 ${basedir}/target/classes/activemq/server1 true diff --git a/examples/jms/jms-bridge/readme.html b/examples/jms/jms-bridge/readme.html index 2864bae669..5cf959ce08 100644 --- a/examples/jms/jms-bridge/readme.html +++ b/examples/jms/jms-bridge/readme.html @@ -118,7 +118,12 @@ under the License. InitialContext sourceContext = createContext(sourceServer); InitialContext targetContext = createContext(targetServer); -
  • We then create a JMS Bridge and start it, Note, the Bridge needs a transaction manager, in this instance we will use the JBoss TM
  • +
  • We then create a JMS Bridge and start it, Note, for certain quality of service modes such as + ONCE_AND_ONCE_ONLY and AT_LEAST_ONCE a Transaction Manager is required to ensure Messages are delivered + accordingly. A Transaction Manager can be either loaded via implementation of TransactionManagerLocator intefer + and loaded via standard a ServiceLoader or by explicitly setting an instance of a Transaction Manager on the + bridge using setTranscationManager(TransactionManager tm) method. In this example we'll be using the DUPLICATES_OK + quality of service so there is no need for a Transaction Manager.
                 JMSBridge jmsBridge = new JMSBridgeImpl(
                    new JNDIConnectionFactoryFactory(sourceJndiParams, "source/ConnectionFactory"),
    @@ -132,13 +137,12 @@ under the License.
                    null,
                    5000,
                    10,
    -               QualityOfServiceMode.ONCE_AND_ONLY_ONCE,
    +               QualityOfServiceMode.DUPLICATES_OK,
                    1,
                    -1,
                    null,
                    null,
                    true);
    -            jmsBridge.setTransactionManager(new TransactionManagerImple());
                 ....
             jmsBridge.start();
             
    diff --git a/examples/jms/jms-bridge/src/main/java/org/apache/activemq/jms/example/JMSBridgeExample.java b/examples/jms/jms-bridge/src/main/java/org/apache/activemq/jms/example/JMSBridgeExample.java index f6ff686c36..0eaa6353f6 100644 --- a/examples/jms/jms-bridge/src/main/java/org/apache/activemq/jms/example/JMSBridgeExample.java +++ b/examples/jms/jms-bridge/src/main/java/org/apache/activemq/jms/example/JMSBridgeExample.java @@ -16,7 +16,6 @@ */ package org.apache.activemq.jms.example; -import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple; import org.apache.activemq.jms.bridge.JMSBridge; import org.apache.activemq.jms.bridge.QualityOfServiceMode; import org.apache.activemq.jms.bridge.impl.JMSBridgeImpl; @@ -77,13 +76,12 @@ public class JMSBridgeExample null, 5000, 10, - QualityOfServiceMode.ONCE_AND_ONLY_ONCE, + QualityOfServiceMode.DUPLICATES_OK, 1, -1, null, null, true); - jmsBridge.setTransactionManager(new TransactionManagerImple()); Connection sourceConnection = null; Connection targetConnection = null; diff --git a/examples/jms/perf/pom.xml b/examples/jms/perf/pom.xml index 74a4ba7be7..df34152f3c 100644 --- a/examples/jms/perf/pom.xml +++ b/examples/jms/perf/pom.xml @@ -49,9 +49,8 @@ under the License. ${netty.version} - org.jboss.javaee - jboss-jms-api - 1.1.0.GA + org.apache.geronimo.specs + geronimo-jms_2.0_spec org.apache.activemq.examples.jms @@ -129,9 +128,8 @@ under the License. ${netty.version} - org.jboss.javaee - jboss-jms-api - 1.1.0.GA + org.apache.geronimo.specs + geronimo-jms_2.0_spec diff --git a/examples/jms/proton-cpp/pom.xml b/examples/jms/proton-cpp/pom.xml index 41c0b3d9f8..a9f1596005 100644 --- a/examples/jms/proton-cpp/pom.xml +++ b/examples/jms/proton-cpp/pom.xml @@ -48,11 +48,6 @@ under the License. netty-all ${netty.version} - - org.jboss.javaee - jboss-jms-api - 1.1.0.GA - org.apache.geronimo.specs geronimo-jms_2.0_spec @@ -130,9 +125,8 @@ under the License. ${netty.version} - org.jboss.javaee - jboss-jms-api - 1.1.0.GA + org.apache.geronimo.specs + geronimo-jms_2.0_spec diff --git a/examples/jms/stop-server-failover/pom.xml b/examples/jms/stop-server-failover/pom.xml index e35869ad16..0e11b9fa44 100644 --- a/examples/jms/stop-server-failover/pom.xml +++ b/examples/jms/stop-server-failover/pom.xml @@ -75,8 +75,6 @@ under the License. start - 1199 - 1198 ${basedir}/target/classes/activemq/server1 true diff --git a/examples/jms/xa-heuristic/pom.xml b/examples/jms/xa-heuristic/pom.xml index 5079f786cd..126e55fe3f 100644 --- a/examples/jms/xa-heuristic/pom.xml +++ b/examples/jms/xa-heuristic/pom.xml @@ -42,11 +42,6 @@ under the License. org.apache.geronimo.specs geronimo-jms_2.0_spec - - org.jboss.jbossts.jts - jbossjts-jacorb - 4.17.4.Final - diff --git a/examples/jms/xa-with-jta/pom.xml b/examples/jms/xa-with-jta/pom.xml index defdc9f575..baf9b1abf8 100644 --- a/examples/jms/xa-with-jta/pom.xml +++ b/examples/jms/xa-with-jta/pom.xml @@ -46,11 +46,6 @@ under the License. org.apache.geronimo.specs geronimo-ejb_3.0_spec - - org.jboss.jbossts - jbossjta - 4.16.4.Final - org.apache.geronimo.specs geronimo-jta_1.1_spec diff --git a/examples/jms/xa-with-jta/src/main/java/org/apache/activemq/jms/example/XAwithJTAExample.java b/examples/jms/xa-with-jta/src/main/java/org/apache/activemq/jms/example/XAwithJTAExample.java index ed181ca667..abeed14bb0 100644 --- a/examples/jms/xa-with-jta/src/main/java/org/apache/activemq/jms/example/XAwithJTAExample.java +++ b/examples/jms/xa-with-jta/src/main/java/org/apache/activemq/jms/example/XAwithJTAExample.java @@ -30,8 +30,6 @@ import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; -import com.arjuna.ats.jta.TransactionManager; - import org.apache.activemq.common.example.ActiveMQExample; /** From 86cdc589d8464ce1b143fdeca84d71379b723b53 Mon Sep 17 00:00:00 2001 From: Martyn Taylor Date: Mon, 12 Jan 2015 15:54:40 +0000 Subject: [PATCH 2/8] ActiveMQ6-65 Removes XA with JTA example This example requires a Transaction Manager implementation to run. As we are not shipping with an appropriate Transaction Manager this is being removed. --- examples/jms/pom.xml | 1 - examples/jms/xa-with-jta/pom.xml | 137 ----------- examples/jms/xa-with-jta/readme.html | 220 ------------------ .../jms/example/XAwithJTAExample.java | 220 ------------------ .../server0/activemq-configuration.xml | 54 ----- .../activemq/server0/activemq-jms.xml | 28 --- .../activemq/server0/activemq-users.xml | 27 --- .../src/main/resources/jbossts-properties.xml | 175 -------------- .../src/main/resources/jndi.properties | 20 -- 9 files changed, 882 deletions(-) delete mode 100644 examples/jms/xa-with-jta/pom.xml delete mode 100644 examples/jms/xa-with-jta/readme.html delete mode 100644 examples/jms/xa-with-jta/src/main/java/org/apache/activemq/jms/example/XAwithJTAExample.java delete mode 100644 examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-configuration.xml delete mode 100644 examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-jms.xml delete mode 100644 examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-users.xml delete mode 100644 examples/jms/xa-with-jta/src/main/resources/jbossts-properties.xml delete mode 100644 examples/jms/xa-with-jta/src/main/resources/jndi.properties diff --git a/examples/jms/pom.xml b/examples/jms/pom.xml index d5efa761ad..b7928dec41 100644 --- a/examples/jms/pom.xml +++ b/examples/jms/pom.xml @@ -128,7 +128,6 @@ under the License. xa-heuristic xa-receive xa-send - xa-with-jta diff --git a/examples/jms/xa-with-jta/pom.xml b/examples/jms/xa-with-jta/pom.xml deleted file mode 100644 index baf9b1abf8..0000000000 --- a/examples/jms/xa-with-jta/pom.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - 4.0.0 - - - org.apache.activemq.examples.jms - jms-examples - 6.0.0-SNAPSHOT - - - activemq-jms-xa-with-jta-example - jar - ActiveMQ6 JMS XA with JTA Example - - - - org.apache.activemq.examples.jms - activemq-jms-examples-common - ${project.version} - - - org.apache.geronimo.specs - geronimo-jms_2.0_spec - - - org.apache.geronimo.specs - geronimo-ejb_3.0_spec - - - org.apache.geronimo.specs - geronimo-jta_1.1_spec - 1.1.1 - - - - - - - org.apache.activemq - activemq-maven-plugin - - - start - - start - - - - - build.directory - ${basedir}/target/ - - - - - - runClient - - runClient - - - org.apache.activemq.jms.example.XAwithJTAExample - - - - stop - - stop - - - - - - org.apache.activemq.examples.jms - activemq-jms-xa-with-jta-example - ${project.version} - - - org.apache.activemq - activemq-core-client - ${project.version} - - - org.apache.activemq - activemq-server - ${project.version} - - - org.apache.activemq - activemq-jms-client - ${project.version} - - - org.apache.activemq - activemq-jms-server - ${project.version} - - - io.netty - netty-all - ${netty.version} - - - org.apache.geronimo.specs - geronimo-jms_2.0_spec - ${geronimo.jms.2.spec.version} - - - - false - ${basedir}/target/classes/activemq/server0 - - - - - - diff --git a/examples/jms/xa-with-jta/readme.html b/examples/jms/xa-with-jta/readme.html deleted file mode 100644 index 8a77a37f61..0000000000 --- a/examples/jms/xa-with-jta/readme.html +++ /dev/null @@ -1,220 +0,0 @@ - - - - - ActiveMQ JMS XA with JTA Example - - - - - -

    JMS XA with JTA Example

    - -

    This example shows you how to use JTA interfaces to control transactions with ActiveMQ. JTA provides - facilities to start and stop a transaction and enlist XA resources into a transaction.

    - -

    ActiveMQ is JTA aware, meaning you can use ActiveMQ in a XA transactional environment - and participate in XA transactions. It provides the javax.transaction.xa.XAResource interface for that - purpose. Users can get a XAConnectionFactory to create XAConnections and XASessions.

    - -

    In this example we get a transaction manager from JBoss JTA to control the transactions. First we create an XASession - for receiving and a normal session for sending. Then we start a new xa transaction and enlist the receiving - XASession through its XAResource. We then send two words, 'hello' and 'world', receive them, and let the - transaction roll back. The received messages are cancelled back to the queue. Next we start - a new transaction with the same XAResource enlisted, but this time we commit the transaction after receiving the - messages. Then we check that no more messages are to be received. In each transaction a dummy XAResource is also - enlisted to show the transaction processing information.

    - -

    Example step-by-step

    -

    To run the example, simply type mvn verify from this directory. It will download the JBoss JTA jars before - it launches the example.

    - -
      -
    1. First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the client-jndi.properties file in the directory ../common/config
    2. -
      -           InitialContext initialContext = getContext(0);
      -        
      - -
    3. We look-up the JMS queue object from JNDI
    4. -
      -           Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");
      -        
      - -
    5. We perform a lookup on the XA Connection Factory
    6. -
      -           XAConnectionFactory cf = (XAConnectionFactory) initialContext.lookup("/XAConnectionFactory");
      -        
      - -
    7. We create a JMS XAConnection
    8. -
      -           connection = cf.createXAConnection();
      -        
      - -
    9. We Start the connection
    10. -
      -           connection.start();
      -        
      - -
    11. We create a JMS XASession
    12. -
      -          XASession xaSession = connection.createXASession();
      -       
      - -
    13. We create a normal session
    14. -
      -          Session normalSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      -       
      - -
    15. We create a normal Message Producer
    16. -
      -           
      -           MessageProducer normalProducer = normalSession.createProducer(queue);
      -           
      -       
      - -
    17. We get the JMS Session
    18. -
      -          Session session = xaSession.getSession();
      -       
      - -
    19. We create a message consumer
    20. -
      -          MessageConsumer xaConsumer = session.createConsumer(queue); 
      -       
      - -
    21. We create two Text Messages
    22. -
      -          
      -          TextMessage helloMessage = session.createTextMessage("hello");
      -          TextMessage worldMessage = session.createTextMessage("world");
      -          
      -       
      - -
    23. We get the Transaction Manager
    24. -
      -          javax.transaction.TransactionManager txMgr = TransactionManager.transactionManager();
      -       
      - -
    25. We start a transaction
    26. -
      -          txMgr.begin();
      -       
      - -
    27. We get the JMS XAResource
    28. -
      -          XAResource xaRes = xaSession.getXAResource();
      -       
      - -
    29. We enlist the resources in the Transaction work
    30. -
      -          
      -          Transaction transaction = txMgr.getTransaction();
      -          transaction.enlistResource(new DummyXAResource());
      -          transaction.enlistResource(xaRes);
      -          
      -       
      - -
    31. We send two messages.
    32. -
      -          
      -         normalProducer.send(helloMessage);
      -         normalProducer.send(worldMessage);
      -          
      -       
      - -
    33. We receive the messages
    34. -
      -          
      -          TextMessage rm1 = (TextMessage)xaConsumer.receive();
      -          System.out.println("Message received: " + rm1.getText());
      -          TextMessage rm2 = (TextMessage)xaConsumer.receive();
      -          System.out.println("Message received: " + rm2.getText());
      -          
      -       
      - -
    35. We roll back the transaction
    36. -
      -          txMgr.rollback();
      -       
      - -
    37. We create another transaction
    38. -
      -          
      -          txMgr.begin();
      -          transaction = txMgr.getTransaction();
      -          
      -       
      - -
    39. We enlist the resources to start the transaction work
    40. -
      -                   
      -          transaction.enlistResource(new DummyXAResource());
      -          transaction.enlistResource(xaRes);
      -          
      -       
      - -
    41. We receive those messages again
    42. -
      -           
      -           rm1 = (TextMessage)xaConsumer.receive();
      -           System.out.println("Message received again: " + rm1.getText());
      -           rm2 = (TextMessage)xaConsumer.receive();
      -           System.out.println("Message received again: " + rm2.getText());
      -            
      -       
      - -
    43. We commit
    44. -
      -          txMgr.commit();
      -       
      - -
    45. We check that no more messages are received.
    46. -
      -          
      -          TextMessage rm3 = (TextMessage)xaConsumer.receive(2000);
      -          if (rm3 == null)
      -          {
      -             System.out.println("No message received after commit.");
      -          }
      -          else
      -          {
      -             result = false;
      -          }
      -          
      -       
      - -
    47. And finally, always remember to close your JMS connections and resources after use, in a finally block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects
    48. - -
      -           finally
      -           {
      -              if (initialContext != null)
      -              {
      -                initialContext.close();
      -              }
      -              if (connection != null)
      -              {
      -                 connection.close();
      -              }
      -           }
      -        
      -
    - - diff --git a/examples/jms/xa-with-jta/src/main/java/org/apache/activemq/jms/example/XAwithJTAExample.java b/examples/jms/xa-with-jta/src/main/java/org/apache/activemq/jms/example/XAwithJTAExample.java deleted file mode 100644 index abeed14bb0..0000000000 --- a/examples/jms/xa-with-jta/src/main/java/org/apache/activemq/jms/example/XAwithJTAExample.java +++ /dev/null @@ -1,220 +0,0 @@ -/** - * 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.jms.example; - -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TextMessage; -import javax.jms.XAConnection; -import javax.jms.XAConnectionFactory; -import javax.jms.XASession; -import javax.naming.InitialContext; -import javax.transaction.Transaction; -import javax.transaction.xa.XAException; -import javax.transaction.xa.XAResource; -import javax.transaction.xa.Xid; - -import org.apache.activemq.common.example.ActiveMQExample; - -/** - * A simple JMS example showing the ActiveMQ XA support with JTA. - * - * @author Howard Gao - */ -public class XAwithJTAExample extends ActiveMQExample -{ - private volatile boolean result = true; - - public static void main(final String[] args) - { - new XAwithJTAExample().run(args); - } - - @Override - public boolean runExample() throws Exception - { - XAConnection connection = null; - InitialContext initialContext = null; - try - { - // Step 1. Create an initial context to perform the JNDI lookup. - initialContext = new InitialContext(); - - // Step 2. Lookup on the queue - Queue queue = (Queue)initialContext.lookup("queue/exampleQueue"); - - // Step 3. Perform a lookup on the XA Connection Factory - XAConnectionFactory cf = (XAConnectionFactory)initialContext.lookup("XAConnectionFactory"); - - // Step 4.Create a JMS XAConnection - connection = cf.createXAConnection(); - - // Step 5. Start the connection - connection.start(); - - // Step 6. Create a JMS XASession - XASession xaSession = connection.createXASession(); - - // Step 7. Create a normal session - Session normalSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - // Step 8. Create a normal Message Producer - MessageProducer normalProducer = normalSession.createProducer(queue); - - // Step 9. Get the JMS Session - Session session = xaSession.getSession(); - - // Step 10. Create a message consumer - MessageConsumer xaConsumer = session.createConsumer(queue); - - // Step 11. Create two Text Messages - TextMessage helloMessage = session.createTextMessage("hello"); - TextMessage worldMessage = session.createTextMessage("world"); - - // Step 12. Get the Transaction Manager - javax.transaction.TransactionManager txMgr = TransactionManager.transactionManager(); - - // Step 13. Start a transaction - txMgr.begin(); - - // Step 14. Get the JMS XAResource - XAResource xaRes = xaSession.getXAResource(); - - // Step 15. enlist the resource in the Transaction work - Transaction transaction = txMgr.getTransaction(); - transaction.enlistResource(new DummyXAResource()); - transaction.enlistResource(xaRes); - - // Step 16. Send two messages. - normalProducer.send(helloMessage); - normalProducer.send(worldMessage); - - // Step 17. Receive the message - TextMessage rm1 = (TextMessage)xaConsumer.receive(); - System.out.println("Message received: " + rm1.getText()); - TextMessage rm2 = (TextMessage)xaConsumer.receive(); - System.out.println("Message received: " + rm2.getText()); - - // Step 18. Roll back the transaction - txMgr.rollback(); - - // Step 19. Create another transaction - txMgr.begin(); - transaction = txMgr.getTransaction(); - - // Step 20. Enlist the resources to start the transaction work - transaction.enlistResource(new DummyXAResource()); - transaction.enlistResource(xaRes); - - // Step 21. receive those messages again - rm1 = (TextMessage)xaConsumer.receive(); - System.out.println("Message received again: " + rm1.getText()); - rm2 = (TextMessage)xaConsumer.receive(); - System.out.println("Message received again: " + rm2.getText()); - - // Step 22. Commit! - txMgr.commit(); - - // Step 23. Check no more messages are received. - TextMessage rm3 = (TextMessage)xaConsumer.receive(2000); - if (rm3 == null) - { - System.out.println("No message received after commit."); - } - else - { - result = false; - } - - return result; - } - finally - { - // Step 24. Be sure to close our JMS resources! - if (initialContext != null) - { - initialContext.close(); - } - if (connection != null) - { - connection.close(); - } - } - } - - public static class DummyXAResource implements XAResource - { - - public DummyXAResource() - { - } - - public void commit(final Xid xid, final boolean arg1) throws XAException - { - System.out.println("DummyXAResource commit() called, xid: " + xid); - } - - public void end(final Xid xid, final int arg1) throws XAException - { - System.out.println("DummyXAResource end() called, xid: " + xid); - } - - public void forget(final Xid xid) throws XAException - { - System.out.println("DummyXAResource forget() called, xid: " + xid); - } - - public int getTransactionTimeout() throws XAException - { - return 0; - } - - public boolean isSameRM(final XAResource arg0) throws XAException - { - return this == arg0; - } - - public int prepare(final Xid xid) throws XAException - { - return XAResource.XA_OK; - } - - public Xid[] recover(final int arg0) throws XAException - { - return null; - } - - public void rollback(final Xid xid) throws XAException - { - System.out.println("DummyXAResource rollback() called, xid: " + xid); - } - - public boolean setTransactionTimeout(final int arg0) throws XAException - { - return false; - } - - public void start(final Xid xid, final int arg1) throws XAException - { - System.out.println("DummyXAResource start() called, Xid: " + xid); - } - - } - -} diff --git a/examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-configuration.xml b/examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-configuration.xml deleted file mode 100644 index 9f7ef1c0f8..0000000000 --- a/examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-configuration.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - ${build.directory}/server0/data/messaging/bindings - - ${build.directory}/server0/data/messaging/journal - - ${build.directory}/server0/data/messaging/largemessages - - ${build.directory}/server0/data/messaging/paging - - - - - org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory - - - - - - - - - - - - - - - - - - diff --git a/examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-jms.xml b/examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-jms.xml deleted file mode 100644 index 8ca9fd6e26..0000000000 --- a/examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-jms.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - diff --git a/examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-users.xml b/examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-users.xml deleted file mode 100644 index f63079de03..0000000000 --- a/examples/jms/xa-with-jta/src/main/resources/activemq/server0/activemq-users.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - diff --git a/examples/jms/xa-with-jta/src/main/resources/jbossts-properties.xml b/examples/jms/xa-with-jta/src/main/resources/jbossts-properties.xml deleted file mode 100644 index 8eb68a4220..0000000000 --- a/examples/jms/xa-with-jta/src/main/resources/jbossts-properties.xml +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - - YES - - - PutObjectStoreDirHere - - - ON - - - 1 - - - 1 - - - com.arjuna.ats.internal.jta.recovery.arjunacore.JTATransactionLogXAResourceOrphanFilter - com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter - - - - 0 - - - - - - com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule - com.arjuna.ats.internal.txoj.recovery.TORecoveryModule - com.arjuna.ats.internal.jts.recovery.transactions.TopLevelTransactionRecoveryModule - com.arjuna.ats.internal.jts.recovery.transactions.ServerTransactionRecoveryModule - com.arjuna.ats.internal.jta.recovery.jts.XARecoveryModule - - - - - com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner - com.arjuna.ats.internal.jts.recovery.contact.ExpiredContactScanner - com.arjuna.ats.internal.jts.recovery.transactions.ExpiredToplevelScanner - com.arjuna.ats.internal.jts.recovery.transactions.ExpiredServerScanner - - - - - - 4712 - - - - - 0 - - - - - - YES - - - - com.arjuna.ats.internal.jts.orbspecific.recovery.RecoveryEnablement - - - com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple - - com.arjuna.ats.internal.jta.transaction.arjunacore.UserTransactionImple - - com.arjuna.ats.internal.jta.transaction.jts.TransactionSynchronizationRegistryImple - - - CONFIGURATION_FILE - - - - com.arjuna.orbportability.orb.PreInit1=com.arjuna.ats.internal.jts.context.ContextPropagationManager - - com.arjuna.orbportability.orb.PostInit=com.arjuna.ats.jts.utils.ORBSetup - - com.arjuna.orbportability.orb.PostInit2=com.arjuna.ats.internal.jts.recovery.RecoveryInit - - com.arjuna.orbportability.orb.PostSet1=com.arjuna.ats.jts.utils.ORBSetup - - - - 4711 - - - - - - diff --git a/examples/jms/xa-with-jta/src/main/resources/jndi.properties b/examples/jms/xa-with-jta/src/main/resources/jndi.properties deleted file mode 100644 index 6364ce46d9..0000000000 --- a/examples/jms/xa-with-jta/src/main/resources/jndi.properties +++ /dev/null @@ -1,20 +0,0 @@ -# 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. - -java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory -java.naming.provider.url=tcp://localhost:5445 -queue.queue/exampleQueue=exampleQueue From b4e2884f14ac467f58cb1a85479ece1cbe36df03 Mon Sep 17 00:00:00 2001 From: jbertram Date: Mon, 12 Jan 2015 10:16:00 -0600 Subject: [PATCH 3/8] Allow snapshots to fix the build after removing parent root --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a84af9889f..4f3f440150 100644 --- a/pom.xml +++ b/pom.xml @@ -414,7 +414,7 @@ - false + true never From ec9ff4f55edf6e865f574c7be6cefa18db5dfeaa Mon Sep 17 00:00:00 2001 From: Clebert Suconic Date: Wed, 7 Jan 2015 14:56:31 -0500 Subject: [PATCH 4/8] ACTIVEMQ6-68 Improving Scale down routine and fixing test https://issues.apache.org/jira/browse/ACTIVEMQ6-68 The logic on transferring method is a bit complex, where I found a better way to calculate the targetIDs. This will also fix a few ScaleDownTests I also added some extra tests using ScaleDownDirect --- .../activemq/utils/LinkedListIterator.java | 2 +- .../cursor/impl/PageSubscriptionImpl.java | 18 +- .../core/postoffice/AddressManager.java | 3 + .../activemq/core/postoffice/PostOffice.java | 3 + .../core/postoffice/impl/PostOfficeImpl.java | 5 + .../postoffice/impl/SimpleAddressManager.java | 11 + .../apache/activemq/core/server/Queue.java | 9 +- .../impl/BackupRecoveryJournalLoader.java | 2 +- .../core/server/impl/LiveOnlyActivation.java | 3 +- .../activemq/core/server/impl/QueueImpl.java | 41 +- .../core/server/impl/ScaleDownHandler.java | 631 ++++++++++-------- .../impl/ScheduledDeliveryHandlerTest.java | 4 +- .../activemq/tests/util/ServiceTestBase.java | 2 +- .../integration/client/HangConsumerTest.java | 5 +- .../client/InterruptedLargeMessageTest.java | 4 +- .../cluster/distribution/ClusterTestBase.java | 6 +- .../server/ScaleDownDirectTest.java | 319 +++++++++ .../integration/server/ScaleDownTest.java | 66 +- .../unit/core/postoffice/impl/FakeQueue.java | 4 +- .../server/impl/fakes/FakePostOffice.java | 7 + 20 files changed, 819 insertions(+), 326 deletions(-) create mode 100644 tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/server/ScaleDownDirectTest.java diff --git a/activemq-core-client/src/main/java/org/apache/activemq/utils/LinkedListIterator.java b/activemq-core-client/src/main/java/org/apache/activemq/utils/LinkedListIterator.java index 4320dab31a..642dc80eff 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/utils/LinkedListIterator.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/utils/LinkedListIterator.java @@ -28,7 +28,7 @@ import java.util.Iterator; * * */ -public interface LinkedListIterator extends Iterator +public interface LinkedListIterator extends Iterator, AutoCloseable { void repeat(); diff --git a/activemq-server/src/main/java/org/apache/activemq/core/paging/cursor/impl/PageSubscriptionImpl.java b/activemq-server/src/main/java/org/apache/activemq/core/paging/cursor/impl/PageSubscriptionImpl.java index 6482795668..e6dfc568a8 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/paging/cursor/impl/PageSubscriptionImpl.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/paging/cursor/impl/PageSubscriptionImpl.java @@ -1247,6 +1247,8 @@ final class PageSubscriptionImpl implements PageSubscription private volatile boolean isredelivery = false; + private PagedReference currentDelivery = null; + private volatile PagedReference lastRedelivery = null; // We only store the position for redeliveries. They will be read from the SoftCache again during delivery. @@ -1298,9 +1300,9 @@ final class PageSubscriptionImpl implements PageSubscription if (cachedNext != null) { - PagedReference retPos = cachedNext; + currentDelivery = cachedNext; cachedNext = null; - return retPos; + return currentDelivery; } try @@ -1310,7 +1312,8 @@ final class PageSubscriptionImpl implements PageSubscription position = getStartPosition(); } - return moveNext(); + currentDelivery = moveNext(); + return currentDelivery; } catch (RuntimeException e) { @@ -1473,10 +1476,13 @@ final class PageSubscriptionImpl implements PageSubscription public void remove() { deliveredCount.incrementAndGet(); - PageCursorInfo info = PageSubscriptionImpl.this.getPageInfo(position); - if (info != null) + if (currentDelivery != null) { - info.remove(position); + PageCursorInfo info = PageSubscriptionImpl.this.getPageInfo(currentDelivery.getPosition()); + if (info != null) + { + info.remove(currentDelivery.getPosition()); + } } } diff --git a/activemq-server/src/main/java/org/apache/activemq/core/postoffice/AddressManager.java b/activemq-server/src/main/java/org/apache/activemq/core/postoffice/AddressManager.java index b0b98e8fc5..9ca7dace03 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/postoffice/AddressManager.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/postoffice/AddressManager.java @@ -17,6 +17,7 @@ package org.apache.activemq.core.postoffice; import java.util.Map; +import java.util.Set; import org.apache.activemq.api.core.SimpleString; import org.apache.activemq.core.transaction.Transaction; @@ -50,4 +51,6 @@ public interface AddressManager Binding getBinding(SimpleString queueName); Map getBindings(); + + Set getAddresses(); } diff --git a/activemq-server/src/main/java/org/apache/activemq/core/postoffice/PostOffice.java b/activemq-server/src/main/java/org/apache/activemq/core/postoffice/PostOffice.java index de28190b8a..e805d8bb6d 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/postoffice/PostOffice.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/postoffice/PostOffice.java @@ -17,6 +17,7 @@ package org.apache.activemq.core.postoffice; import java.util.Map; +import java.util.Set; import org.apache.activemq.api.core.Pair; import org.apache.activemq.api.core.SimpleString; @@ -95,4 +96,6 @@ public interface PostOffice extends ActiveMQComponent boolean isAddressBound(final SimpleString address) throws Exception; + Set getAddresses(); + } diff --git a/activemq-server/src/main/java/org/apache/activemq/core/postoffice/impl/PostOfficeImpl.java b/activemq-server/src/main/java/org/apache/activemq/core/postoffice/impl/PostOfficeImpl.java index 0d0fa036c1..a6b05bfb7f 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/postoffice/impl/PostOfficeImpl.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/postoffice/impl/PostOfficeImpl.java @@ -861,6 +861,11 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding return notificationLock; } + public Set getAddresses() + { + return addressManager.getAddresses(); + } + public void sendQueueInfoToQueue(final SimpleString queueName, final SimpleString address) throws Exception { // We send direct to the queue so we can send it to the same queue that is bound to the notifications address - diff --git a/activemq-server/src/main/java/org/apache/activemq/core/postoffice/impl/SimpleAddressManager.java b/activemq-server/src/main/java/org/apache/activemq/core/postoffice/impl/SimpleAddressManager.java index c11bbd537a..259ceb72f7 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/postoffice/impl/SimpleAddressManager.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/postoffice/impl/SimpleAddressManager.java @@ -16,7 +16,9 @@ */ package org.apache.activemq.core.postoffice.impl; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -151,6 +153,15 @@ public class SimpleAddressManager implements AddressManager mappings.clear(); } + + @Override + public Set getAddresses() + { + Set addresses = new HashSet<>(); + addresses.addAll(mappings.keySet()); + return addresses; + } + protected void removeBindingInternal(final SimpleString address, final SimpleString bindableName) { Bindings bindings = mappings.get(address); diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/Queue.java b/activemq-server/src/main/java/org/apache/activemq/core/server/Queue.java index 77cd91543d..4759df0f71 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/Queue.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/Queue.java @@ -176,6 +176,10 @@ public interface Queue extends Bindable boolean checkRedelivery(MessageReference ref, long timeBase, boolean ignoreRedeliveryDelay) throws Exception; + /** + * It will iterate thorugh memory only (not paging) + * @return + */ LinkedListIterator iterator(); LinkedListIterator totalIterator(); @@ -228,7 +232,10 @@ public interface Queue extends Bindable void incrementMesssagesAdded(); - List cancelScheduledMessages(); + /** + * cancels scheduled messages and send them to the head of the queue. + */ + void deliverScheduledMessages(); void postAcknowledge(MessageReference ref); diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/BackupRecoveryJournalLoader.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/BackupRecoveryJournalLoader.java index 32ea1dbf37..39b34df39a 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/BackupRecoveryJournalLoader.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/BackupRecoveryJournalLoader.java @@ -90,7 +90,7 @@ public class BackupRecoveryJournalLoader extends PostOfficeJournalLoader @Override public void postLoad(Journal messageJournal, ResourceManager resourceManager, Map>> duplicateIDMap) throws Exception { - ScaleDownHandler scaleDownHandler = new ScaleDownHandler(pagingManager, postOffice, nodeManager, clusterController); + ScaleDownHandler scaleDownHandler = new ScaleDownHandler(pagingManager, postOffice, nodeManager, clusterController, parentServer.getStorageManager()); locator.setProtocolManagerFactory(ActiveMQServerSideProtocolManagerFactory.getInstance()); try (ClientSessionFactory sessionFactory = locator.createSessionFactory()) diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/LiveOnlyActivation.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/LiveOnlyActivation.java index ff2c8072af..2265b47fed 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/LiveOnlyActivation.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/LiveOnlyActivation.java @@ -187,7 +187,8 @@ public class LiveOnlyActivation extends Activation ScaleDownHandler scaleDownHandler = new ScaleDownHandler(activeMQServer.getPagingManager(), activeMQServer.getPostOffice(), activeMQServer.getNodeManager(), - activeMQServer.getClusterManager().getClusterController()); + activeMQServer.getClusterManager().getClusterController(), + activeMQServer.getStorageManager()); ConcurrentMap duplicateIDCaches = ((PostOfficeImpl) activeMQServer.getPostOffice()).getDuplicateIDCaches(); Map>> duplicateIDMap = new HashMap<>(); for (SimpleString address : duplicateIDCaches.keySet()) diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueImpl.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueImpl.java index 9523205296..e127fe6037 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueImpl.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueImpl.java @@ -1220,9 +1220,18 @@ public class QueueImpl implements Queue } @Override - public List cancelScheduledMessages() + public void deliverScheduledMessages() { - return scheduledDeliveryHandler.cancel(null); + List scheduledMessages = scheduledDeliveryHandler.cancel(null); + if (scheduledMessages != null && scheduledMessages.size() > 0) + { + for (MessageReference ref : scheduledMessages) + { + ref.getMessage().putLongProperty(MessageImpl.HDR_SCHEDULED_DELIVERY_TIME, ref.getScheduledDeliveryTime()); + ref.setScheduledDeliveryTime(0); + } + this.addHead(scheduledMessages); + } } public long getMessagesAdded() @@ -3105,6 +3114,8 @@ public class QueueImpl implements Queue Iterator interIterator = null; LinkedListIterator messagesIterator = null; + Iterator lastIterator = null; + public TotalQueueIterator() { if (pageSubscription != null) @@ -3118,18 +3129,21 @@ public class QueueImpl implements Queue @Override public boolean hasNext() { - if (messagesIterator.hasNext()) + if (messagesIterator != null && messagesIterator.hasNext()) { + lastIterator = messagesIterator; return true; } if (interIterator.hasNext()) { + lastIterator = interIterator; return true; } if (pageIter != null) { if (pageIter.hasNext()) { + lastIterator = pageIter; return true; } } @@ -3140,18 +3154,21 @@ public class QueueImpl implements Queue @Override public MessageReference next() { - if (messagesIterator.hasNext()) + if (messagesIterator != null && messagesIterator.hasNext()) { - return messagesIterator.next(); + MessageReference msg = messagesIterator.next(); + return msg; } if (interIterator.hasNext()) { + lastIterator = interIterator; return interIterator.next(); } if (pageIter != null) { if (pageIter.hasNext()) { + lastIterator = pageIter; return pageIter.next(); } } @@ -3162,6 +3179,10 @@ public class QueueImpl implements Queue @Override public void remove() { + if (lastIterator != null) + { + lastIterator.remove(); + } } @Override @@ -3172,8 +3193,14 @@ public class QueueImpl implements Queue @Override public void close() { - if (pageIter != null) pageIter.close(); - messagesIterator.close(); + if (pageIter != null) + { + pageIter.close(); + } + if (messagesIterator != null) + { + messagesIterator.close(); + } } } diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ScaleDownHandler.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ScaleDownHandler.java index 1d351f47b9..f5f87f9724 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ScaleDownHandler.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ScaleDownHandler.java @@ -20,11 +20,13 @@ import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; import org.apache.activemq.api.core.Message; import org.apache.activemq.api.core.Pair; @@ -42,7 +44,9 @@ import org.apache.activemq.core.paging.PagingManager; import org.apache.activemq.core.paging.PagingStore; import org.apache.activemq.core.paging.cursor.PageSubscription; import org.apache.activemq.core.paging.cursor.PagedReference; +import org.apache.activemq.core.persistence.StorageManager; import org.apache.activemq.core.postoffice.Binding; +import org.apache.activemq.core.postoffice.Bindings; import org.apache.activemq.core.postoffice.PostOffice; import org.apache.activemq.core.postoffice.impl.LocalQueueBinding; import org.apache.activemq.core.postoffice.impl.PostOfficeImpl; @@ -56,6 +60,7 @@ import org.apache.activemq.core.server.cluster.ClusterController; import org.apache.activemq.core.transaction.ResourceManager; import org.apache.activemq.core.transaction.Transaction; import org.apache.activemq.core.transaction.TransactionOperation; +import org.apache.activemq.core.transaction.impl.TransactionImpl; import org.apache.activemq.utils.LinkedListIterator; public class ScaleDownHandler @@ -64,20 +69,22 @@ public class ScaleDownHandler final PostOffice postOffice; private NodeManager nodeManager; private final ClusterController clusterController; + private final StorageManager storageManager; private String targetNodeId; - public ScaleDownHandler(PagingManager pagingManager, PostOffice postOffice, NodeManager nodeManager, ClusterController clusterController) + public ScaleDownHandler(PagingManager pagingManager, PostOffice postOffice, NodeManager nodeManager, ClusterController clusterController, StorageManager storageManager) { this.pagingManager = pagingManager; this.postOffice = postOffice; this.nodeManager = nodeManager; this.clusterController = clusterController; + this.storageManager = storageManager; } public long scaleDown(ClientSessionFactory sessionFactory, ResourceManager resourceManager, Map>> duplicateIDMap, + List>> duplicateIDMap, SimpleString managementAddress, SimpleString targetNodeId) throws Exception { @@ -91,218 +98,239 @@ public class ScaleDownHandler return num; } - private long scaleDownMessages(ClientSessionFactory sessionFactory, SimpleString nodeId) throws Exception + public long scaleDownMessages(ClientSessionFactory sessionFactory, SimpleString nodeId) throws Exception { long messageCount = 0; targetNodeId = nodeId != null ? nodeId.toString() : getTargetNodeId(sessionFactory); - ClientSession session = sessionFactory.createSession(false, true, true); - Map queueIDs = new HashMap<>(); - ClientProducer producer = session.createProducer(); - - List addresses = new ArrayList<>(); - for (Map.Entry entry : postOffice.getAllBindings().entrySet()) + try (ClientSession session = sessionFactory.createSession(false, true, true)) { - if (entry.getValue() instanceof LocalQueueBinding) - { - SimpleString address = entry.getValue().getAddress(); + ClientProducer producer = session.createProducer(); - // There is a special case involving store-and-forward queues used for clustering. - // If this queue is supposed to forward messages to the server that I'm scaling down to I need to handle these messages differently. - boolean storeAndForward = false; - if (address.toString().startsWith("sf.")) + // perform a loop per address + for (SimpleString address : postOffice.getAddresses()) + { + ActiveMQServerLogger.LOGGER.debug("Scaling down address " + address); + Bindings bindings = postOffice.getBindingsForAddress(address); + + // It will get a list of queues on this address, ordered by the number of messages + Set queues = new TreeSet<>(new OrderQueueByNumberOfReferencesComparator()); + for (Binding binding : bindings.getBindings()) { - // these get special treatment later - storeAndForward = true; + if (binding instanceof LocalQueueBinding) + { + Queue queue = ((LocalQueueBinding) binding).getQueue(); + // as part of scale down we will cancel any scheduled message and pass it to theWhile we scan for the queues we will also cancel any scheduled messages and deliver them right away + queue.deliverScheduledMessages(); + queues.add(queue); + } } - // this means we haven't inspected this address before - if (!addresses.contains(address)) + + if (address.toString().startsWith("sf.")) { - addresses.add(address); + messageCount += scaleDownSNF(address, queues, producer); + } + else + { + messageCount += scaleDownRegularMessages(address, queues, session, producer); + } - PagingStore store = pagingManager.getPageStore(address); + } + } - // compile a list of all the relevant queues and queue iterators for this address - List queues = new ArrayList<>(); - Map> queueIterators = new HashMap<>(); - for (Binding binding : postOffice.getBindingsForAddress(address).getBindings()) + return messageCount; + } + + public long scaleDownRegularMessages(final SimpleString address, final Set queues, final ClientSession clientSession, final ClientProducer producer) throws Exception + { + ActiveMQServerLogger.LOGGER.debug("Scaling down messages on address " + address); + long messageCount = 0; + + final HashMap controls = new HashMap(); + + PagingStore pageStore = pagingManager.getPageStore(address); + + Transaction tx = new TransactionImpl(storageManager); + + pageStore.disableCleanup(); + + try + { + + for (Queue queue : queues) + { + controls.put(queue, new QueuesXRefInnerManager(clientSession, queue, pageStore)); + } + + // compile a list of all the relevant queues and queue iterators for this address + for (Queue loopQueue : queues) + { + ActiveMQServerLogger.LOGGER.debug("Scaling down messages on address " + address + " / performing loop on queue " + loopQueue); + + try (LinkedListIterator messagesIterator = loopQueue.totalIterator()) + { + + while (messagesIterator.hasNext()) { - if (binding instanceof LocalQueueBinding) + MessageReference messageReference = messagesIterator.next(); + Message message = messageReference.getMessage().copy(); + + ActiveMQServerLogger.LOGGER.debug("Reading message " + message + " from queue " + loopQueue); + Set queuesFound = new HashSet<>(); + + for (Map.Entry controlEntry : controls.entrySet()) { - Queue queue = ((LocalQueueBinding) binding).getQueue(); - //remove the scheduled messages and reset on the actual message ready for sending - //we may set the time multiple times on a message but it will always be the same. - //set the ref scheduled time to 0 so it is in the queue ready for resending - List messageReferences = queue.cancelScheduledMessages(); - for (MessageReference ref : messageReferences) + if (controlEntry.getKey() == loopQueue) { - ref.getMessage().putLongProperty(MessageImpl.HDR_SCHEDULED_DELIVERY_TIME, ref.getScheduledDeliveryTime()); - ref.setScheduledDeliveryTime(0); + // no need to lookup on itself, we just add it + queuesFound.add(controlEntry.getValue()); } - queue.addHead(messageReferences); - queues.add(queue); - queueIterators.put(queue.getName(), queue.totalIterator()); + else if (controlEntry.getValue().lookup(messageReference)) + { + ActiveMQServerLogger.LOGGER.debug("Message existed on queue " + controlEntry.getKey().getID() + " removeID=" + controlEntry.getValue().getQueueID()); + queuesFound.add(controlEntry.getValue()); + } + } + + // get the ID for every queue that contains the message + ByteBuffer buffer = ByteBuffer.allocate(queuesFound.size() * 8); + + + for (QueuesXRefInnerManager control : queuesFound) + { + long queueID = control.getQueueID(); + buffer.putLong(queueID); + } + + + message.putBytesProperty(MessageImpl.HDR_ROUTE_TO_IDS, buffer.array()); + + if (ActiveMQServerLogger.LOGGER.isDebugEnabled()) + { + if (messageReference.isPaged()) + { + ActiveMQServerLogger.LOGGER.debug("*********************<<<<< Scaling down pdgmessage " + message); + } + else + { + ActiveMQServerLogger.LOGGER.debug("*********************<<<<< Scaling down message " + message); + } + } + + producer.send(address, message); + messageCount++; + + messagesIterator.remove(); + + // We need to perform the ack / removal after sending, otherwise the message could been removed before the send is finished + for (QueuesXRefInnerManager queueFound : queuesFound) + { + ackMessageOnQueue(tx, queueFound.getQueue(), messageReference); + } + + } + } + } + + tx.commit(); + + + for (QueuesXRefInnerManager controlRemoved : controls.values()) + { + controlRemoved.close(); + } + + return messageCount; + } + finally + { + pageStore.enableCleanup(); + pageStore.getCursorProvider().scheduleCleanup(); + } + } + + private long scaleDownSNF(final SimpleString address, final Set queues, final ClientProducer producer) throws Exception + { + long messageCount = 0; + + final String propertyEnd; + + // If this SNF is towards our targetNodeId + boolean queueOnTarget = address.toString().endsWith(targetNodeId); + + if (queueOnTarget) + { + propertyEnd = targetNodeId; + } + else + { + propertyEnd = address.toString().substring(address.toString().lastIndexOf(".")); + } + + Transaction tx = new TransactionImpl(storageManager); + + for (Queue queue : queues) + { + // using auto-closeable + try (LinkedListIterator messagesIterator = queue.totalIterator()) + { + // loop through every message of this queue + while (messagesIterator.hasNext()) + { + MessageReference messageRef = messagesIterator.next(); + Message message = messageRef.getMessage().copy(); + + /* Here we are taking messages out of a store-and-forward queue and sending them to the corresponding + * address on the scale-down target server. However, we have to take the existing _HQ_ROUTE_TOsf.* + * property and put its value into the _HQ_ROUTE_TO property so the message is routed properly. + */ + + byte[] oldRouteToIDs = null; + + List propertiesToRemove = new ArrayList<>(); + message.removeProperty(MessageImpl.HDR_ROUTE_TO_IDS); + for (SimpleString propName : message.getPropertyNames()) + { + if (propName.startsWith(MessageImpl.HDR_ROUTE_TO_IDS)) + { + if (propName.toString().endsWith(propertyEnd)) + { + oldRouteToIDs = message.getBytesProperty(propName); + } + propertiesToRemove.add(propName); } } - // sort into descending order - order is based on the number of references in the queue - Collections.sort(queues, new OrderQueueByNumberOfReferencesComparator()); + // TODO: what if oldRouteToIDs == null ?? - // loop through every queue on this address - List checkedQueues = new ArrayList<>(); - for (Queue bigLoopQueue : queues) + for (SimpleString propertyToRemove : propertiesToRemove) { - checkedQueues.add(bigLoopQueue.getName()); - - LinkedListIterator bigLoopMessageIterator = bigLoopQueue.totalIterator(); - try - { - // loop through every message of this queue - while (bigLoopMessageIterator.hasNext()) - { - MessageReference bigLoopRef = bigLoopMessageIterator.next(); - Message message = bigLoopRef.getMessage().copy(); - - if (storeAndForward) - { - if (address.toString().endsWith(targetNodeId)) - { - /* Here we are taking messages out of a store-and-forward queue and sending them to the corresponding - * address on the scale-down target server. However, we have to take the existing _HQ_ROUTE_TOsf.* - * property and put its value into the _HQ_ROUTE_TO property so the message is routed properly. - */ - - byte[] oldRouteToIDs = null; - - List propertiesToRemove = new ArrayList<>(); - message.removeProperty(MessageImpl.HDR_ROUTE_TO_IDS); - for (SimpleString propName : message.getPropertyNames()) - { - if (propName.startsWith(MessageImpl.HDR_ROUTE_TO_IDS)) - { - if (propName.toString().endsWith(targetNodeId)) - { - oldRouteToIDs = message.getBytesProperty(propName); - } - propertiesToRemove.add(propName); - } - } - - for (SimpleString propertyToRemove : propertiesToRemove) - { - message.removeProperty(propertyToRemove); - } - - message.putBytesProperty(MessageImpl.HDR_ROUTE_TO_IDS, oldRouteToIDs); - } - else - { - /* Here we are taking messages out of a store-and-forward queue and sending them to the corresponding - * store-and-forward address on the scale-down target server. In this case we use a special property - * for the queue ID so that the scale-down target server can route it appropriately. - */ - byte[] oldRouteToIDs = null; - - List propertiesToRemove = new ArrayList<>(); - message.removeProperty(MessageImpl.HDR_ROUTE_TO_IDS); - for (SimpleString propName : message.getPropertyNames()) - { - if (propName.startsWith(MessageImpl.HDR_ROUTE_TO_IDS)) - { - if (propName.toString().endsWith(address.toString().substring(address.toString().lastIndexOf(".")))) - { - oldRouteToIDs = message.getBytesProperty(propName); - } - propertiesToRemove.add(propName); - } - } - - for (SimpleString propertyToRemove : propertiesToRemove) - { - message.removeProperty(propertyToRemove); - } - - message.putBytesProperty(MessageImpl.HDR_SCALEDOWN_TO_IDS, oldRouteToIDs); - } - - ActiveMQServerLogger.LOGGER.debug("Scaling down message " + message + " from " + address + " to " + message.getAddress() + " on node " + targetNodeId); - producer.send(message.getAddress(), message); - messageCount++; - bigLoopQueue.deleteReference(message.getMessageID()); - } - else - { - List queuesWithMessage = new ArrayList<>(); - queuesWithMessage.add(bigLoopQueue); - long messageId = message.getMessageID(); - - getQueuesWithMessage(store, queues, queueIterators, checkedQueues, bigLoopQueue, queuesWithMessage, bigLoopRef, messageId); - - // get the ID for every queue that contains the message - ByteBuffer buffer = ByteBuffer.allocate(queuesWithMessage.size() * 8); - StringBuilder logMessage = new StringBuilder(); - logMessage.append("Scaling down message ").append(messageId).append(" to "); - for (Queue queue : queuesWithMessage) - { - long queueID; - String queueName = queue.getName().toString(); - - if (queueIDs.containsKey(queueName)) - { - queueID = queueIDs.get(queueName); - } - else - { - queueID = createQueueIfNecessaryAndGetID(session, queue, address); - queueIDs.put(queueName, queueID); // store it so we don't have to look it up every time - } - - logMessage.append(queueName).append("(").append(queueID).append(")").append(", "); - buffer.putLong(queueID); - } - - logMessage.delete(logMessage.length() - 2, logMessage.length()); // trim off the trailing comma and space - ActiveMQServerLogger.LOGGER.debug(logMessage.append(" on address ").append(address)); - - message.putBytesProperty(MessageImpl.HDR_ROUTE_TO_IDS, buffer.array()); - //we need this incase we are sending back to the source server of the message, this basically - //acts like the bridge and ignores dup detection - if (message.containsProperty(MessageImpl.HDR_DUPLICATE_DETECTION_ID)) - { - byte[] bytes = new byte[24]; - - ByteBuffer bb = ByteBuffer.wrap(bytes); - bb.put(nodeManager.getUUID().asBytes()); - bb.putLong(messageId); - - message.putBytesProperty(MessageImpl.HDR_BRIDGE_DUPLICATE_ID, bb.array()); - } - - producer.send(address, message); - messageCount++; - - // delete the reference from all queues which contain it - bigLoopQueue.deleteReference(messageId); - for (Queue queue : queuesWithMessage) - { - queue.deleteReference(messageId); - } - } - } - } - finally - { - bigLoopMessageIterator.close(); - queueIterators.get(bigLoopQueue.getName()).close(); - } + message.removeProperty(propertyToRemove); } + + if (queueOnTarget) + { + message.putBytesProperty(MessageImpl.HDR_ROUTE_TO_IDS, oldRouteToIDs); + } + else + { + message.putBytesProperty(MessageImpl.HDR_SCALEDOWN_TO_IDS, oldRouteToIDs); + } + + ActiveMQServerLogger.LOGGER.debug("Scaling down message " + message + " from " + address + " to " + message.getAddress() + " on node " + targetNodeId); + producer.send(message.getAddress(), message); + + messageCount++; + + messagesIterator.remove(); + + ackMessageOnQueue(tx, queue, messageRef); } } } - producer.close(); - session.close(); + tx.commit(); return messageCount; } @@ -324,6 +352,8 @@ public class ScaleDownHandler Transaction transaction = resourceManager.getTransaction(xid); session.start(xid, XAResource.TMNOFLAGS); List allOperations = transaction.getAllOperations(); + + // Get the information of the Prepared TXs so it could replay the TXs Map, List>> queuesToSendTo = new HashMap<>(); for (TransactionOperation operation : allOperations) { @@ -387,6 +417,7 @@ public class ScaleDownHandler } } } + ClientProducer producer = session.createProducer(); for (Map.Entry, List>> entry : queuesToSendTo.entrySet()) { @@ -436,78 +467,6 @@ public class ScaleDownHandler } session.close(); } - - /** - * Loop through every *other* queue on this address to see if it also contains this message. - * Skip queues with filters that don't match as matching messages will never be in there. - * Also skip queues that we've already checked in the "big" loop. - */ - private void getQueuesWithMessage(PagingStore store, List queues, Map> queueIterators, List checkedQueues, Queue bigLoopQueue, List queuesWithMessage, MessageReference bigLoopRef, long messageId) throws Exception - { - for (Queue queue : queues) - { - if (!checkedQueues.contains(queue.getName()) && - ((queue.getFilter() == null && - bigLoopQueue.getFilter() == null) || - (queue.getFilter() != null && - queue.getFilter().equals(bigLoopQueue.getFilter())))) - { - // an optimization for paged messages, eliminates the need to (potentially) scan the whole queue - if (bigLoopRef.isPaged()) - { - PageSubscription subscription = store.getCursorProvider().getSubscription(queue.getID()); - if (subscription.contains((PagedReference) bigLoopRef)) - { - queuesWithMessage.add(queue); - } - } - else - { - LinkedListIterator queueIterator = queueIterators.get(queue.getName()); - boolean first = true; - long initialMessageID = 0; - while (queueIterator.hasNext()) - { - Message m = queueIterator.next().getMessage(); - if (first) - { - initialMessageID = m.getMessageID(); - first = false; - } - if (m.getMessageID() == messageId) - { - queuesWithMessage.add(queue); - break; - } - } - - /** - * if we've reached the end then reset the iterator and go through again until we - * get back to the place where we started - */ - if (!queueIterator.hasNext()) - { - queueIterator = queue.totalIterator(); - queueIterators.put(queue.getName(), queueIterator); - while (queueIterator.hasNext()) - { - Message m = queueIterator.next().getMessage(); - if (m.getMessageID() == initialMessageID) - { - break; - } - else if (m.getMessageID() == messageId) - { - queuesWithMessage.add(queue); - break; - } - } - } - } - } - } - } - /** * Get the ID of the queues involved so the message can be routed properly. This is done because we cannot * send directly to a queue, we have to send to an address instead but not all the queues related to the @@ -557,11 +516,159 @@ public class ScaleDownHandler if (queue1 == queue2) return EQUAL; - if (queue1.getMessageCount() == queue2.getMessageCount()) return EQUAL; + if (queue1.getMessageCount() == queue2.getMessageCount()) + { + // if it's the same count we will use the ID as a tie breaker: + + long tieBreak = queue2.getID() - queue1.getID(); + + if (tieBreak > 0) return AFTER; + else if (tieBreak < 0) return BEFORE; + else return EQUAL; // EQUAL here shouldn't really happen... but lets do the check anyways + + } if (queue1.getMessageCount() > queue2.getMessageCount()) return BEFORE; if (queue1.getMessageCount() < queue2.getMessageCount()) return AFTER; return result; } } + + + private void ackMessageOnQueue(Transaction tx, Queue queue, MessageReference messageRef) throws Exception + { + queue.acknowledge(tx, messageRef); + } + + /** + * this class will control iterations while + * looking over for messages relations + */ + private class QueuesXRefInnerManager + { + private final Queue queue; + private LinkedListIterator memoryIterator; + private MessageReference lastRef = null; + private final PagingStore store; + + /** + * ClientSession used for looking up and creating queues + */ + private final ClientSession clientSession; + + private long targetQueueID = -1; + + + QueuesXRefInnerManager(final ClientSession clientSession, final Queue queue, final PagingStore store) + { + this.queue = queue; + this.store = store; + this.clientSession = clientSession; + } + + public Queue getQueue() + { + return queue; + } + + public long getQueueID() throws Exception + { + + if (targetQueueID < 0) + { + targetQueueID = createQueueIfNecessaryAndGetID(clientSession, queue, queue.getAddress()); + } + return targetQueueID; + } + + public void close() + { + if (memoryIterator != null) + { + memoryIterator.close(); + } + } + + public boolean lookup(MessageReference reference) throws Exception + { + + if (reference.isPaged()) + { + PageSubscription subscription = store.getCursorProvider().getSubscription(queue.getID()); + if (subscription.contains((PagedReference) reference)) + { + return true; + } + } + else + { + + if (lastRef != null && lastRef.getMessage().equals(reference.getMessage())) + { + lastRef = null; + memoryIterator.remove(); + return true; + } + + int numberOfScans = 2; + + if (memoryIterator == null) + { + // If we have a brand new iterator, and we can't find something + numberOfScans = 1; + } + + MessageReference initialRef = null; + for (int i = 0; i < numberOfScans; i++) + { + ActiveMQServerLogger.LOGGER.debug("iterating on queue " + queue + " while looking for reference " + reference); + memoryIterator = queue.iterator(); + + while (memoryIterator.hasNext()) + { + lastRef = memoryIterator.next(); + + ActiveMQServerLogger.LOGGER.debug("Iterating on message " + lastRef); + + if (lastRef.getMessage().equals(reference.getMessage())) + { + memoryIterator.remove(); + lastRef = null; + return true; + } + + if (initialRef == null) + { + lastRef = initialRef; + } + else + { + if (initialRef.equals(lastRef)) + { + if (!memoryIterator.hasNext()) + { + // if by coincidence we are at the end of the iterator, we just reset the iterator + lastRef = null; + memoryIterator.close(); + memoryIterator = null; + } + return false; + } + } + } + } + + } + + // if we reached two iterations without finding anything.. we just go away by cleaning everything up + lastRef = null; + memoryIterator.close(); + memoryIterator = null; + + return false; + } + + } + + } diff --git a/activemq-server/src/test/java/org/apache/activemq/core/server/impl/ScheduledDeliveryHandlerTest.java b/activemq-server/src/test/java/org/apache/activemq/core/server/impl/ScheduledDeliveryHandlerTest.java index b41b332a6b..abb6e86d64 100644 --- a/activemq-server/src/test/java/org/apache/activemq/core/server/impl/ScheduledDeliveryHandlerTest.java +++ b/activemq-server/src/test/java/org/apache/activemq/core/server/impl/ScheduledDeliveryHandlerTest.java @@ -1483,9 +1483,9 @@ public class ScheduledDeliveryHandlerTest extends Assert } @Override - public List cancelScheduledMessages() + public void deliverScheduledMessages() { - return null; + } @Override diff --git a/activemq-server/src/test/java/org/apache/activemq/tests/util/ServiceTestBase.java b/activemq-server/src/test/java/org/apache/activemq/tests/util/ServiceTestBase.java index ad621260aa..dd6b9453c0 100644 --- a/activemq-server/src/test/java/org/apache/activemq/tests/util/ServiceTestBase.java +++ b/activemq-server/src/test/java/org/apache/activemq/tests/util/ServiceTestBase.java @@ -972,7 +972,7 @@ public abstract class ServiceTestBase extends UnitTestCase protected HashMap countJournal(Configuration config) throws Exception { final HashMap recordsType = new HashMap(); - SequentialFileFactory messagesFF = new NIOSequentialFileFactory(getJournalDir(), null); + SequentialFileFactory messagesFF = new NIOSequentialFileFactory(config.getJournalDirectory(), null); JournalImpl messagesJournal = new JournalImpl(config.getJournalFileSize(), config.getJournalMinFiles(), diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/HangConsumerTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/HangConsumerTest.java index 42c2b59131..b4a79774de 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/HangConsumerTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/HangConsumerTest.java @@ -16,7 +16,6 @@ */ package org.apache.activemq.tests.integration.client; import org.apache.activemq.api.core.ActiveMQException; -import org.apache.activemq.core.server.MessageReference; import org.apache.activemq.core.server.ServerConsumer; import org.junit.Before; import org.junit.After; @@ -24,7 +23,6 @@ import org.junit.Test; import java.lang.management.ManagementFactory; import java.util.LinkedList; -import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; @@ -274,9 +272,8 @@ public class HangConsumerTest extends ServiceTestBase } @Override - public List cancelScheduledMessages() + public void deliverScheduledMessages() { - return null; } } diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/InterruptedLargeMessageTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/InterruptedLargeMessageTest.java index 25ca4eee63..9db1ff1867 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/InterruptedLargeMessageTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/InterruptedLargeMessageTest.java @@ -20,7 +20,6 @@ import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import java.io.IOException; import java.util.HashMap; -import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; @@ -534,9 +533,8 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase } @Override - public List cancelScheduledMessages() + public void deliverScheduledMessages() { - return null; } } diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/cluster/distribution/ClusterTestBase.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/cluster/distribution/ClusterTestBase.java index f510091ac3..9c4d1185e8 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/cluster/distribution/ClusterTestBase.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/cluster/distribution/ClusterTestBase.java @@ -62,6 +62,7 @@ import org.apache.activemq.core.postoffice.Bindings; import org.apache.activemq.core.postoffice.PostOffice; import org.apache.activemq.core.postoffice.QueueBinding; import org.apache.activemq.core.postoffice.impl.LocalQueueBinding; +import org.apache.activemq.core.protocol.core.impl.CoreProtocolManagerFactory; import org.apache.activemq.core.remoting.impl.netty.TransportConstants; import org.apache.activemq.core.server.ActiveMQServer; import org.apache.activemq.core.server.ActiveMQServers; @@ -1681,7 +1682,8 @@ public abstract class ClusterTestBase extends ServiceTestBase .setThreadPoolMaxSize(10) .clearAcceptorConfigurations() .addAcceptorConfiguration(createTransportConfiguration(netty, true, generateParams(node, netty))) - .setHAPolicyConfiguration(haPolicyConfiguration); + .setHAPolicyConfiguration(haPolicyConfiguration) + .setResolveProtocols(false); ActiveMQServer server; @@ -1708,6 +1710,8 @@ public abstract class ClusterTestBase extends ServiceTestBase } } + server.addProtocolManagerFactory(new CoreProtocolManagerFactory()); + server.setIdentity(this.getClass().getSimpleName() + "/Live(" + node + ")"); servers[node] = server; } diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/server/ScaleDownDirectTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/server/ScaleDownDirectTest.java new file mode 100644 index 0000000000..0ae56db919 --- /dev/null +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/server/ScaleDownDirectTest.java @@ -0,0 +1,319 @@ +/** + * 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.tests.integration.server; + +import java.util.Arrays; +import java.util.Collection; + +import org.apache.activemq.api.core.Message; +import org.apache.activemq.api.core.SimpleString; +import org.apache.activemq.api.core.client.ActiveMQClient; +import org.apache.activemq.api.core.client.ClientConsumer; +import org.apache.activemq.api.core.client.ClientMessage; +import org.apache.activemq.api.core.client.ClientProducer; +import org.apache.activemq.api.core.client.ClientSession; +import org.apache.activemq.api.core.client.ClientSessionFactory; +import org.apache.activemq.core.postoffice.impl.LocalQueueBinding; +import org.apache.activemq.core.server.impl.ScaleDownHandler; +import org.apache.activemq.core.settings.impl.AddressSettings; +import org.apache.activemq.tests.integration.cluster.distribution.ClusterTestBase; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +/** + * On this test we will run ScaleDown directly as an unit-test in several cases, + * simulating what would happen during a real scale down. + * + * @author clebertsuconic + */ +@RunWith(value = Parameterized.class) +public class ScaleDownDirectTest extends ClusterTestBase +{ + + + @Parameterized.Parameters(name = "isNetty={0}") + public static Collection getParameters() + { + return Arrays.asList(new Object[][]{ + {false}, {true} + }); + } + + + private final boolean isNetty; + + public ScaleDownDirectTest(boolean isNetty) + { + this.isNetty = isNetty; + } + + @Override + @Before + public void setUp() throws Exception + { + super.setUp(); + setupLiveServer(0, isFileStorage(), isNetty, true); + setupLiveServer(1, isFileStorage(), isNetty, true); + startServers(0, 1); + setupSessionFactory(0, isNetty); + setupSessionFactory(1, isNetty); + + } + + @Override + @After + public void tearDown() throws Exception + { + super.tearDown(); + } + + @Test + public void testSendMixedSmallMessages() throws Exception + { + internalTest(100, 100); + } + + @Test + public void testSendMixedLargelMessages() throws Exception + { + internalTest(2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, 100); + } + + protected void internalTest(int bufferSize, int numberOfMessages) throws Exception + { + ClientSessionFactory sf = sfs[0]; + + ClientSession session = sf.createSession(true, true); + + session.createQueue("ad1", "queue1", true); + + ClientProducer producer = session.createProducer("ad1"); + + byte[] buffer = new byte[bufferSize]; + for (int i = 0; i < bufferSize; i++) + { + buffer[i] = getSamplebyte(i); + } + + for (int i = 0; i < numberOfMessages; i++) + { + ClientMessage message = session.createMessage(true); + message.putIntProperty("i", i); + message.getBodyBuffer().writeBytes(buffer); + producer.send(message); + } + + session.createQueue("ad1", "queue2", true); + + for (int i = numberOfMessages; i < (numberOfMessages * 2); i++) + { + ClientMessage message = session.createMessage(true); + message.putIntProperty("i", i); + message.getBodyBuffer().writeBytes(buffer); + producer.send(message); + } + + assertEquals(numberOfMessages * 2, performScaledown()); + + sfs[0].close(); + + session.close(); + + stopServers(0); + + session = sfs[1].createSession(true, true); + + ClientConsumer consumer1 = session.createConsumer("queue1"); + session.start(); + + + for (int i = 0; i < numberOfMessages * 2; i++) + { + ClientMessage message = consumer1.receive(5000); + assertNotNull(message); + assertEquals(i, message.getIntProperty("i").intValue()); +// message.acknowledge(); + + checkBody(message, bufferSize); + + } + + ClientMessage messageCheckNull = consumer1.receiveImmediate(); + + assertNull(messageCheckNull); + + ClientConsumer consumer2 = session.createConsumer("queue2"); + for (int i = numberOfMessages; i < numberOfMessages * 2; i++) + { + ClientMessage message = consumer2.receive(5000); + assertNotNull(message); + assertEquals(i, message.getIntProperty("i").intValue()); +// message.acknowledge(); + checkBody(message, bufferSize); + } + + messageCheckNull = consumer2.receiveImmediate(); + + System.out.println("Received " + messageCheckNull); + + assertNull(messageCheckNull); + } + + + + @Test + public void testPaging() throws Exception + { + final int CHUNK_SIZE = 50; + int messageCount = 0; + final String addressName = "testAddress"; + final String queueName = "testQueue"; + + createQueue(0, addressName, queueName, null, true); + createQueue(1, addressName, queueName, null, true); + + ClientSessionFactory sf = sfs[0]; + ClientSession session = addClientSession(sf.createSession(false, false)); + ClientProducer producer = addClientProducer(session.createProducer(addressName)); + + AddressSettings defaultSetting = new AddressSettings(); + defaultSetting.setPageSizeBytes(10 * 1024); + defaultSetting.setMaxSizeBytes(20 * 1024); + servers[0].getAddressSettingsRepository().addMatch("#", defaultSetting); + + while (!servers[0].getPagingManager().getPageStore(new SimpleString(addressName)).isPaging()) + { + for (int i = 0; i < CHUNK_SIZE; i++) + { + Message message = session.createMessage(true); + message.getBodyBuffer().writeBytes(new byte[1024]); + // The only purpose of this count here is for eventually debug messages on print-data / print-pages +// message.putIntProperty("count", messageCount); + producer.send(message); + messageCount++; + } + session.commit(); + } + + assertEquals(messageCount, performScaledown()); + + servers[0].stop(); + + addConsumer(0, 1, queueName, null); + for (int i = 0; i < messageCount; i++) + { + ClientMessage message = consumers[0].getConsumer().receive(500); + Assert.assertNotNull(message); +// Assert.assertEquals(i, message.getIntProperty("count").intValue()); + } + + Assert.assertNull(consumers[0].getConsumer().receiveImmediate()); + removeConsumer(0); + } + + + + @Test + public void testBasicScaleDown() throws Exception + { + final int TEST_SIZE = 2; + final String addressName = "testAddress"; + final String queueName1 = "testQueue1"; + final String queueName2 = "testQueue2"; + + // create 2 queues on each node mapped to the same address + createQueue(0, addressName, queueName1, null, true); + createQueue(0, addressName, queueName2, null, true); + createQueue(1, addressName, queueName1, null, true); + createQueue(1, addressName, queueName2, null, true); + + // send messages to node 0 + send(0, addressName, TEST_SIZE, true, null); + + // consume a message from queue 2 + addConsumer(1, 0, queueName2, null, false); + ClientMessage clientMessage = consumers[1].getConsumer().receive(250); + Assert.assertNotNull(clientMessage); + clientMessage.acknowledge(); + consumers[1].getSession().commit(); + removeConsumer(1); + + // at this point on node 0 there should be 2 messages in testQueue1 and 1 message in testQueue2 + Assert.assertEquals(TEST_SIZE, getMessageCount(((LocalQueueBinding) servers[0].getPostOffice().getBinding(new SimpleString(queueName1))).getQueue())); + Assert.assertEquals(TEST_SIZE - 1, getMessageCount(((LocalQueueBinding) servers[0].getPostOffice().getBinding(new SimpleString(queueName2))).getQueue())); + + assertEquals(TEST_SIZE, performScaledown()); + // trigger scaleDown from node 0 to node 1 + servers[0].stop(); + + // get the 2 messages from queue 1 + addConsumer(0, 1, queueName1, null); + clientMessage = consumers[0].getConsumer().receive(250); + Assert.assertNotNull(clientMessage); + clientMessage.acknowledge(); + clientMessage = consumers[0].getConsumer().receive(250); + Assert.assertNotNull(clientMessage); + clientMessage.acknowledge(); + + // ensure there are no more messages on queue 1 + clientMessage = consumers[0].getConsumer().receive(250); + Assert.assertNull(clientMessage); + removeConsumer(0); + + // get the 1 message from queue 2 + addConsumer(0, 1, queueName2, null); + clientMessage = consumers[0].getConsumer().receive(250); + Assert.assertNotNull(clientMessage); + clientMessage.acknowledge(); + + // ensure there are no more messages on queue 1 + clientMessage = consumers[0].getConsumer().receive(250); + Assert.assertNull(clientMessage); + removeConsumer(0); + } + + private void checkBody(ClientMessage message, int bufferSize) + { + assertEquals(bufferSize, message.getBodySize()); + byte[] body = new byte[message.getBodySize()]; + message.getBodyBuffer().readBytes(body); + for (int bpos = 0; bpos < bufferSize; bpos++) + { + if (getSamplebyte(bpos) != body[bpos]) + { + fail("body comparison failure at " + message); + } + } + } + + private long performScaledown() throws Exception + { + ScaleDownHandler handler = new ScaleDownHandler(servers[0].getPagingManager(), servers[0].getPostOffice(), + servers[0].getNodeManager(), + servers[0].getClusterManager().getClusterController(), + servers[0].getStorageManager()); + + return handler.scaleDownMessages(sfs[1], servers[1].getNodeID()); + } + + +} diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/server/ScaleDownTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/server/ScaleDownTest.java index 72666c7d76..9119927812 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/server/ScaleDownTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/server/ScaleDownTest.java @@ -30,8 +30,6 @@ import org.apache.activemq.api.core.client.ClientSessionFactory; import org.apache.activemq.api.core.client.ActiveMQClient; import org.apache.activemq.core.config.ScaleDownConfiguration; import org.apache.activemq.core.config.ha.LiveOnlyPolicyConfiguration; -import org.apache.activemq.core.persistence.impl.journal.JournalStorageManager; -import org.apache.activemq.core.persistence.impl.journal.LargeServerMessageImpl; import org.apache.activemq.core.postoffice.Binding; import org.apache.activemq.core.postoffice.impl.LocalQueueBinding; import org.apache.activemq.core.settings.impl.AddressSettings; @@ -119,13 +117,13 @@ public class ScaleDownTest extends ClusterTestBase final String queueName2 = "testQueue2"; // create 2 queues on each node mapped to the same address - createQueue(0, addressName, queueName1, null, false); - createQueue(0, addressName, queueName2, null, false); - createQueue(1, addressName, queueName1, null, false); - createQueue(1, addressName, queueName2, null, false); + createQueue(0, addressName, queueName1, null, true); + createQueue(0, addressName, queueName2, null, true); + createQueue(1, addressName, queueName1, null, true); + createQueue(1, addressName, queueName2, null, true); // send messages to node 0 - send(0, addressName, TEST_SIZE, false, null); + send(0, addressName, TEST_SIZE, true, null); // consume a message from queue 2 addConsumer(1, 0, queueName2, null, false); @@ -375,32 +373,28 @@ public class ScaleDownTest extends ClusterTestBase final String addressName = "testAddress"; final String queueName = "testQueue"; - createQueue(0, addressName, queueName, null, false); - createQueue(1, addressName, queueName, null, false); + createQueue(0, addressName, queueName, null, true); + createQueue(1, addressName, queueName, null, true); ClientSessionFactory sf = sfs[0]; ClientSession session = addClientSession(sf.createSession(false, false)); ClientProducer producer = addClientProducer(session.createProducer(addressName)); - LargeServerMessageImpl fileMessage = new LargeServerMessageImpl((JournalStorageManager) servers[0].getStorageManager()); - fileMessage.setMessageID(1005); - fileMessage.setDurable(true); - - for (int i = 0; i < 2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE; i++) + byte[] buffer = new byte[2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE]; + for (int i = 0; i < buffer.length; i++) { - fileMessage.addBytes(new byte[]{UnitTestCase.getSamplebyte(i)}); + buffer[i] = getSamplebyte(i); } - fileMessage.putLongProperty(Message.HDR_LARGE_BODY_SIZE, 2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE); + for (int nmsg = 0; nmsg < 10; nmsg++) + { + ClientMessage message = session.createMessage(true); + message.getBodyBuffer().writeBytes(buffer); + producer.send(message); + session.commit(); + } - fileMessage.releaseResources(); - - producer.send(fileMessage); - - fileMessage.deleteFile(); - - session.commit(); servers[0].stop(); @@ -409,19 +403,23 @@ public class ScaleDownTest extends ClusterTestBase ClientConsumer consumer = addClientConsumer(session.createConsumer(queueName)); session.start(); - ClientMessage msg = consumer.receive(250); - - Assert.assertNotNull(msg); - - Assert.assertEquals(2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, msg.getBodySize()); - - for (int i = 0; i < 2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE; i++) + for (int nmsg = 0; nmsg < 10; nmsg++) { - Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg.getBodyBuffer().readByte()); - } + ClientMessage msg = consumer.receive(250); - msg.acknowledge(); - session.commit(); + Assert.assertNotNull(msg); + + Assert.assertEquals(2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, msg.getBodySize()); + + for (int i = 0; i < 2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE; i++) + { + byte byteRead = msg.getBodyBuffer().readByte(); + Assert.assertEquals(msg + " Is different", UnitTestCase.getSamplebyte(i), byteRead); + } + + msg.acknowledge(); + session.commit(); + } } @Test diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/postoffice/impl/FakeQueue.java b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/postoffice/impl/FakeQueue.java index e4c4efd4d7..b88ee6ea6e 100644 --- a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/postoffice/impl/FakeQueue.java +++ b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/postoffice/impl/FakeQueue.java @@ -362,9 +362,9 @@ public class FakeQueue implements Queue } @Override - public List cancelScheduledMessages() + public void deliverScheduledMessages() { - return null; + } @Override diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/fakes/FakePostOffice.java b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/fakes/FakePostOffice.java index cf431d4d57..70cdb7f04f 100644 --- a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/fakes/FakePostOffice.java +++ b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/fakes/FakePostOffice.java @@ -17,6 +17,7 @@ package org.apache.activemq.tests.unit.core.server.impl.fakes; import java.util.Map; +import java.util.Set; import org.apache.activemq.api.core.Pair; import org.apache.activemq.api.core.SimpleString; @@ -43,6 +44,12 @@ public class FakePostOffice implements PostOffice return false; } + @Override + public Set getAddresses() + { + return null; + } + @Override public void start() throws Exception { From e293d80f08de58e4ce2bafd9d63c1a4185e079a9 Mon Sep 17 00:00:00 2001 From: jbertram Date: Tue, 6 Jan 2015 13:34:38 -0600 Subject: [PATCH 5/8] ACTIVEMQ6-13 auto-create/auto-delete jms queues Implements a new feature for the broker whereby it may automatically create and delete JMS queues which are not explicitly defined through the management API or file-based configuration. A JMS queue is created in response to a sent message or connected consumer. The queue may subsequently be deleted when it no longer has any messages and consumers. Auto-creation and auto-deletion can both be turned on/off via address-setting. --- .../api/core/client/ClientSession.java | 12 + .../management/ActiveMQServerControl.java | 4 +- .../core/management/AddressSettingsInfo.java | 24 +- .../core/client/impl/AddressQueryImpl.java | 11 +- .../core/client/impl/QueueQueryImpl.java | 20 + .../core/impl/ActiveMQSessionContext.java | 16 +- .../core/protocol/core/impl/ChannelImpl.java | 4 + .../protocol/core/impl/PacketDecoder.java | 14 + .../core/protocol/core/impl/PacketImpl.java | 4 + .../SessionBindingQueryResponseMessage.java | 9 +- ...SessionBindingQueryResponseMessage_V2.java | 90 ++++ .../SessionQueueQueryResponseMessage.java | 21 +- .../SessionQueueQueryResponseMessage_V2.java | 130 ++++++ .../core/server/QueueQueryResult.java | 22 +- .../resources/activemq-version.properties | 2 +- .../jms/client/ActiveMQMessageProducer.java | 9 +- .../activemq/jms/client/ActiveMQSession.java | 37 +- .../impl/FileConfigurationParser.java | 12 + .../impl/ActiveMQServerControlImpl.java | 8 +- .../core/persistence/QueueBindingInfo.java | 2 + .../impl/journal/JournalStorageManager.java | 20 +- .../core/ServerSessionPacketHandler.java | 30 +- .../activemq/core/server/ActiveMQServer.java | 7 + .../core/server/ActiveMQServerLogger.java | 4 + .../core/server/AutoCreatedQueueManager.java | 29 ++ .../core/server/BindingQueryResult.java | 11 +- .../apache/activemq/core/server/Queue.java | 4 +- .../activemq/core/server/QueueFactory.java | 3 +- .../core/server/impl/ActiveMQServerImpl.java | 27 +- .../impl/AutoCreatedQueueManagerImpl.java | 93 +++++ .../core/server/impl/LastValueQueue.java | 2 + .../server/impl/PostOfficeJournalLoader.java | 9 +- .../core/server/impl/QueueFactoryImpl.java | 5 +- .../activemq/core/server/impl/QueueImpl.java | 17 +- .../core/server/impl/ServerSessionImpl.java | 30 +- .../core/settings/impl/AddressSettings.java | 70 +++- .../schema/activemq-configuration.xsd | 17 + .../config/impl/FileConfigurationTest.java | 4 + .../impl/ScheduledDeliveryHandlerTest.java | 9 +- .../core/settings/AddressSettingsTest.java | 3 +- .../ConfigurationTest-full-config.xml | 4 + docs/user-manual/en/queue-attributes.md | 12 + pom.xml | 2 +- .../concurrent/server/impl/QueueTest.java | 1 + .../client/AutoCreateJmsQueueTest.java | 187 +++++++++ .../client/AutoDeleteJmsQueueTest.java | 84 ++++ .../integration/client/HangConsumerTest.java | 8 +- .../client/InterruptedLargeMessageTest.java | 6 +- .../integration/client/PagingOrderTest.java | 8 +- .../jms/client/TopicCleanupTest.java | 2 +- .../jms/jms2client/NonExistentQueueTest.java | 2 +- .../management/ActiveMQServerControlTest.java | 22 +- .../ActiveMQServerControlUsingCoreTest.java | 8 +- .../persistence/ExportFormatTest.java | 60 +-- .../activemq/jms/tests/SessionTest.java | 9 + .../core/server/impl/QueueImplTest.java | 3 + .../unit/core/postoffice/impl/FakeQueue.java | 9 +- .../unit/core/server/impl/QueueImplTest.java | 389 ++++-------------- .../server/impl/fakes/FakeQueueFactory.java | 4 +- 59 files changed, 1228 insertions(+), 437 deletions(-) create mode 100644 activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionBindingQueryResponseMessage_V2.java create mode 100644 activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionQueueQueryResponseMessage_V2.java create mode 100644 activemq-server/src/main/java/org/apache/activemq/core/server/AutoCreatedQueueManager.java create mode 100644 activemq-server/src/main/java/org/apache/activemq/core/server/impl/AutoCreatedQueueManagerImpl.java create mode 100644 tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/AutoCreateJmsQueueTest.java create mode 100644 tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/AutoDeleteJmsQueueTest.java diff --git a/activemq-core-client/src/main/java/org/apache/activemq/api/core/client/ClientSession.java b/activemq-core-client/src/main/java/org/apache/activemq/api/core/client/ClientSession.java index 11c579157e..75116fc38a 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/api/core/client/ClientSession.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/api/core/client/ClientSession.java @@ -48,6 +48,12 @@ public interface ClientSession extends XAResource, AutoCloseable * Returns the names of the queues bound to the binding. */ List getQueueNames(); + + /** + * Returns true if auto-creation for this address is enabled and if the address queried is for a JMS + * queue, false else. + */ + boolean isAutoCreateJmsQueues(); } /** @@ -81,6 +87,12 @@ public interface ClientSession extends XAResource, AutoCloseable */ boolean isDurable(); + /** + * Returns true if auto-creation for this queue is enabled and if the queue queried is a JMS queue, + * false else. + */ + boolean isAutoCreateJmsQueues(); + /** * Returns the number of consumers attached to the queue. */ diff --git a/activemq-core-client/src/main/java/org/apache/activemq/api/core/management/ActiveMQServerControl.java b/activemq-core-client/src/main/java/org/apache/activemq/api/core/management/ActiveMQServerControl.java index f33b109d79..6c2b64e658 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/api/core/management/ActiveMQServerControl.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/api/core/management/ActiveMQServerControl.java @@ -565,7 +565,9 @@ public interface ActiveMQServerControl @Parameter(desc = "the policy to use when the address is full", name = "addressFullMessagePolicy") String addressFullMessagePolicy, @Parameter(desc = "when a consumer falls below this threshold in terms of messages consumed per second it will be considered 'slow'", name = "slowConsumerThreshold") long slowConsumerThreshold, @Parameter(desc = "how often (in seconds) to check for slow consumers", name = "slowConsumerCheckPeriod") long slowConsumerCheckPeriod, - @Parameter(desc = "the policy to use when a slow consumer is detected", name = "slowConsumerPolicy") String slowConsumerPolicy) throws Exception; + @Parameter(desc = "the policy to use when a slow consumer is detected", name = "slowConsumerPolicy") String slowConsumerPolicy, + @Parameter(desc = "allow queues to be created automatically", name = "autoCreateJmsQueues") boolean autoCreateJmsQueues, + @Parameter(desc = "allow auto-created queues to be deleted automatically", name = "autoDeleteJmsQueues") boolean autoDeleteJmsQueues) throws Exception; void removeAddressSettings(String addressMatch) throws Exception; diff --git a/activemq-core-client/src/main/java/org/apache/activemq/api/core/management/AddressSettingsInfo.java b/activemq-core-client/src/main/java/org/apache/activemq/api/core/management/AddressSettingsInfo.java index c60d46a6b3..bc7f82acee 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/api/core/management/AddressSettingsInfo.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/api/core/management/AddressSettingsInfo.java @@ -60,6 +60,10 @@ public final class AddressSettingsInfo private final String slowConsumerPolicy; + private final boolean autoCreateJmsQueues; + + private final boolean autoDeleteJmsQueues; + // Static -------------------------------------------------------- public static AddressSettingsInfo from(final String jsonString) throws Exception @@ -80,7 +84,9 @@ public final class AddressSettingsInfo object.getBoolean("sendToDLAOnNoRoute"), object.getLong("slowConsumerThreshold"), object.getLong("slowConsumerCheckPeriod"), - object.getString("slowConsumerPolicy")); + object.getString("slowConsumerPolicy"), + object.getBoolean("autoCreateJmsQueues"), + object.getBoolean("autoDeleteJmsQueues")); } // Constructors -------------------------------------------------- @@ -100,7 +106,9 @@ public final class AddressSettingsInfo boolean sendToDLAOnNoRoute, long slowConsumerThreshold, long slowConsumerCheckPeriod, - String slowConsumerPolicy) + String slowConsumerPolicy, + boolean autoCreateJmsQueues, + boolean autoDeleteJmsQueues) { this.addressFullMessagePolicy = addressFullMessagePolicy; this.maxSizeBytes = maxSizeBytes; @@ -118,6 +126,8 @@ public final class AddressSettingsInfo this.slowConsumerThreshold = slowConsumerThreshold; this.slowConsumerCheckPeriod = slowConsumerCheckPeriod; this.slowConsumerPolicy = slowConsumerPolicy; + this.autoCreateJmsQueues = autoCreateJmsQueues; + this.autoDeleteJmsQueues = autoDeleteJmsQueues; } // Public -------------------------------------------------------- @@ -206,5 +216,15 @@ public final class AddressSettingsInfo { return slowConsumerPolicy; } + + public boolean isAutoCreateJmsQueues() + { + return autoCreateJmsQueues; + } + + public boolean isAutoDeleteJmsQueues() + { + return autoDeleteJmsQueues; + } } diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/client/impl/AddressQueryImpl.java b/activemq-core-client/src/main/java/org/apache/activemq/core/client/impl/AddressQueryImpl.java index 53ed6c7e6b..6c7c8a3a05 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/core/client/impl/AddressQueryImpl.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/client/impl/AddressQueryImpl.java @@ -24,15 +24,17 @@ import org.apache.activemq.api.core.client.ClientSession; public class AddressQueryImpl implements ClientSession.AddressQuery, ClientSession.BindingQuery { - private final boolean exists; private final ArrayList queueNames; - public AddressQueryImpl(final boolean exists, final List queueNames) + private final boolean autoCreateJmsQueues; + + public AddressQueryImpl(final boolean exists, final List queueNames, final boolean autoCreateJmsQueues) { this.exists = exists; this.queueNames = new ArrayList(queueNames); + this.autoCreateJmsQueues = autoCreateJmsQueues; } public List getQueueNames() @@ -44,4 +46,9 @@ public class AddressQueryImpl implements ClientSession.AddressQuery, ClientSessi { return exists; } + + public boolean isAutoCreateJmsQueues() + { + return autoCreateJmsQueues; + } } diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/client/impl/QueueQueryImpl.java b/activemq-core-client/src/main/java/org/apache/activemq/core/client/impl/QueueQueryImpl.java index 5d948d81d7..a330bfb2f5 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/core/client/impl/QueueQueryImpl.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/client/impl/QueueQueryImpl.java @@ -38,6 +38,8 @@ public class QueueQueryImpl implements ClientSession.QueueQuery private final SimpleString name; + private final boolean autoCreateJmsQueues; + public QueueQueryImpl(final boolean durable, final boolean temporary, final int consumerCount, @@ -47,7 +49,19 @@ public class QueueQueryImpl implements ClientSession.QueueQuery final SimpleString name, final boolean exists) { + this(durable, temporary, consumerCount, messageCount, filterString, address, name, exists, false); + } + public QueueQueryImpl(final boolean durable, + final boolean temporary, + final int consumerCount, + final long messageCount, + final SimpleString filterString, + final SimpleString address, + final SimpleString name, + final boolean exists, + final boolean autoCreateJmsQueues) + { this.durable = durable; this.temporary = temporary; this.consumerCount = consumerCount; @@ -56,6 +70,7 @@ public class QueueQueryImpl implements ClientSession.QueueQuery this.address = address; this.name = name; this.exists = exists; + this.autoCreateJmsQueues = autoCreateJmsQueues; } public SimpleString getName() @@ -88,6 +103,11 @@ public class QueueQueryImpl implements ClientSession.QueueQuery return durable; } + public boolean isAutoCreateJmsQueues() + { + return autoCreateJmsQueues; + } + public boolean isTemporary() { return temporary; diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/ActiveMQSessionContext.java b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/ActiveMQSessionContext.java index 4519b76ef0..17632c4088 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/ActiveMQSessionContext.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/ActiveMQSessionContext.java @@ -60,7 +60,7 @@ import org.apache.activemq.core.protocol.core.impl.wireformat.RollbackMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionAcknowledgeMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionAddMetaDataMessageV2; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryMessage; -import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryResponseMessage; +import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryResponseMessage_V2; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionCloseMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionConsumerCloseMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionConsumerFlowCreditMessage; @@ -72,7 +72,7 @@ import org.apache.activemq.core.protocol.core.impl.wireformat.SessionIndividualA import org.apache.activemq.core.protocol.core.impl.wireformat.SessionProducerCreditsFailMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionProducerCreditsMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryMessage; -import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryResponseMessage; +import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryResponseMessage_V2; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionReceiveContinuationMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionReceiveLargeMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionReceiveMessage; @@ -231,13 +231,11 @@ public class ActiveMQSessionContext extends SessionContext public ClientSession.QueueQuery queueQuery(final SimpleString queueName) throws ActiveMQException { SessionQueueQueryMessage request = new SessionQueueQueryMessage(queueName); - SessionQueueQueryResponseMessage response = (SessionQueueQueryResponseMessage) sessionChannel.sendBlocking(request, PacketImpl.SESS_QUEUEQUERY_RESP); + SessionQueueQueryResponseMessage_V2 response = (SessionQueueQueryResponseMessage_V2) sessionChannel.sendBlocking(request, PacketImpl.SESS_QUEUEQUERY_RESP_V2); return response.toQueueQuery(); - } - public ClientConsumerInternal createConsumer(SimpleString queueName, SimpleString filterString, int windowSize, int maxRate, int ackBatchSize, boolean browseOnly, Executor executor, Executor flowControlExecutor) throws ActiveMQException @@ -252,7 +250,7 @@ public class ActiveMQSessionContext extends SessionContext browseOnly, true); - SessionQueueQueryResponseMessage queueInfo = (SessionQueueQueryResponseMessage) sessionChannel.sendBlocking(request, PacketImpl.SESS_QUEUEQUERY_RESP); + SessionQueueQueryResponseMessage_V2 queueInfo = (SessionQueueQueryResponseMessage_V2) sessionChannel.sendBlocking(request, PacketImpl.SESS_QUEUEQUERY_RESP_V2); // The actual windows size that gets used is determined by the user since // could be overridden on the queue settings @@ -283,10 +281,10 @@ public class ActiveMQSessionContext extends SessionContext public ClientSession.AddressQuery addressQuery(final SimpleString address) throws ActiveMQException { - SessionBindingQueryResponseMessage response = - (SessionBindingQueryResponseMessage) sessionChannel.sendBlocking(new SessionBindingQueryMessage(address), PacketImpl.SESS_BINDINGQUERY_RESP); + SessionBindingQueryResponseMessage_V2 response = + (SessionBindingQueryResponseMessage_V2) sessionChannel.sendBlocking(new SessionBindingQueryMessage(address), PacketImpl.SESS_BINDINGQUERY_RESP_V2); - return new AddressQueryImpl(response.isExists(), response.getQueueNames()); + return new AddressQueryImpl(response.isExists(), response.getQueueNames(), response.isAutoCreateJmsQueues()); } diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/ChannelImpl.java b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/ChannelImpl.java index 71e7ced21f..579ff23674 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/ChannelImpl.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/ChannelImpl.java @@ -161,6 +161,10 @@ public final class ChannelImpl implements Channel return version >= 125; case PacketImpl.DISCONNECT_V2: return version >= 125; + case PacketImpl.SESS_QUEUEQUERY_RESP_V2: + return version >= 126; + case PacketImpl.SESS_BINDINGQUERY_RESP_V2: + return version >= 126; default: return true; } diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/PacketDecoder.java b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/PacketDecoder.java index 44745730b9..cbb94c3004 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/PacketDecoder.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/PacketDecoder.java @@ -39,6 +39,7 @@ import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_ADD_ME import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_ADD_METADATA2; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_BINDINGQUERY; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_BINDINGQUERY_RESP; +import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_BINDINGQUERY_RESP_V2; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_CLOSE; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_COMMIT; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_CONSUMER_CLOSE; @@ -52,6 +53,7 @@ import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_PRODUC import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_PRODUCER_REQUEST_CREDITS; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_QUEUEQUERY; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_QUEUEQUERY_RESP; +import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_QUEUEQUERY_RESP_V2; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_RECEIVE_CONTINUATION; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_ROLLBACK; import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_SEND_CONTINUATION; @@ -107,6 +109,7 @@ import org.apache.activemq.core.protocol.core.impl.wireformat.SessionAddMetaData import org.apache.activemq.core.protocol.core.impl.wireformat.SessionAddMetaDataMessageV2; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryResponseMessage; +import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryResponseMessage_V2; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionCloseMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionCommitMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionConsumerCloseMessage; @@ -120,6 +123,7 @@ import org.apache.activemq.core.protocol.core.impl.wireformat.SessionProducerCre import org.apache.activemq.core.protocol.core.impl.wireformat.SessionProducerCreditsMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryResponseMessage; +import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryResponseMessage_V2; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionReceiveContinuationMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionRequestProducerCreditsMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionSendContinuationMessage; @@ -251,6 +255,11 @@ public abstract class PacketDecoder implements Serializable packet = new SessionQueueQueryResponseMessage(); break; } + case SESS_QUEUEQUERY_RESP_V2: + { + packet = new SessionQueueQueryResponseMessage_V2(); + break; + } case CREATE_QUEUE: { packet = new CreateQueueMessage(); @@ -276,6 +285,11 @@ public abstract class PacketDecoder implements Serializable packet = new SessionBindingQueryResponseMessage(); break; } + case SESS_BINDINGQUERY_RESP_V2: + { + packet = new SessionBindingQueryResponseMessage_V2(); + break; + } case SESS_XA_START: { packet = new SessionXAStartMessage(); diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/PacketImpl.java b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/PacketImpl.java index 71e6415c5a..e2bdc28a56 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/PacketImpl.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/PacketImpl.java @@ -246,6 +246,10 @@ public class PacketImpl implements Packet public static final byte SCALEDOWN_ANNOUNCEMENT = -6; + public static final byte SESS_QUEUEQUERY_RESP_V2 = -7; + + public static final byte SESS_BINDINGQUERY_RESP_V2 = -8; + // Static -------------------------------------------------------- public PacketImpl(final byte type) diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionBindingQueryResponseMessage.java b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionBindingQueryResponseMessage.java index 2f56abd236..dc56506d64 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionBindingQueryResponseMessage.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionBindingQueryResponseMessage.java @@ -32,9 +32,9 @@ import org.apache.activemq.core.protocol.core.impl.PacketImpl; */ public class SessionBindingQueryResponseMessage extends PacketImpl { - private boolean exists; + protected boolean exists; - private List queueNames; + protected List queueNames; public SessionBindingQueryResponseMessage(final boolean exists, final List queueNames) { @@ -50,6 +50,11 @@ public class SessionBindingQueryResponseMessage extends PacketImpl super(SESS_BINDINGQUERY_RESP); } + public SessionBindingQueryResponseMessage(byte v2) + { + super(v2); + } + @Override public boolean isResponse() { diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionBindingQueryResponseMessage_V2.java b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionBindingQueryResponseMessage_V2.java new file mode 100644 index 0000000000..2a9e440770 --- /dev/null +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionBindingQueryResponseMessage_V2.java @@ -0,0 +1,90 @@ +/** + * 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.core.protocol.core.impl.wireformat; + +import java.util.List; + +import org.apache.activemq.api.core.ActiveMQBuffer; +import org.apache.activemq.api.core.SimpleString; + +/** + * @author Justin Bertram + * + */ +public class SessionBindingQueryResponseMessage_V2 extends SessionBindingQueryResponseMessage +{ + private boolean autoCreateJmsQueues; + + public SessionBindingQueryResponseMessage_V2(final boolean exists, final List queueNames, final boolean autoCreateJmsQueues) + { + super(SESS_BINDINGQUERY_RESP_V2); + + this.exists = exists; + + this.queueNames = queueNames; + + this.autoCreateJmsQueues = autoCreateJmsQueues; + } + + public SessionBindingQueryResponseMessage_V2() + { + super(SESS_BINDINGQUERY_RESP_V2); + } + + public boolean isAutoCreateJmsQueues() + { + return autoCreateJmsQueues; + } + + @Override + public void encodeRest(final ActiveMQBuffer buffer) + { + super.encodeRest(buffer); + buffer.writeBoolean(autoCreateJmsQueues); + } + + @Override + public void decodeRest(final ActiveMQBuffer buffer) + { + super.decodeRest(buffer); + autoCreateJmsQueues = buffer.readBoolean(); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + (autoCreateJmsQueues ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (!(obj instanceof SessionBindingQueryResponseMessage_V2)) + return false; + SessionBindingQueryResponseMessage_V2 other = (SessionBindingQueryResponseMessage_V2)obj; + if (autoCreateJmsQueues != other.autoCreateJmsQueues) + return false; + return true; + } +} diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionQueueQueryResponseMessage.java b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionQueueQueryResponseMessage.java index 43ae4df566..d7d031a14f 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionQueueQueryResponseMessage.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionQueueQueryResponseMessage.java @@ -32,21 +32,21 @@ import org.apache.activemq.core.server.QueueQueryResult; */ public class SessionQueueQueryResponseMessage extends PacketImpl { - private SimpleString name; + protected SimpleString name; - private boolean exists; + protected boolean exists; - private boolean durable; + protected boolean durable; - private int consumerCount; + protected int consumerCount; - private long messageCount; + protected long messageCount; - private SimpleString filterString; + protected SimpleString filterString; - private SimpleString address; + protected SimpleString address; - private boolean temporary; + protected boolean temporary; public SessionQueueQueryResponseMessage(final QueueQueryResult result) { @@ -59,6 +59,11 @@ public class SessionQueueQueryResponseMessage extends PacketImpl this(null, null, false, false, null, 0, 0, false); } + public SessionQueueQueryResponseMessage(byte v2) + { + super(v2); + } + private SessionQueueQueryResponseMessage(final SimpleString name, final SimpleString address, final boolean durable, diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionQueueQueryResponseMessage_V2.java b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionQueueQueryResponseMessage_V2.java new file mode 100644 index 0000000000..4c6b47439c --- /dev/null +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/protocol/core/impl/wireformat/SessionQueueQueryResponseMessage_V2.java @@ -0,0 +1,130 @@ +/** + * 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.core.protocol.core.impl.wireformat; + +import org.apache.activemq.api.core.ActiveMQBuffer; +import org.apache.activemq.api.core.SimpleString; +import org.apache.activemq.api.core.client.ClientSession; +import org.apache.activemq.core.client.impl.QueueQueryImpl; +import org.apache.activemq.core.server.QueueQueryResult; + +/** + * @author Justin Bertram + * + */ +public class SessionQueueQueryResponseMessage_V2 extends SessionQueueQueryResponseMessage +{ + private boolean autoCreationEnabled; + + public SessionQueueQueryResponseMessage_V2(final QueueQueryResult result) + { + this(result.getName(), result.getAddress(), result.isDurable(), result.isTemporary(), + result.getFilterString(), result.getConsumerCount(), result.getMessageCount(), result.isExists(), result.isAutoCreateJmsQueues()); + } + + public SessionQueueQueryResponseMessage_V2() + { + this(null, null, false, false, null, 0, 0, false, false); + } + + private SessionQueueQueryResponseMessage_V2(final SimpleString name, + final SimpleString address, + final boolean durable, + final boolean temporary, + final SimpleString filterString, + final int consumerCount, + final long messageCount, + final boolean exists, + final boolean autoCreationEnabled) + { + super(SESS_QUEUEQUERY_RESP_V2); + + this.durable = durable; + + this.temporary = temporary; + + this.consumerCount = consumerCount; + + this.messageCount = messageCount; + + this.filterString = filterString; + + this.address = address; + + this.name = name; + + this.exists = exists; + + this.autoCreationEnabled = autoCreationEnabled; + } + + public boolean isAutoCreationEnabled() + { + return autoCreationEnabled; + } + + @Override + public void encodeRest(final ActiveMQBuffer buffer) + { + super.encodeRest(buffer); + buffer.writeBoolean(autoCreationEnabled); + } + + @Override + public void decodeRest(final ActiveMQBuffer buffer) + { + super.decodeRest(buffer); + autoCreationEnabled = buffer.readBoolean(); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + (autoCreationEnabled ? 1231 : 1237); + return result; + } + + public ClientSession.QueueQuery toQueueQuery() + { + return new QueueQueryImpl(isDurable(), + isTemporary(), + getConsumerCount(), + getMessageCount(), + getFilterString(), + getAddress(), + getName(), + isExists(), + isAutoCreationEnabled()); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (!(obj instanceof SessionQueueQueryResponseMessage_V2)) + return false; + SessionQueueQueryResponseMessage_V2 other = (SessionQueueQueryResponseMessage_V2)obj; + if (autoCreationEnabled != other.autoCreationEnabled) + return false; + return true; + } +} diff --git a/activemq-core-client/src/main/java/org/apache/activemq/core/server/QueueQueryResult.java b/activemq-core-client/src/main/java/org/apache/activemq/core/server/QueueQueryResult.java index 9650fff490..3b7cbf6f1c 100644 --- a/activemq-core-client/src/main/java/org/apache/activemq/core/server/QueueQueryResult.java +++ b/activemq-core-client/src/main/java/org/apache/activemq/core/server/QueueQueryResult.java @@ -43,29 +43,28 @@ public class QueueQueryResult private boolean temporary; + private boolean autoCreateJmsQueues; + public QueueQueryResult(final SimpleString name, final SimpleString address, final boolean durable, final boolean temporary, final SimpleString filterString, final int consumerCount, - final long messageCount) + final long messageCount, + final boolean autoCreateJmsQueues) { - this(name, address, durable, temporary, filterString, consumerCount, messageCount, true); + this(name, address, durable, temporary, filterString, consumerCount, messageCount, autoCreateJmsQueues, true); } - public QueueQueryResult() - { - this(null, null, false, false, null, 0, 0, false); - } - - private QueueQueryResult(final SimpleString name, + public QueueQueryResult(final SimpleString name, final SimpleString address, final boolean durable, final boolean temporary, final SimpleString filterString, final int consumerCount, final long messageCount, + final boolean autoCreateJmsQueues, final boolean exists) { this.durable = durable; @@ -82,6 +81,8 @@ public class QueueQueryResult this.name = name; + this.autoCreateJmsQueues = autoCreateJmsQueues; + this.exists = exists; } @@ -125,4 +126,9 @@ public class QueueQueryResult return temporary; } + public boolean isAutoCreateJmsQueues() + { + return autoCreateJmsQueues; + } + } diff --git a/activemq-core-client/src/main/resources/activemq-version.properties b/activemq-core-client/src/main/resources/activemq-version.properties index f09128221d..8dc05e58a4 100644 --- a/activemq-core-client/src/main/resources/activemq-version.properties +++ b/activemq-core-client/src/main/resources/activemq-version.properties @@ -21,4 +21,4 @@ activemq.version.microVersion=${activemq.version.microVersion} activemq.version.incrementingVersion=${activemq.version.incrementingVersion} activemq.version.versionSuffix=${activemq.version.versionSuffix} activemq.version.versionTag=${activemq.version.versionTag} -activemq.version.compatibleVersionList=121,122,123,124,125 +activemq.version.compatibleVersionList=121,122,123,124,125,126 diff --git a/activemq-jms-client/src/main/java/org/apache/activemq/jms/client/ActiveMQMessageProducer.java b/activemq-jms-client/src/main/java/org/apache/activemq/jms/client/ActiveMQMessageProducer.java index 167d601a97..772b83615d 100644 --- a/activemq-jms-client/src/main/java/org/apache/activemq/jms/client/ActiveMQMessageProducer.java +++ b/activemq-jms-client/src/main/java/org/apache/activemq/jms/client/ActiveMQMessageProducer.java @@ -415,7 +415,14 @@ public class ActiveMQMessageProducer implements MessageProducer, QueueSender, To ClientSession.AddressQuery query = clientSession.addressQuery(address); if (!query.isExists()) { - throw new InvalidDestinationException("Destination " + address + " does not exist"); + if (query.isAutoCreateJmsQueues()) + { + clientSession.createQueue(address, address, true); + } + else + { + throw new InvalidDestinationException("Destination " + address + " does not exist"); + } } else { diff --git a/activemq-jms-client/src/main/java/org/apache/activemq/jms/client/ActiveMQSession.java b/activemq-jms-client/src/main/java/org/apache/activemq/jms/client/ActiveMQSession.java index bb79174a47..7725ba81d4 100644 --- a/activemq-jms-client/src/main/java/org/apache/activemq/jms/client/ActiveMQSession.java +++ b/activemq-jms-client/src/main/java/org/apache/activemq/jms/client/ActiveMQSession.java @@ -326,7 +326,14 @@ public class ActiveMQSession implements QueueSession, TopicSession if (!response.isExists()) { - throw new InvalidDestinationException("Destination " + jbd.getName() + " does not exist"); + if (response.isAutoCreateJmsQueues()) + { + session.createQueue(jbd.getSimpleAddress(), jbd.getSimpleAddress(), true); + } + else + { + throw new InvalidDestinationException("Destination " + jbd.getName() + " does not exist"); + } } connection.addKnownDestination(jbd.getSimpleAddress()); @@ -730,7 +737,14 @@ public class ActiveMQSession implements QueueSession, TopicSession if (!response.isExists()) { - throw new InvalidDestinationException("Queue " + dest.getName() + " does not exist"); + if (response.isAutoCreateJmsQueues()) + { + session.createQueue(dest.getSimpleAddress(), dest.getSimpleAddress(), true); + } + else + { + throw new InvalidDestinationException("Destination " + dest.getName() + " does not exist"); + } } connection.addKnownDestination(dest.getSimpleAddress()); @@ -902,10 +916,17 @@ public class ActiveMQSession implements QueueSession, TopicSession try { - AddressQuery message = session.addressQuery(new SimpleString(jbq.getAddress())); - if (!message.isExists()) + AddressQuery response = session.addressQuery(new SimpleString(jbq.getAddress())); + if (!response.isExists()) { - throw new InvalidDestinationException(jbq.getAddress() + " does not exist"); + if (response.isAutoCreateJmsQueues()) + { + session.createQueue(jbq.getSimpleAddress(), jbq.getSimpleAddress(), true); + } + else + { + throw new InvalidDestinationException("Destination " + jbq.getName() + " does not exist"); + } } } catch (ActiveMQException e) @@ -1239,13 +1260,13 @@ public class ActiveMQSession implements QueueSession, TopicSession QueueQuery response = session.queueQuery(queue.getSimpleAddress()); - if (response.isExists()) + if (!response.isExists() && !response.isAutoCreateJmsQueues()) { - return queue; + return null; } else { - return null; + return queue; } } diff --git a/activemq-server/src/main/java/org/apache/activemq/core/deployers/impl/FileConfigurationParser.java b/activemq-server/src/main/java/org/apache/activemq/core/deployers/impl/FileConfigurationParser.java index be2b2de1a1..f396da3c3d 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/deployers/impl/FileConfigurationParser.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/deployers/impl/FileConfigurationParser.java @@ -152,6 +152,10 @@ public final class FileConfigurationParser extends XMLConfigurationUtil private static final String SLOW_CONSUMER_POLICY_NODE_NAME = "slow-consumer-policy"; + private static final String AUTO_CREATE_JMS_QUEUES = "auto-create-jms-queues"; + + private static final String AUTO_DELETE_JMS_QUEUES = "auto-delete-jms-queues"; + // Attributes ---------------------------------------------------- private boolean validateAIO = false; @@ -1139,6 +1143,14 @@ public final class FileConfigurationParser extends XMLConfigurationUtil SlowConsumerPolicy policy = Enum.valueOf(SlowConsumerPolicy.class, value); addressSettings.setSlowConsumerPolicy(policy); } + else if (AUTO_CREATE_JMS_QUEUES.equalsIgnoreCase(name)) + { + addressSettings.setAutoCreateJmsQueues(XMLUtil.parseBoolean(child)); + } + else if (AUTO_DELETE_JMS_QUEUES.equalsIgnoreCase(name)) + { + addressSettings.setAutoDeleteJmsQueues(XMLUtil.parseBoolean(child)); + } } return setting; } diff --git a/activemq-server/src/main/java/org/apache/activemq/core/management/impl/ActiveMQServerControlImpl.java b/activemq-server/src/main/java/org/apache/activemq/core/management/impl/ActiveMQServerControlImpl.java index 16f9fa00bb..b899f092bc 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/management/impl/ActiveMQServerControlImpl.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/management/impl/ActiveMQServerControlImpl.java @@ -1635,6 +1635,8 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active policy = addressSettings.getSlowConsumerPolicy() == SlowConsumerPolicy.NOTIFY ? "NOTIFY" : "KILL"; settings.put("slowConsumerPolicy", policy); + settings.put("autoCreateJmsQueues", addressSettings.isAutoCreateJmsQueues()); + settings.put("autoDeleteJmsQueues", addressSettings.isAutoDeleteJmsQueues()); JSONObject jsonObject = new JSONObject(settings); return jsonObject.toString(); @@ -1658,7 +1660,9 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active final String addressFullMessagePolicy, final long slowConsumerThreshold, final long slowConsumerCheckPeriod, - final String slowConsumerPolicy) throws Exception + final String slowConsumerPolicy, + final boolean autoCreateJmsQueues, + final boolean autoDeleteJmsQueues) throws Exception { checkStarted(); @@ -1721,6 +1725,8 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active { addressSettings.setSlowConsumerPolicy(SlowConsumerPolicy.KILL); } + addressSettings.setAutoCreateJmsQueues(autoCreateJmsQueues); + addressSettings.setAutoDeleteJmsQueues(autoDeleteJmsQueues); server.getAddressSettingsRepository().addMatch(address, addressSettings); storageManager.storeAddressSetting(new PersistedAddressSetting(new SimpleString(address), addressSettings)); diff --git a/activemq-server/src/main/java/org/apache/activemq/core/persistence/QueueBindingInfo.java b/activemq-server/src/main/java/org/apache/activemq/core/persistence/QueueBindingInfo.java index 69885b08c2..a4ecf2259d 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/persistence/QueueBindingInfo.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/persistence/QueueBindingInfo.java @@ -43,4 +43,6 @@ public interface QueueBindingInfo SimpleString getFilterString(); + boolean isAutoCreated(); + } diff --git a/activemq-server/src/main/java/org/apache/activemq/core/persistence/impl/journal/JournalStorageManager.java b/activemq-server/src/main/java/org/apache/activemq/core/persistence/impl/journal/JournalStorageManager.java index 204411831b..82b135c70b 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/persistence/impl/journal/JournalStorageManager.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/persistence/impl/journal/JournalStorageManager.java @@ -2014,7 +2014,8 @@ public class JournalStorageManager implements StorageManager PersistentQueueBindingEncoding bindingEncoding = new PersistentQueueBindingEncoding(queue.getName(), binding.getAddress(), - filterString); + filterString, + queue.isAutoCreated()); readLock(); try @@ -3027,6 +3028,8 @@ public class JournalStorageManager implements StorageManager public SimpleString filterString; + public boolean autoCreated; + public PersistentQueueBindingEncoding() { } @@ -3041,16 +3044,20 @@ public class JournalStorageManager implements StorageManager address + ", filterString=" + filterString + + ", autoCreated=" + + autoCreated + "]"; } public PersistentQueueBindingEncoding(final SimpleString name, final SimpleString address, - final SimpleString filterString) + final SimpleString filterString, + final boolean autoCreated) { this.name = name; this.address = address; this.filterString = filterString; + this.autoCreated = autoCreated; } public long getId() @@ -3083,11 +3090,17 @@ public class JournalStorageManager implements StorageManager return name; } + public boolean isAutoCreated() + { + return autoCreated; + } + public void decode(final ActiveMQBuffer buffer) { name = buffer.readSimpleString(); address = buffer.readSimpleString(); filterString = buffer.readNullableSimpleString(); + autoCreated = buffer.readBoolean(); } public void encode(final ActiveMQBuffer buffer) @@ -3095,12 +3108,13 @@ public class JournalStorageManager implements StorageManager buffer.writeSimpleString(name); buffer.writeSimpleString(address); buffer.writeNullableSimpleString(filterString); + buffer.writeBoolean(autoCreated); } public int getEncodeSize() { return SimpleString.sizeofString(name) + SimpleString.sizeofString(address) + - SimpleString.sizeofNullableString(filterString); + SimpleString.sizeofNullableString(filterString) + DataConstants.SIZE_BOOLEAN; } } diff --git a/activemq-server/src/main/java/org/apache/activemq/core/protocol/core/ServerSessionPacketHandler.java b/activemq-server/src/main/java/org/apache/activemq/core/protocol/core/ServerSessionPacketHandler.java index 65db0866e8..529137a5ff 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/protocol/core/ServerSessionPacketHandler.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/protocol/core/ServerSessionPacketHandler.java @@ -72,6 +72,7 @@ import org.apache.activemq.core.protocol.core.impl.wireformat.SessionAddMetaData import org.apache.activemq.core.protocol.core.impl.wireformat.SessionAddMetaDataMessageV2; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryResponseMessage; +import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryResponseMessage_V2; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionConsumerCloseMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionConsumerFlowCreditMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionCreateConsumerMessage; @@ -81,6 +82,7 @@ import org.apache.activemq.core.protocol.core.impl.wireformat.SessionForceConsum import org.apache.activemq.core.protocol.core.impl.wireformat.SessionIndividualAcknowledgeMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryResponseMessage; +import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryResponseMessage_V2; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionRequestProducerCreditsMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionSendContinuationMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionSendLargeMessage; @@ -230,7 +232,15 @@ public class ServerSessionPacketHandler implements ChannelHandler { // We send back queue information on the queue as a response- this allows the queue to // be automatically recreated on failover - response = new SessionQueueQueryResponseMessage(session.executeQueueQuery(request.getQueueName())); + QueueQueryResult queueQueryResult = session.executeQueueQuery(request.getQueueName()); + if (channel.supports(PacketImpl.SESS_QUEUEQUERY_RESP_V2)) + { + response = new SessionQueueQueryResponseMessage_V2(queueQueryResult); + } + else + { + response = new SessionQueueQueryResponseMessage(queueQueryResult); + } } break; @@ -277,7 +287,14 @@ public class ServerSessionPacketHandler implements ChannelHandler requiresResponse = true; SessionQueueQueryMessage request = (SessionQueueQueryMessage)packet; QueueQueryResult result = session.executeQueueQuery(request.getQueueName()); - response = new SessionQueueQueryResponseMessage(result); + if (channel.supports(PacketImpl.SESS_QUEUEQUERY_RESP_V2)) + { + response = new SessionQueueQueryResponseMessage_V2(result); + } + else + { + response = new SessionQueueQueryResponseMessage(result); + } break; } case SESS_BINDINGQUERY: @@ -285,7 +302,14 @@ public class ServerSessionPacketHandler implements ChannelHandler requiresResponse = true; SessionBindingQueryMessage request = (SessionBindingQueryMessage)packet; BindingQueryResult result = session.executeBindingQuery(request.getAddress()); - response = new SessionBindingQueryResponseMessage(result.isExists(), result.getQueueNames()); + if (channel.supports(PacketImpl.SESS_BINDINGQUERY_RESP_V2)) + { + response = new SessionBindingQueryResponseMessage_V2(result.isExists(), result.getQueueNames(), result.isAutoCreateJmsQueues()); + } + else + { + response = new SessionBindingQueryResponseMessage(result.isExists(), result.getQueueNames()); + } break; } case SESS_ACKNOWLEDGE: diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/ActiveMQServer.java b/activemq-server/src/main/java/org/apache/activemq/core/server/ActiveMQServer.java index 2866f2ef5e..2054be14bc 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/ActiveMQServer.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/ActiveMQServer.java @@ -177,6 +177,13 @@ public interface ActiveMQServer extends ActiveMQComponent boolean durable, boolean temporary) throws Exception; + Queue createQueue(SimpleString address, + SimpleString queueName, + SimpleString filter, + boolean durable, + boolean temporary, + boolean autoCreated) throws Exception; + Queue deployQueue(SimpleString address, SimpleString queueName, SimpleString filterString, diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/ActiveMQServerLogger.java b/activemq-server/src/main/java/org/apache/activemq/core/server/ActiveMQServerLogger.java index 469b75142c..7d6889dc60 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/ActiveMQServerLogger.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/ActiveMQServerLogger.java @@ -1366,4 +1366,8 @@ public interface ActiveMQServerLogger extends BasicLogger @Message(id = 224064, value = "Setting <{0}> is invalid with this HA Policy Configuration. Please use exclusively or remove. Ignoring <{0}> value.", format = Message.Format.MESSAGE_FORMAT) void incompatibleWithHAPolicyChosen(String parameter); + @LogMessage(level = Logger.Level.ERROR) + @Message(id = 224065, value = "Failed to remove auto-created queue {0}", format = Message.Format.MESSAGE_FORMAT) + void errorRemovingAutoCreatedQueue(@Cause Exception e, SimpleString bindingName); + } diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/AutoCreatedQueueManager.java b/activemq-server/src/main/java/org/apache/activemq/core/server/AutoCreatedQueueManager.java new file mode 100644 index 0000000000..03d4d8888d --- /dev/null +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/AutoCreatedQueueManager.java @@ -0,0 +1,29 @@ +/** + * 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.core.server; + +import org.apache.activemq.api.core.SimpleString; +import org.apache.activemq.utils.ReferenceCounter; + +/** + * @author Clebert Suconic + */ + +public interface AutoCreatedQueueManager extends ReferenceCounter +{ + SimpleString getQueueName(); +} diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/BindingQueryResult.java b/activemq-server/src/main/java/org/apache/activemq/core/server/BindingQueryResult.java index 9d2255f84a..33339cfd4e 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/BindingQueryResult.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/BindingQueryResult.java @@ -33,11 +33,15 @@ public class BindingQueryResult private List queueNames; - public BindingQueryResult(final boolean exists, final List queueNames) + private boolean autoCreateJmsQueues; + + public BindingQueryResult(final boolean exists, final List queueNames, final boolean autoCreateJmsQueues) { this.exists = exists; this.queueNames = queueNames; + + this.autoCreateJmsQueues = autoCreateJmsQueues; } public boolean isExists() @@ -45,6 +49,11 @@ public class BindingQueryResult return exists; } + public boolean isAutoCreateJmsQueues() + { + return autoCreateJmsQueues; + } + public List getQueueNames() { return queueNames; diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/Queue.java b/activemq-server/src/main/java/org/apache/activemq/core/server/Queue.java index 4759df0f71..e3d2d2c1c3 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/Queue.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/Queue.java @@ -49,6 +49,8 @@ public interface Queue extends Bindable boolean isTemporary(); + boolean isAutoCreated(); + void addConsumer(Consumer consumer) throws Exception; void removeConsumer(Consumer consumer); @@ -62,7 +64,7 @@ public interface Queue extends Bindable * on shared subscriptions where the queue needs to be deleted when all the * consumers are closed. */ - void setConsumersRefCount(ActiveMQServer server); + void setConsumersRefCount(ReferenceCounter referenceCounter); ReferenceCounter getConsumersRefCount(); diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/QueueFactory.java b/activemq-server/src/main/java/org/apache/activemq/core/server/QueueFactory.java index 12cef0a29d..8e9e7ed0ce 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/QueueFactory.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/QueueFactory.java @@ -39,7 +39,8 @@ public interface QueueFactory Filter filter, PageSubscription pageSubscription, boolean durable, - boolean temporary); + boolean temporary, + boolean autoCreated); /** * This is required for delete-all-reference to work correctly with paging diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ActiveMQServerImpl.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ActiveMQServerImpl.java index bba4729cf6..fd412d9af5 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ActiveMQServerImpl.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ActiveMQServerImpl.java @@ -1193,9 +1193,18 @@ public class ActiveMQServerImpl implements ActiveMQServer final boolean durable, final boolean temporary) throws Exception { - return createQueue(address, queueName, filterString, durable, temporary, false, false); + return createQueue(address, queueName, filterString, durable, temporary, false, false, false); } + public Queue createQueue(final SimpleString address, + final SimpleString queueName, + final SimpleString filterString, + final boolean durable, + final boolean temporary, + final boolean autoCreated) throws Exception + { + return createQueue(address, queueName, filterString, durable, temporary, false, false, autoCreated); + } /** * Creates a transient queue. A queue that will exist as long as there are consumers. @@ -1214,7 +1223,7 @@ public class ActiveMQServerImpl implements ActiveMQServer final SimpleString filterString, boolean durable) throws Exception { - Queue queue = createQueue(address, name, filterString, durable, !durable, true, !durable); + Queue queue = createQueue(address, name, filterString, durable, !durable, true, !durable, false); if (!queue.getAddress().equals(address)) { @@ -1263,7 +1272,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { ActiveMQServerLogger.LOGGER.deployQueue(queueName); - return createQueue(address, queueName, filterString, durable, temporary, true, false); + return createQueue(address, queueName, filterString, durable, temporary, true, false, false); } public void destroyQueue(final SimpleString queueName) throws Exception @@ -1981,7 +1990,8 @@ public class ActiveMQServerImpl implements ActiveMQServer final boolean durable, final boolean temporary, final boolean ignoreIfExists, - final boolean transientQueue) throws Exception + final boolean transientQueue, + final boolean autoCreated) throws Exception { QueueBinding binding = (QueueBinding) postOffice.getBinding(queueName); @@ -2021,11 +2031,16 @@ public class ActiveMQServerImpl implements ActiveMQServer filter, pageSubscription, durable, - temporary); + temporary, + autoCreated); if (transientQueue) { - queue.setConsumersRefCount(this); + queue.setConsumersRefCount(new TransientQueueManagerImpl(this, queueName)); + } + else if (autoCreated) + { + queue.setConsumersRefCount(new AutoCreatedQueueManagerImpl(this, queueName)); } binding = new LocalQueueBinding(address, queue, nodeManager.getNodeId()); diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/AutoCreatedQueueManagerImpl.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/AutoCreatedQueueManagerImpl.java new file mode 100644 index 0000000000..5bcd2c66b1 --- /dev/null +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/AutoCreatedQueueManagerImpl.java @@ -0,0 +1,93 @@ +/** + * 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.core.server.impl; + +import org.apache.activemq.api.core.SimpleString; +import org.apache.activemq.core.server.ActiveMQServer; +import org.apache.activemq.core.server.ActiveMQServerLogger; +import org.apache.activemq.core.server.AutoCreatedQueueManager; +import org.apache.activemq.core.server.Queue; +import org.apache.activemq.utils.ReferenceCounterUtil; + +/** + * @author Clebert Suconic + */ + +public class AutoCreatedQueueManagerImpl implements AutoCreatedQueueManager +{ + private final SimpleString queueName; + + private final ActiveMQServer server; + + private final Runnable runnable = new Runnable() + { + public void run() + { + try + { + Queue queue = server.locateQueue(queueName); + long consumerCount = queue.getConsumerCount(); + long messageCount = queue.getMessageCount(); + + if (server.locateQueue(queueName).getMessageCount() == 0) + { + if (ActiveMQServerLogger.LOGGER.isDebugEnabled()) + { + ActiveMQServerLogger.LOGGER.debug("deleting auto-created queue \"" + queueName + "\" because consumerCount = " + consumerCount + " and messageCount = " + messageCount); + } + + server.destroyQueue(queueName, null, false); + } + else if (ActiveMQServerLogger.LOGGER.isDebugEnabled()) + { + ActiveMQServerLogger.LOGGER.debug("NOT deleting auto-created queue \"" + queueName + "\" because consumerCount = " + consumerCount + " and messageCount = " + messageCount); + } + } + catch (Exception e) + { + ActiveMQServerLogger.LOGGER.errorRemovingAutoCreatedQueue(e, queueName); + } + } + }; + + private final ReferenceCounterUtil referenceCounterUtil = new ReferenceCounterUtil(runnable); + + public AutoCreatedQueueManagerImpl(ActiveMQServer server, SimpleString queueName) + { + this.server = server; + + this.queueName = queueName; + } + + @Override + public int increment() + { + return referenceCounterUtil.increment(); + } + + @Override + public int decrement() + { + return referenceCounterUtil.decrement(); + } + + @Override + public SimpleString getQueueName() + { + return queueName; + } +} diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/LastValueQueue.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/LastValueQueue.java index bd86f98b0d..c796d2d331 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/LastValueQueue.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/LastValueQueue.java @@ -55,6 +55,7 @@ public class LastValueQueue extends QueueImpl final PageSubscription pageSubscription, final boolean durable, final boolean temporary, + final boolean autoCreated, final ScheduledExecutorService scheduledExecutor, final PostOffice postOffice, final StorageManager storageManager, @@ -68,6 +69,7 @@ public class LastValueQueue extends QueueImpl pageSubscription, durable, temporary, + autoCreated, scheduledExecutor, postOffice, storageManager, diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/PostOfficeJournalLoader.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/PostOfficeJournalLoader.java index 7fcf169060..90a035ee7c 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/PostOfficeJournalLoader.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/PostOfficeJournalLoader.java @@ -46,6 +46,7 @@ import org.apache.activemq.core.postoffice.Binding; import org.apache.activemq.core.postoffice.DuplicateIDCache; import org.apache.activemq.core.postoffice.PostOffice; import org.apache.activemq.core.postoffice.impl.LocalQueueBinding; +import org.apache.activemq.core.postoffice.impl.PostOfficeImpl; import org.apache.activemq.core.server.ActiveMQServerLogger; import org.apache.activemq.core.server.MessageReference; import org.apache.activemq.core.server.NodeManager; @@ -155,7 +156,13 @@ public class PostOfficeJournalLoader implements JournalLoader filter, subscription, true, - false); + false, + queueBindingInfo.isAutoCreated()); + + if (queueBindingInfo.isAutoCreated()) + { + queue.setConsumersRefCount(new AutoCreatedQueueManagerImpl(((PostOfficeImpl)postOffice).getServer(), queueBindingInfo.getQueueName())); + } Binding binding = new LocalQueueBinding(queueBindingInfo.getAddress(), queue, nodeManager.getNodeId()); diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueFactoryImpl.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueFactoryImpl.java index ff5fdd87e2..104ce4ffcd 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueFactoryImpl.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueFactoryImpl.java @@ -75,7 +75,8 @@ public class QueueFactoryImpl implements QueueFactory final Filter filter, final PageSubscription pageSubscription, final boolean durable, - final boolean temporary) + final boolean temporary, + final boolean autoCreated) { AddressSettings addressSettings = addressSettingsRepository.getMatch(address.toString()); @@ -89,6 +90,7 @@ public class QueueFactoryImpl implements QueueFactory pageSubscription, durable, temporary, + autoCreated, scheduledExecutor, postOffice, storageManager, @@ -104,6 +106,7 @@ public class QueueFactoryImpl implements QueueFactory pageSubscription, durable, temporary, + autoCreated, scheduledExecutor, postOffice, storageManager, diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueImpl.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueImpl.java index e127fe6037..90d424c15e 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueImpl.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/QueueImpl.java @@ -61,7 +61,6 @@ import org.apache.activemq.core.server.ActiveMQServerLogger; import org.apache.activemq.core.server.Consumer; import org.apache.activemq.core.server.HandleStatus; import org.apache.activemq.core.server.ActiveMQMessageBundle; -import org.apache.activemq.core.server.ActiveMQServer; import org.apache.activemq.core.server.MessageReference; import org.apache.activemq.core.server.Queue; import org.apache.activemq.core.server.RoutingContext; @@ -131,6 +130,8 @@ public class QueueImpl implements Queue private final boolean temporary; + private final boolean autoCreated; + private final PostOffice postOffice; private volatile boolean queueDestroyed = false; @@ -315,6 +316,7 @@ public class QueueImpl implements Queue final Filter filter, final boolean durable, final boolean temporary, + final boolean autoCreated, final ScheduledExecutorService scheduledExecutor, final PostOffice postOffice, final StorageManager storageManager, @@ -328,6 +330,7 @@ public class QueueImpl implements Queue null, durable, temporary, + autoCreated, scheduledExecutor, postOffice, storageManager, @@ -342,6 +345,7 @@ public class QueueImpl implements Queue final PageSubscription pageSubscription, final boolean durable, final boolean temporary, + final boolean autoCreated, final ScheduledExecutorService scheduledExecutor, final PostOffice postOffice, final StorageManager storageManager, @@ -362,6 +366,8 @@ public class QueueImpl implements Queue this.temporary = temporary; + this.autoCreated = autoCreated; + this.postOffice = postOffice; this.storageManager = storageManager; @@ -425,11 +431,11 @@ public class QueueImpl implements Queue } // Queue implementation ---------------------------------------------------------------------------------------- - public synchronized void setConsumersRefCount(final ActiveMQServer server) + public synchronized void setConsumersRefCount(final ReferenceCounter referenceCounter) { if (refCountForConsumers == null) { - this.refCountForConsumers = new TransientQueueManagerImpl(server, this.name); + this.refCountForConsumers = referenceCounter; } } @@ -449,6 +455,11 @@ public class QueueImpl implements Queue return temporary; } + public boolean isAutoCreated() + { + return autoCreated; + } + public SimpleString getName() { return name; diff --git a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ServerSessionImpl.java b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ServerSessionImpl.java index 553747b836..379079584e 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ServerSessionImpl.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/server/impl/ServerSessionImpl.java @@ -37,6 +37,7 @@ import org.apache.activemq.api.core.Pair; import org.apache.activemq.api.core.SimpleString; import org.apache.activemq.api.core.management.CoreNotificationType; import org.apache.activemq.api.core.management.ManagementHelper; +import org.apache.activemq.api.core.management.ResourceNames; import org.apache.activemq.core.client.impl.ClientMessageImpl; import org.apache.activemq.core.exception.ActiveMQXAException; import org.apache.activemq.core.filter.Filter; @@ -549,7 +550,15 @@ public class ServerSessionImpl implements ServerSession, FailureListener securityStore.check(address, CheckType.CREATE_NON_DURABLE_QUEUE, this); } - Queue queue = server.createQueue(address, name, filterString, durable, temporary); + // any non-temporary JMS queue created via this method should be marked as auto-created + if (!temporary && address.toString().startsWith(ResourceNames.JMS_QUEUE) && address.equals(name)) + { + server.createQueue(address, name, filterString, durable, temporary, true); + } + else + { + server.createQueue(address, name, filterString, durable, temporary); + } if (temporary) { @@ -676,6 +685,8 @@ public class ServerSessionImpl implements ServerSession, FailureListener public QueueQueryResult executeQueueQuery(final SimpleString name) throws Exception { + boolean autoCreateJmsQueues = name.toString().startsWith(ResourceNames.JMS_QUEUE) && server.getAddressSettingsRepository().getMatch(name.toString()).isAutoCreateJmsQueues(); + if (name == null) { throw ActiveMQMessageBundle.BUNDLE.queueNameIsNull(); @@ -699,16 +710,21 @@ public class ServerSessionImpl implements ServerSession, FailureListener queue.isTemporary(), filterString, queue.getConsumerCount(), - queue.getMessageCount()); + queue.getMessageCount(), + autoCreateJmsQueues); } // make an exception for the management address (see HORNETQ-29) else if (name.equals(managementAddress)) { - response = new QueueQueryResult(name, managementAddress, true, false, null, -1, -1); + response = new QueueQueryResult(name, managementAddress, true, false, null, -1, -1, autoCreateJmsQueues); + } + else if (autoCreateJmsQueues) + { + response = new QueueQueryResult(name, name, true, false, null, 0, 0, true, false); } else { - response = new QueueQueryResult(); + response = new QueueQueryResult(null, null, false, false, null, 0, 0, false, false); } return response; @@ -716,6 +732,8 @@ public class ServerSessionImpl implements ServerSession, FailureListener public BindingQueryResult executeBindingQuery(final SimpleString address) throws Exception { + boolean autoCreateJmsQueues = address.toString().startsWith(ResourceNames.JMS_QUEUE) && server.getAddressSettingsRepository().getMatch(address.toString()).isAutoCreateJmsQueues(); + if (address == null) { throw ActiveMQMessageBundle.BUNDLE.addressIsNull(); @@ -726,7 +744,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener // make an exception for the management address (see HORNETQ-29) if (address.equals(managementAddress)) { - return new BindingQueryResult(true, names); + return new BindingQueryResult(true, names, autoCreateJmsQueues); } Bindings bindings = postOffice.getMatchingBindings(address); @@ -739,7 +757,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener } } - return new BindingQueryResult(!names.isEmpty(), names); + return new BindingQueryResult(!names.isEmpty(), names, autoCreateJmsQueues); } public void forceConsumerDelivery(final long consumerID, final long sequence) throws Exception diff --git a/activemq-server/src/main/java/org/apache/activemq/core/settings/impl/AddressSettings.java b/activemq-server/src/main/java/org/apache/activemq/core/settings/impl/AddressSettings.java index 0d3a32e4f1..5a8689b75e 100644 --- a/activemq-server/src/main/java/org/apache/activemq/core/settings/impl/AddressSettings.java +++ b/activemq-server/src/main/java/org/apache/activemq/core/settings/impl/AddressSettings.java @@ -56,6 +56,10 @@ public class AddressSettings implements Mergeable, Serializable public static final boolean DEFAULT_LAST_VALUE_QUEUE = false; + public static final boolean DEFAULT_AUTO_CREATE_QUEUES = true; + + public static final boolean DEFAULT_AUTO_DELETE_QUEUES = true; + public static final long DEFAULT_REDISTRIBUTION_DELAY = -1; public static final long DEFAULT_EXPIRY_DELAY = -1; @@ -106,6 +110,10 @@ public class AddressSettings implements Mergeable, Serializable private SlowConsumerPolicy slowConsumerPolicy = null; + private Boolean autoCreateJmsQueues = null; + + private Boolean autoDeleteJmsQueues = null; + public AddressSettings(AddressSettings other) { this.addressFullMessagePolicy = other.addressFullMessagePolicy; @@ -127,6 +135,8 @@ public class AddressSettings implements Mergeable, Serializable this.slowConsumerThreshold = other.slowConsumerThreshold; this.slowConsumerCheckPeriod = other.slowConsumerCheckPeriod; this.slowConsumerPolicy = other.slowConsumerPolicy; + this.autoCreateJmsQueues = other.autoCreateJmsQueues; + this.autoDeleteJmsQueues = other.autoDeleteJmsQueues; } public AddressSettings() @@ -134,6 +144,26 @@ public class AddressSettings implements Mergeable, Serializable } + public boolean isAutoCreateJmsQueues() + { + return autoCreateJmsQueues != null ? autoCreateJmsQueues : AddressSettings.DEFAULT_AUTO_CREATE_QUEUES; + } + + public void setAutoCreateJmsQueues(final boolean autoCreateJmsQueues) + { + this.autoCreateJmsQueues = autoCreateJmsQueues; + } + + public boolean isAutoDeleteJmsQueues() + { + return autoDeleteJmsQueues != null ? autoDeleteJmsQueues : AddressSettings.DEFAULT_AUTO_DELETE_QUEUES; + } + + public void setAutoDeleteJmsQueues(final boolean autoDeleteJmsQueues) + { + this.autoDeleteJmsQueues = autoDeleteJmsQueues; + } + public boolean isLastValueQueue() { return lastValueQueue != null ? lastValueQueue : AddressSettings.DEFAULT_LAST_VALUE_QUEUE; @@ -398,6 +428,14 @@ public class AddressSettings implements Mergeable, Serializable { slowConsumerPolicy = merged.slowConsumerPolicy; } + if (autoCreateJmsQueues == null) + { + autoCreateJmsQueues = merged.autoCreateJmsQueues; + } + if (autoDeleteJmsQueues == null) + { + autoDeleteJmsQueues = merged.autoDeleteJmsQueues; + } } @Override @@ -458,6 +496,10 @@ public class AddressSettings implements Mergeable, Serializable { slowConsumerPolicy = null; } + + autoCreateJmsQueues = BufferHelper.readNullableBoolean(buffer); + + autoDeleteJmsQueues = BufferHelper.readNullableBoolean(buffer); } @Override @@ -482,7 +524,9 @@ public class AddressSettings implements Mergeable, Serializable BufferHelper.sizeOfNullableBoolean(sendToDLAOnNoRoute) + BufferHelper.sizeOfNullableLong(slowConsumerCheckPeriod) + BufferHelper.sizeOfNullableLong(slowConsumerThreshold) + - BufferHelper.sizeOfNullableSimpleString(slowConsumerPolicy != null ? slowConsumerPolicy.toString() : null); + BufferHelper.sizeOfNullableSimpleString(slowConsumerPolicy != null ? slowConsumerPolicy.toString() : null) + + BufferHelper.sizeOfNullableBoolean(autoCreateJmsQueues) + + BufferHelper.sizeOfNullableBoolean(autoDeleteJmsQueues); } @Override @@ -526,6 +570,10 @@ public class AddressSettings implements Mergeable, Serializable BufferHelper.writeNullableLong(buffer, slowConsumerCheckPeriod); buffer.writeNullableSimpleString(slowConsumerPolicy != null ? new SimpleString(slowConsumerPolicy.toString()) : null); + + BufferHelper.writeNullableBoolean(buffer, autoCreateJmsQueues); + + BufferHelper.writeNullableBoolean(buffer, autoDeleteJmsQueues); } /* (non-Javadoc) @@ -556,6 +604,8 @@ public class AddressSettings implements Mergeable, Serializable result = prime * result + ((slowConsumerThreshold == null) ? 0 : slowConsumerThreshold.hashCode()); result = prime * result + ((slowConsumerCheckPeriod == null) ? 0 : slowConsumerCheckPeriod.hashCode()); result = prime * result + ((slowConsumerPolicy == null) ? 0 : slowConsumerPolicy.hashCode()); + result = prime * result + ((autoCreateJmsQueues == null) ? 0 : autoCreateJmsQueues.hashCode()); + result = prime * result + ((autoDeleteJmsQueues == null) ? 0 : autoDeleteJmsQueues.hashCode()); return result; } @@ -705,6 +755,20 @@ public class AddressSettings implements Mergeable, Serializable } else if (!slowConsumerPolicy.equals(other.slowConsumerPolicy)) return false; + if (autoCreateJmsQueues == null) + { + if (other.autoCreateJmsQueues != null) + return false; + } + else if (!autoCreateJmsQueues.equals(other.autoCreateJmsQueues)) + return false; + if (autoDeleteJmsQueues == null) + { + if (other.autoDeleteJmsQueues != null) + return false; + } + else if (!autoDeleteJmsQueues.equals(other.autoDeleteJmsQueues)) + return false; return true; } @@ -751,6 +815,10 @@ public class AddressSettings implements Mergeable, Serializable slowConsumerCheckPeriod + ", slowConsumerPolicy=" + slowConsumerPolicy + + ", autoCreateJmsQueues=" + + autoCreateJmsQueues + + ", autoDeleteJmsQueues=" + + autoDeleteJmsQueues + "]"; } } diff --git a/activemq-server/src/main/resources/schema/activemq-configuration.xsd b/activemq-server/src/main/resources/schema/activemq-configuration.xsd index 7ca0468d32..bc6bea3ed8 100644 --- a/activemq-server/src/main/resources/schema/activemq-configuration.xsd +++ b/activemq-server/src/main/resources/schema/activemq-configuration.xsd @@ -2258,6 +2258,23 @@ + + + + + whether or not to automatically create JMS queues when a producer sends or a consumer connects to a + queue + + + + + + + + whether or not to delete auto-created JMS queues when the queue has 0 consumers and 0 messages + + + diff --git a/activemq-server/src/test/java/org/apache/activemq/core/config/impl/FileConfigurationTest.java b/activemq-server/src/test/java/org/apache/activemq/core/config/impl/FileConfigurationTest.java index a892c03413..bf10266679 100644 --- a/activemq-server/src/test/java/org/apache/activemq/core/config/impl/FileConfigurationTest.java +++ b/activemq-server/src/test/java/org/apache/activemq/core/config/impl/FileConfigurationTest.java @@ -297,6 +297,8 @@ public class FileConfigurationTest extends ConfigurationImplTest assertEquals(10, conf.getAddressesSettings().get("a1").getSlowConsumerThreshold()); assertEquals(5, conf.getAddressesSettings().get("a1").getSlowConsumerCheckPeriod()); assertEquals(SlowConsumerPolicy.NOTIFY, conf.getAddressesSettings().get("a1").getSlowConsumerPolicy()); + assertEquals(true, conf.getAddressesSettings().get("a1").isAutoCreateJmsQueues()); + assertEquals(true, conf.getAddressesSettings().get("a1").isAutoDeleteJmsQueues()); assertEquals("a2.1", conf.getAddressesSettings().get("a2").getDeadLetterAddress().toString()); assertEquals("a2.2", conf.getAddressesSettings().get("a2").getExpiryAddress().toString()); @@ -308,6 +310,8 @@ public class FileConfigurationTest extends ConfigurationImplTest assertEquals(20, conf.getAddressesSettings().get("a2").getSlowConsumerThreshold()); assertEquals(15, conf.getAddressesSettings().get("a2").getSlowConsumerCheckPeriod()); assertEquals(SlowConsumerPolicy.KILL, conf.getAddressesSettings().get("a2").getSlowConsumerPolicy()); + assertEquals(false, conf.getAddressesSettings().get("a2").isAutoCreateJmsQueues()); + assertEquals(false, conf.getAddressesSettings().get("a2").isAutoDeleteJmsQueues()); assertEquals(2, conf.getQueueConfigurations().size()); diff --git a/activemq-server/src/test/java/org/apache/activemq/core/server/impl/ScheduledDeliveryHandlerTest.java b/activemq-server/src/test/java/org/apache/activemq/core/server/impl/ScheduledDeliveryHandlerTest.java index abb6e86d64..7b85924e42 100644 --- a/activemq-server/src/test/java/org/apache/activemq/core/server/impl/ScheduledDeliveryHandlerTest.java +++ b/activemq-server/src/test/java/org/apache/activemq/core/server/impl/ScheduledDeliveryHandlerTest.java @@ -42,7 +42,6 @@ import org.apache.activemq.core.message.BodyEncoder; import org.apache.activemq.core.paging.PagingStore; import org.apache.activemq.core.paging.cursor.PageSubscription; import org.apache.activemq.core.server.Consumer; -import org.apache.activemq.core.server.ActiveMQServer; import org.apache.activemq.core.server.MessageReference; import org.apache.activemq.core.server.Queue; import org.apache.activemq.core.server.RoutingContext; @@ -1053,6 +1052,12 @@ public class ScheduledDeliveryHandlerTest extends Assert return false; } + @Override + public boolean isAutoCreated() + { + return false; + } + @Override public void addConsumer(Consumer consumer) throws Exception { @@ -1072,7 +1077,7 @@ public class ScheduledDeliveryHandlerTest extends Assert } @Override - public void setConsumersRefCount(ActiveMQServer server) + public void setConsumersRefCount(ReferenceCounter referenceCounter) { } diff --git a/activemq-server/src/test/java/org/apache/activemq/core/settings/AddressSettingsTest.java b/activemq-server/src/test/java/org/apache/activemq/core/settings/AddressSettingsTest.java index 2d71668f27..42324203db 100644 --- a/activemq-server/src/test/java/org/apache/activemq/core/settings/AddressSettingsTest.java +++ b/activemq-server/src/test/java/org/apache/activemq/core/settings/AddressSettingsTest.java @@ -46,7 +46,8 @@ public class AddressSettingsTest extends UnitTestCase Assert.assertEquals(AddressSettings.DEFAULT_SLOW_CONSUMER_THRESHOLD, addressSettings.getSlowConsumerThreshold()); Assert.assertEquals(AddressSettings.DEFAULT_SLOW_CONSUMER_CHECK_PERIOD, addressSettings.getSlowConsumerCheckPeriod()); Assert.assertEquals(AddressSettings.DEFAULT_SLOW_CONSUMER_POLICY, addressSettings.getSlowConsumerPolicy()); - + Assert.assertEquals(AddressSettings.DEFAULT_AUTO_CREATE_QUEUES, addressSettings.isAutoCreateJmsQueues()); + Assert.assertEquals(AddressSettings.DEFAULT_AUTO_DELETE_QUEUES, addressSettings.isAutoDeleteJmsQueues()); } @Test diff --git a/activemq-server/src/test/resources/ConfigurationTest-full-config.xml b/activemq-server/src/test/resources/ConfigurationTest-full-config.xml index 9180f93fab..3f2ab446fc 100644 --- a/activemq-server/src/test/resources/ConfigurationTest-full-config.xml +++ b/activemq-server/src/test/resources/ConfigurationTest-full-config.xml @@ -271,6 +271,8 @@ 10 5 NOTIFY + true + true a2.1 @@ -283,6 +285,8 @@ 20 15 KILL + false + false diff --git a/docs/user-manual/en/queue-attributes.md b/docs/user-manual/en/queue-attributes.md index d53467350e..9892e69991 100644 --- a/docs/user-manual/en/queue-attributes.md +++ b/docs/user-manual/en/queue-attributes.md @@ -95,6 +95,8 @@ entry that would be found in the `activemq-configuration.xml` file. -1 NOTIFY 5 + true + true @@ -176,3 +178,13 @@ on this notification. `slow-consumer-check-period`. How often to check for slow consumers on a particular queue. Measured in minutes. Default is 5. See ? for more information about slow consumer detection. + +`auto-create-jms-queues`. Whether or not the broker should automatically +create a JMS queue when a JMS message is sent to a queue whose name fits +the address `match` (remember, a JMS queue is just a core queue which has +the same address and queue name) or a JMS consumer tries to connect to a +queue whose name fits the address `match`. Queues which are auto-created +are durable, non-temporary, and non-transient. + +`auto-delete-jms-queues`. Whether or not to the broker should automatically +delete auto-created JMS queues when they have both 0 consumers and 0 messages. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 4f3f440150..0f861f7805 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ 6 0 0 - 125,124,123,122 + 126,125,124,123,122 SNAPSHOT SNAPSHOT diff --git a/tests/concurrent-tests/src/test/java/org/apache/activemq/tests/concurrent/server/impl/QueueTest.java b/tests/concurrent-tests/src/test/java/org/apache/activemq/tests/concurrent/server/impl/QueueTest.java index 5ba28b5ee4..f0039ff0c8 100644 --- a/tests/concurrent-tests/src/test/java/org/apache/activemq/tests/concurrent/server/impl/QueueTest.java +++ b/tests/concurrent-tests/src/test/java/org/apache/activemq/tests/concurrent/server/impl/QueueTest.java @@ -77,6 +77,7 @@ public class QueueTest extends UnitTestCase null, null, false, + false, false); FakeConsumer consumer = new FakeConsumer(); diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/AutoCreateJmsQueueTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/AutoCreateJmsQueueTest.java new file mode 100644 index 0000000000..f76d631675 --- /dev/null +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/AutoCreateJmsQueueTest.java @@ -0,0 +1,187 @@ +/** + * 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.tests.integration.client; + +import javax.jms.Connection; +import javax.jms.InvalidDestinationException; +import javax.jms.JMSSecurityException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TextMessage; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.activemq.api.core.SimpleString; +import org.apache.activemq.api.jms.ActiveMQJMSClient; +import org.apache.activemq.core.security.Role; +import org.apache.activemq.core.server.Queue; +import org.apache.activemq.tests.util.JMSTestBase; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * @author Justin Bertram + */ +public class AutoCreateJmsQueueTest extends JMSTestBase +{ + @Test + public void testAutoCreateOnSendToQueue() throws Exception + { + Connection connection = cf.createConnection(); + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + javax.jms.Queue queue = ActiveMQJMSClient.createQueue("test"); + + MessageProducer producer = session.createProducer(queue); + + final int numMessages = 100; + + for (int i = 0; i < numMessages; i++) + { + TextMessage mess = session.createTextMessage("msg" + i); + producer.send(mess); + } + + producer.close(); + + MessageConsumer messageConsumer = session.createConsumer(queue); + connection.start(); + + for (int i = 0; i < numMessages; i++) + { + Message m = messageConsumer.receive(5000); + Assert.assertNotNull(m); + } + + connection.close(); + } + + @Test + public void testAutoCreateOnSendToQueueSecurity() throws Exception + { + server.getSecurityManager().addUser("guest", "guest"); + server.getSecurityManager().setDefaultUser("guest"); + server.getSecurityManager().addRole("guest", "rejectAll"); + Role role = new Role("rejectAll", false, false, false, false, false, false, false); + Set roles = new HashSet(); + roles.add(role); + server.getSecurityRepository().addMatch("#", roles); + Connection connection = cf.createConnection(); + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + javax.jms.Queue queue = ActiveMQJMSClient.createQueue("test"); + + try + { + MessageProducer producer = session.createProducer(queue); + Assert.fail("Creating a producer here should throw a JMSSecurityException"); + } + catch (Exception e) + { + Assert.assertTrue(e instanceof JMSSecurityException); + } + + connection.close(); + } + + @Test + public void testAutoCreateOnSendToTopic() throws Exception + { + Connection connection = cf.createConnection(); + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + javax.jms.Topic topic = ActiveMQJMSClient.createTopic("test"); + + try + { + MessageProducer producer = session.createProducer(topic); + Assert.fail("Creating a producer here should throw an exception"); + } + catch (Exception e) + { + Assert.assertTrue(e instanceof InvalidDestinationException); + } + + connection.close(); + } + + @Test + public void testAutoCreateOnConsumeFromQueue() throws Exception + { + Connection connection = null; + connection = cf.createConnection(); + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + javax.jms.Queue queue = ActiveMQJMSClient.createQueue("test"); + + MessageConsumer messageConsumer = session.createConsumer(queue); + connection.start(); + + Message m = messageConsumer.receive(500); + Assert.assertNull(m); + + Queue q = (Queue) server.getPostOffice().getBinding(new SimpleString("jms.queue.test")).getBindable(); + Assert.assertEquals(0, q.getMessageCount()); + Assert.assertEquals(0, q.getMessagesAdded()); + connection.close(); + } + + @Test + public void testAutoCreateOnConsumeFromTopic() throws Exception + { + Connection connection = null; + connection = cf.createConnection(); + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + javax.jms.Topic topic = ActiveMQJMSClient.createTopic("test"); + + try + { + MessageConsumer messageConsumer = session.createConsumer(topic); + Assert.fail("Creating a consumer here should throw an exception"); + } + catch (Exception e) + { + Assert.assertTrue(e instanceof InvalidDestinationException); + } + + connection.close(); + } + + @Before + @Override + public void setUp() throws Exception + { + super.setUp(); + server.getSecurityManager().addUser("guest", "guest"); + server.getSecurityManager().setDefaultUser("guest"); + server.getSecurityManager().addRole("guest", "allowAll"); + Role role = new Role("allowAll", true, true, true, true, true, true, true); + Set roles = new HashSet(); + roles.add(role); + server.getSecurityRepository().addMatch("#", roles); + } + + protected boolean useSecurity() + { + return true; + } +} diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/AutoDeleteJmsQueueTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/AutoDeleteJmsQueueTest.java new file mode 100644 index 0000000000..14cacf77a7 --- /dev/null +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/AutoDeleteJmsQueueTest.java @@ -0,0 +1,84 @@ +/** + * 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.tests.integration.client; + +import javax.jms.Connection; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.activemq.api.core.SimpleString; +import org.apache.activemq.api.jms.ActiveMQJMSClient; +import org.apache.activemq.core.server.Queue; +import org.apache.activemq.tests.util.JMSTestBase; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Justin Bertram + */ +public class AutoDeleteJmsQueueTest extends JMSTestBase +{ + @Test + public void testAutoDelete() throws Exception + { + Connection connection = cf.createConnection(); + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + javax.jms.Queue queue = ActiveMQJMSClient.createQueue("test"); + + MessageProducer producer = session.createProducer(queue); + + final int numMessages = 100; + + for (int i = 0; i < numMessages; i++) + { + TextMessage mess = session.createTextMessage("msg" + i); + producer.send(mess); + } + + producer.close(); + + MessageConsumer messageConsumer = session.createConsumer(queue); + connection.start(); + + for (int i = 0; i < numMessages - 1; i++) + { + Message m = messageConsumer.receive(5000); + Assert.assertNotNull(m); + } + + session.close(); + + // ensure the queue is still there + Queue q = (Queue) server.getPostOffice().getBinding(new SimpleString("jms.queue.test")).getBindable(); + Assert.assertEquals(1, q.getMessageCount()); + Assert.assertEquals(numMessages, q.getMessagesAdded()); + + session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + messageConsumer = session.createConsumer(queue); + Message m = messageConsumer.receive(5000); + Assert.assertNotNull(m); + + connection.close(); + + // ensure the queue was removed + Assert.assertNull(server.getPostOffice().getBinding(new SimpleString("jms.queue.test"))); + } +} diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/HangConsumerTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/HangConsumerTest.java index b4a79774de..e953e83c5e 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/HangConsumerTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/HangConsumerTest.java @@ -242,6 +242,7 @@ public class HangConsumerTest extends ServiceTestBase final PageSubscription pageSubscription, final boolean durable, final boolean temporary, + final boolean autoCreated, final ScheduledExecutorService scheduledExecutor, final PostOffice postOffice, final StorageManager storageManager, @@ -255,6 +256,7 @@ public class HangConsumerTest extends ServiceTestBase pageSubscription, durable, temporary, + autoCreated, scheduledExecutor, postOffice, storageManager, @@ -294,7 +296,8 @@ public class HangConsumerTest extends ServiceTestBase final Filter filter, final PageSubscription pageSubscription, final boolean durable, - final boolean temporary) + final boolean temporary, + final boolean autoCreated) { queue = new MyQueueWithBlocking(persistenceID, address, @@ -303,6 +306,7 @@ public class HangConsumerTest extends ServiceTestBase pageSubscription, durable, temporary, + autoCreated, scheduledExecutor, postOffice, storageManager, @@ -401,7 +405,7 @@ public class HangConsumerTest extends ServiceTestBase // Forcing a situation where the server would unexpectedly create a duplicated queue. The server should still start normally - LocalQueueBinding newBinding = new LocalQueueBinding(QUEUE, new QueueImpl(queueID, QUEUE, QUEUE, null, true, false, null, null, null, null, null), server.getNodeID()); + LocalQueueBinding newBinding = new LocalQueueBinding(QUEUE, new QueueImpl(queueID, QUEUE, QUEUE, null, true, false, false, null, null, null, null, null), server.getNodeID()); server.getStorageManager().addQueueBinding(txID, newBinding); server.getStorageManager().commitBindings(txID); diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/InterruptedLargeMessageTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/InterruptedLargeMessageTest.java index 9db1ff1867..0fb5ab2586 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/InterruptedLargeMessageTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/InterruptedLargeMessageTest.java @@ -506,6 +506,7 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase PageSubscription pageSubscription, boolean durable, boolean temporary, + boolean autoCreated, ScheduledExecutorService scheduledExecutor, PostOffice postOffice, StorageManager storageManager, @@ -519,6 +520,7 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase pageSubscription, durable, temporary, + autoCreated, scheduledExecutor, postOffice, storageManager, @@ -570,7 +572,8 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase Filter filter, PageSubscription pageSubscription, boolean durable, - boolean temporary) + boolean temporary, + boolean autoCreated) { return new NoPostACKQueue(persistenceID, @@ -580,6 +583,7 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase pageSubscription, durable, temporary, + autoCreated, scheduledExecutor, postOffice, storageManager, diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/PagingOrderTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/PagingOrderTest.java index a77ee945ba..fd2591f179 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/PagingOrderTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/client/PagingOrderTest.java @@ -749,7 +749,9 @@ public class PagingOrderTest extends ServiceTestBase "PAGE", -1, 10, - "KILL"); + "KILL", + true, + true); ActiveMQJMSConnectionFactory cf = (ActiveMQJMSConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY)); @@ -824,7 +826,9 @@ public class PagingOrderTest extends ServiceTestBase "PAGE", -1, 10, - "KILL"); + "KILL", + true, + true); jmsServer.createQueue(true, "Q1", null, true, "/queue/Q1"); diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/jms/client/TopicCleanupTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/jms/client/TopicCleanupTest.java index bd264ec6d9..55cd607e9f 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/jms/client/TopicCleanupTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/jms/client/TopicCleanupTest.java @@ -82,7 +82,7 @@ public class TopicCleanupTest extends JMSTestBase { long txid = storage.generateID(); - final Queue queue = new QueueImpl(storage.generateID(), SimpleString.toSimpleString("jms.topic.topic"), SimpleString.toSimpleString("jms.topic.topic"), FilterImpl.createFilter(ActiveMQServerImpl.GENERIC_IGNORED_FILTER), true, false, server.getScheduledPool(), server.getPostOffice(), + final Queue queue = new QueueImpl(storage.generateID(), SimpleString.toSimpleString("jms.topic.topic"), SimpleString.toSimpleString("jms.topic.topic"), FilterImpl.createFilter(ActiveMQServerImpl.GENERIC_IGNORED_FILTER), true, false, false, server.getScheduledPool(), server.getPostOffice(), storage, server.getAddressSettingsRepository(), server.getExecutorFactory().getExecutor()); LocalQueueBinding binding = new LocalQueueBinding(queue.getAddress(), queue, server.getNodeID()); diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/jms/jms2client/NonExistentQueueTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/jms/jms2client/NonExistentQueueTest.java index 1f3db36f20..e632d65020 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/jms/jms2client/NonExistentQueueTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/jms/jms2client/NonExistentQueueTest.java @@ -62,7 +62,7 @@ public class NonExistentQueueTest extends JMSTestBase @Test public void sendToNonExistantDestination() throws Exception { - Destination destination = ActiveMQJMSClient.createQueue("DoesNotExist"); + Destination destination = ActiveMQJMSClient.createTopic("DoesNotExist"); TransportConfiguration transportConfiguration = new TransportConfiguration(InVMConnectorFactory.class.getName()); ConnectionFactory localConnectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration); diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/management/ActiveMQServerControlTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/management/ActiveMQServerControlTest.java index a795e35242..3016d055fd 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/management/ActiveMQServerControlTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/management/ActiveMQServerControlTest.java @@ -507,6 +507,8 @@ public class ActiveMQServerControlTest extends ManagementTestBase long slowConsumerThreshold = 5; long slowConsumerCheckPeriod = 10; String slowConsumerPolicy = SlowConsumerPolicy.KILL.toString(); + boolean autoCreateJmsQueues = false; + boolean autoDeleteJmsQueues = false; serverControl.addAddressSettings(addressMatch, DLA, @@ -525,7 +527,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase addressFullMessagePolicy, slowConsumerThreshold, slowConsumerCheckPeriod, - slowConsumerPolicy); + slowConsumerPolicy, + autoCreateJmsQueues, + autoDeleteJmsQueues); boolean ex = false; @@ -548,7 +552,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase addressFullMessagePolicy, slowConsumerThreshold, slowConsumerCheckPeriod, - slowConsumerPolicy); + slowConsumerPolicy, + autoCreateJmsQueues, + autoDeleteJmsQueues); } catch (Exception expected) { @@ -578,6 +584,8 @@ public class ActiveMQServerControlTest extends ManagementTestBase assertEquals(slowConsumerThreshold, info.getSlowConsumerThreshold()); assertEquals(slowConsumerCheckPeriod, info.getSlowConsumerCheckPeriod()); assertEquals(slowConsumerPolicy, info.getSlowConsumerPolicy()); + assertEquals(autoCreateJmsQueues, info.isAutoCreateJmsQueues()); + assertEquals(autoDeleteJmsQueues, info.isAutoDeleteJmsQueues()); serverControl.addAddressSettings(addressMatch, DLA, @@ -596,7 +604,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase addressFullMessagePolicy, slowConsumerThreshold, slowConsumerCheckPeriod, - slowConsumerPolicy); + slowConsumerPolicy, + autoCreateJmsQueues, + autoDeleteJmsQueues); jsonString = serverControl.getAddressSettingsAsJSON(exactAddress); @@ -618,6 +628,8 @@ public class ActiveMQServerControlTest extends ManagementTestBase assertEquals(slowConsumerThreshold, info.getSlowConsumerThreshold()); assertEquals(slowConsumerCheckPeriod, info.getSlowConsumerCheckPeriod()); assertEquals(slowConsumerPolicy, info.getSlowConsumerPolicy()); + assertEquals(autoCreateJmsQueues, info.isAutoCreateJmsQueues()); + assertEquals(autoDeleteJmsQueues, info.isAutoDeleteJmsQueues()); ex = false; @@ -640,7 +652,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase addressFullMessagePolicy, slowConsumerThreshold, slowConsumerCheckPeriod, - slowConsumerPolicy); + slowConsumerPolicy, + autoCreateJmsQueues, + autoDeleteJmsQueues); } catch (Exception e) { diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/management/ActiveMQServerControlUsingCoreTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/management/ActiveMQServerControlUsingCoreTest.java index cd54124a82..019689fc8d 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/management/ActiveMQServerControlUsingCoreTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/management/ActiveMQServerControlUsingCoreTest.java @@ -582,7 +582,9 @@ public class ActiveMQServerControlUsingCoreTest extends ActiveMQServerControlTes @Parameter(desc = "the policy to use when the address is full", name = "addressFullMessagePolicy") String addressFullMessagePolicy, @Parameter(desc = "when a consumer falls below this threshold in terms of messages consumed per second it will be considered 'slow'", name = "slowConsumerThreshold") long slowConsumerThreshold, @Parameter(desc = "how often (in seconds) to check for slow consumers", name = "slowConsumerCheckPeriod") long slowConsumerCheckPeriod, - @Parameter(desc = "the policy to use when a slow consumer is detected", name = "slowConsumerPolicy") String slowConsumerPolicy) throws Exception + @Parameter(desc = "the policy to use when a slow consumer is detected", name = "slowConsumerPolicy") String slowConsumerPolicy, + @Parameter(desc = "allow queues to be created automatically", name = "autoCreateJmsQueues") boolean autoCreateJmsQueues, + @Parameter(desc = "allow auto-created queues to be deleted automatically", name = "autoDeleteJmsQueues") boolean autoDeleteJmsQueues) throws Exception { proxy.invokeOperation("addAddressSettings", addressMatch, @@ -602,7 +604,9 @@ public class ActiveMQServerControlUsingCoreTest extends ActiveMQServerControlTes addressFullMessagePolicy, slowConsumerThreshold, slowConsumerCheckPeriod, - slowConsumerPolicy); + slowConsumerPolicy, + autoCreateJmsQueues, + autoDeleteJmsQueues); } public void removeAddressSettings(String addressMatch) throws Exception diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/persistence/ExportFormatTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/persistence/ExportFormatTest.java index b905e46c10..fbd9e746c6 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/persistence/ExportFormatTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/tests/integration/persistence/ExportFormatTest.java @@ -16,6 +16,7 @@ */ package org.apache.activemq.tests.integration.persistence; +import org.junit.Ignore; import org.junit.Test; import java.io.StringReader; @@ -47,37 +48,40 @@ public class ExportFormatTest extends ServiceTestBase // Case the format was changed, and the change was agreed, use _testCreateFormat to recreate this field String bindingsFile = "#File,JournalFileImpl: (activemq-bindings-1.bindings id = 1, recordID = 1)\n" + - "operation@AddRecord,id@2,userRecordType@24,length@8,isUpdate@false,compactCount@0,data@AAAAAH____8=\n" + - "operation@AddRecord,id@2,userRecordType@21,length@17,isUpdate@false,compactCount@0,data@AAAABEEAMQAAAAAEQQAxAAA=\n" + - "operation@AddRecord,id@20,userRecordType@24,length@8,isUpdate@false,compactCount@0,data@AAAAAAAAABQ=\n" + - "#File,JournalFileImpl: (activemq-bindings-2.bindings id = 2, recordID = 2)"; + "operation@AddRecord,id@2,userRecordType@24,length@8,isUpdate@false,compactCount@0,data@AAAAAH____8=\n" + + "operation@AddRecordTX,txID@2,id@3,userRecordType@21,length@18,isUpdate@false,compactCount@0,data@AAAABEEAMQAAAAAEQQAxAAAA\n" + + "operation@Commit,txID@2,numberOfRecords@1\n" + + "operation@AddRecord,id@20,userRecordType@24,length@8,isUpdate@false,compactCount@0,data@AAAAAAAAABQ=\n" + + "#File,JournalFileImpl: (activemq-bindings-2.bindings id = 2, recordID = 2)"; // Case the format was changed, and the change was agreed, use _testCreateFormat to recreate this field String journalFile = "#File,JournalFileImpl: (activemq-data-1.amq id = 1, recordID = 1)\n" + - "operation@AddRecordTX,txID@0,id@4,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABAEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP40EAQAAAAEAAAAGawBlAHkABgAAAAA=\n" + - "operation@UpdateTX,txID@0,id@4,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "operation@AddRecordTX,txID@0,id@5,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP5EEAQAAAAEAAAAGawBlAHkABgAAAAE=\n" + - "operation@UpdateTX,txID@0,id@5,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "operation@AddRecordTX,txID@0,id@6,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABgEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP5EEAQAAAAEAAAAGawBlAHkABgAAAAI=\n" + - "operation@UpdateTX,txID@0,id@6,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "operation@AddRecordTX,txID@0,id@7,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABwEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP5EEAQAAAAEAAAAGawBlAHkABgAAAAM=\n" + - "operation@UpdateTX,txID@0,id@7,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "operation@AddRecordTX,txID@0,id@8,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAACAEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP5EEAQAAAAEAAAAGawBlAHkABgAAAAQ=\n" + - "operation@UpdateTX,txID@0,id@8,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "operation@Commit,txID@0,numberOfRecords@10\n" + - "operation@AddRecord,id@12,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADAEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP6gEAQAAAAEAAAAGawBlAHkABgAAAAU=\n" + - "operation@Update,id@12,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "operation@AddRecord,id@13,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP6oEAQAAAAEAAAAGawBlAHkABgAAAAY=\n" + - "operation@Update,id@13,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "operation@AddRecord,id@14,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADgEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP6sEAQAAAAEAAAAGawBlAHkABgAAAAc=\n" + - "operation@Update,id@14,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "operation@AddRecord,id@15,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADwEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP60EAQAAAAEAAAAGawBlAHkABgAAAAg=\n" + - "operation@Update,id@15,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "operation@AddRecord,id@16,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAAEAEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP64EAQAAAAEAAAAGawBlAHkABgAAAAk=\n" + - "operation@Update,id@16,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + - "#File,JournalFileImpl: (activemq-data-2.amq id = 2, recordID = 2)"; + "operation@AddRecordTX,txID@0,id@5,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfYEAQAAAAEAAAAGawBlAHkABgAAAAA=\n" + + "operation@UpdateTX,txID@0,id@5,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "operation@AddRecordTX,txID@0,id@6,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABgEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfoEAQAAAAEAAAAGawBlAHkABgAAAAE=\n" + + "operation@UpdateTX,txID@0,id@6,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "operation@AddRecordTX,txID@0,id@7,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABwEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfoEAQAAAAEAAAAGawBlAHkABgAAAAI=\n" + + "operation@UpdateTX,txID@0,id@7,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "operation@AddRecordTX,txID@0,id@8,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAACAEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfoEAQAAAAEAAAAGawBlAHkABgAAAAM=\n" + + "operation@UpdateTX,txID@0,id@8,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "operation@AddRecordTX,txID@0,id@9,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAACQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfoEAQAAAAEAAAAGawBlAHkABgAAAAQ=\n" + + "operation@UpdateTX,txID@0,id@9,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "operation@Commit,txID@0,numberOfRecords@10\n" + + "operation@AddRecord,id@13,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2Cg0EAQAAAAEAAAAGawBlAHkABgAAAAU=\n" + + "operation@Update,id@13,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "operation@AddRecord,id@14,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADgEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2Cg8EAQAAAAEAAAAGawBlAHkABgAAAAY=\n" + + "operation@Update,id@14,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "operation@AddRecord,id@15,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADwEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2ChMEAQAAAAEAAAAGawBlAHkABgAAAAc=\n" + + "operation@Update,id@15,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "operation@AddRecord,id@16,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAAEAEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2ChcEAQAAAAEAAAAGawBlAHkABgAAAAg=\n" + + "operation@Update,id@16,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "operation@AddRecord,id@17,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAAEQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2ChoEAQAAAAEAAAAGawBlAHkABgAAAAk=\n" + + "operation@Update,id@17,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" + + "#File,JournalFileImpl: (activemq-data-2.amq id = 2, recordID = 2)"; - public void _testCreateFormat() throws Exception + @Test + @Ignore // use this to recreate the format above. Notice we can't change the record format between releases + public void testCreateFormat() throws Exception { ActiveMQServer server = createServer(true); server.start(); @@ -86,7 +90,7 @@ public class ExportFormatTest extends ServiceTestBase ClientSessionFactory factory = createSessionFactory(locator); ClientSession session = factory.createSession(false, false, false); - session.createQueue("A1", "A1"); + session.createQueue("A1", "A1", true); ClientProducer producer = session.createProducer("A1"); for (int i = 0; i < 5; i++) diff --git a/tests/jms-tests/src/test/java/org/apache/activemq/jms/tests/SessionTest.java b/tests/jms-tests/src/test/java/org/apache/activemq/jms/tests/SessionTest.java index c062fe8339..5c686cbbdf 100644 --- a/tests/jms-tests/src/test/java/org/apache/activemq/jms/tests/SessionTest.java +++ b/tests/jms-tests/src/test/java/org/apache/activemq/jms/tests/SessionTest.java @@ -34,6 +34,7 @@ import javax.jms.XAConnection; import javax.jms.XASession; import org.apache.activemq.api.jms.JMSFactoryType; +import org.apache.activemq.core.settings.impl.AddressSettings; import org.apache.activemq.jms.tests.util.ProxyAssertSupport; import org.junit.Test; @@ -113,6 +114,10 @@ public class SessionTest extends ActiveMQServerTestCase @Test public void testCreateNonExistentQueue() throws Exception { + AddressSettings addressSettings = new AddressSettings(); + addressSettings.setAutoCreateJmsQueues(false); + getJmsServer().getAddressSettingsRepository().addMatch("#", addressSettings); + Connection conn = getConnectionFactory().createConnection(); Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); try @@ -147,6 +152,10 @@ public class SessionTest extends ActiveMQServerTestCase @Test public void testCreateQueueWhileTopicWithSameNameExists() throws Exception { + AddressSettings addressSettings = new AddressSettings(); + addressSettings.setAutoCreateJmsQueues(false); + getJmsServer().getAddressSettingsRepository().addMatch("#", addressSettings); + Connection conn = getConnectionFactory().createConnection(); Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); try diff --git a/tests/timing-tests/src/test/java/org/apache/activemq/tests/timing/core/server/impl/QueueImplTest.java b/tests/timing-tests/src/test/java/org/apache/activemq/tests/timing/core/server/impl/QueueImplTest.java index c2fb1ac8d0..e8bbf9513d 100644 --- a/tests/timing-tests/src/test/java/org/apache/activemq/tests/timing/core/server/impl/QueueImplTest.java +++ b/tests/timing-tests/src/test/java/org/apache/activemq/tests/timing/core/server/impl/QueueImplTest.java @@ -81,6 +81,7 @@ public class QueueImplTest extends UnitTestCase null, false, true, + false, scheduledExecutor, null, null, @@ -158,6 +159,7 @@ public class QueueImplTest extends UnitTestCase null, false, true, + false, scheduledExecutor, null, null, @@ -273,6 +275,7 @@ public class QueueImplTest extends UnitTestCase null, false, true, + false, scheduledExecutor, null, null, diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/postoffice/impl/FakeQueue.java b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/postoffice/impl/FakeQueue.java index b88ee6ea6e..1be23eaa93 100644 --- a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/postoffice/impl/FakeQueue.java +++ b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/postoffice/impl/FakeQueue.java @@ -25,7 +25,6 @@ import org.apache.activemq.api.core.SimpleString; import org.apache.activemq.core.filter.Filter; import org.apache.activemq.core.paging.cursor.PageSubscription; import org.apache.activemq.core.server.Consumer; -import org.apache.activemq.core.server.ActiveMQServer; import org.apache.activemq.core.server.MessageReference; import org.apache.activemq.core.server.Queue; import org.apache.activemq.core.server.RoutingContext; @@ -60,7 +59,7 @@ public class FakeQueue implements Queue } @Override - public void setConsumersRefCount(ActiveMQServer server) + public void setConsumersRefCount(ReferenceCounter referenceCounter) { } @@ -427,6 +426,12 @@ public class FakeQueue implements Queue return false; } + @Override + public boolean isAutoCreated() + { + return false; + } + @Override public LinkedListIterator iterator() { diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/QueueImplTest.java b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/QueueImplTest.java index f2e776d73f..a71e97f66e 100644 --- a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/QueueImplTest.java +++ b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/QueueImplTest.java @@ -94,17 +94,7 @@ public class QueueImplTest extends UnitTestCase { final SimpleString name = new SimpleString("oobblle"); - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - name, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getNamedQueue(name); Assert.assertEquals(name, queue.getName()); } @@ -112,31 +102,11 @@ public class QueueImplTest extends UnitTestCase @Test public void testDurable() { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - false, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getNonDurableQueue(); Assert.assertFalse(queue.isDurable()); - queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - true, - false, - scheduledExecutor, - null, - null, - null, - executor); + queue = getDurableQueue(); Assert.assertTrue(queue.isDurable()); } @@ -150,17 +120,7 @@ public class QueueImplTest extends UnitTestCase Consumer cons3 = new FakeConsumer(); - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); Assert.assertEquals(0, queue.getConsumerCount()); @@ -202,17 +162,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testGetFilter() { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); Assert.assertNull(queue.getFilter()); @@ -229,17 +179,7 @@ public class QueueImplTest extends UnitTestCase } }; - queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - filter, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + queue = getFilteredQueue(filter); Assert.assertEquals(filter, queue.getFilter()); @@ -248,17 +188,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testSimpleadd() { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); final int numMessages = 10; @@ -278,17 +208,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testRate() throws InterruptedException { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); final int numMessages = 10; @@ -309,17 +229,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testSimpleNonDirectDelivery() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); final int numMessages = 10; @@ -358,17 +268,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testBusyConsumer() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); FakeConsumer consumer = new FakeConsumer(); @@ -413,17 +313,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testBusyConsumerThenAddMoreMessages() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); FakeConsumer consumer = new FakeConsumer(); @@ -491,17 +381,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testaddHeadadd() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); final int numMessages = 10; @@ -556,17 +436,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testChangeConsumersAndDeliver() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - new FakePostOffice(), - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); final int numMessages = 10; @@ -730,17 +600,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testRoundRobinWithQueueing() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); final int numMessages = 10; @@ -793,17 +653,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testWithPriorities() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); final int numMessages = 10; @@ -856,17 +706,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testConsumerWithFilterAddAndRemove() { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); Filter filter = new FakeFilter("fruit", "orange"); @@ -876,17 +716,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testIterator() { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); final int numMessages = 20; @@ -925,17 +755,7 @@ public class QueueImplTest extends UnitTestCase public void testConsumeWithFiltersAddAndRemoveConsumer() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - new FakePostOffice(), - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); Filter filter = new FakeFilter("fruit", "orange"); @@ -1009,17 +829,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testBusyConsumerWithFilterFirstCallBusy() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); FakeConsumer consumer = new FakeConsumer(FilterImpl.createFilter("color = 'green'")); @@ -1061,17 +871,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testBusyConsumerWithFilterThenAddMoreMessages() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); FakeConsumer consumer = new FakeConsumer(FilterImpl.createFilter("color = 'green'")); @@ -1146,17 +946,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testConsumerWithFilterThenAddMoreMessages() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); final int numMessages = 10; List refs = new ArrayList(); @@ -1220,17 +1010,7 @@ public class QueueImplTest extends UnitTestCase private void testConsumerWithFilters(final boolean direct) throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - new FakePostOffice(), - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); Filter filter = new FakeFilter("fruit", "orange"); @@ -1323,17 +1103,7 @@ public class QueueImplTest extends UnitTestCase public void testMessageOrder() throws Exception { FakeConsumer consumer = new FakeConsumer(); - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference2 = generateReference(queue, 2); MessageReference messageReference3 = generateReference(queue, 3); @@ -1354,17 +1124,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testMessagesAdded() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference2 = generateReference(queue, 2); MessageReference messageReference3 = generateReference(queue, 3); @@ -1377,17 +1137,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testGetReference() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference2 = generateReference(queue, 2); MessageReference messageReference3 = generateReference(queue, 3); @@ -1401,17 +1151,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testGetNonExistentReference() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference2 = generateReference(queue, 2); MessageReference messageReference3 = generateReference(queue, 3); @@ -1430,17 +1170,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testPauseAndResumeWithAsync() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); // pauses the queue queue.pause(); @@ -1498,17 +1228,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testPauseAndResumeWithDirect() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); // Now add a consumer FakeConsumer consumer = new FakeConsumer(); @@ -1553,17 +1273,7 @@ public class QueueImplTest extends UnitTestCase @Test public void testResetMessagesAdded() throws Exception { - QueueImpl queue = new QueueImpl(1, - QueueImplTest.address1, - QueueImplTest.queue1, - null, - false, - true, - scheduledExecutor, - null, - null, - null, - executor); + QueueImpl queue = getTemporaryQueue(); MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference2 = generateReference(queue, 2); queue.addTail(messageReference); @@ -1668,4 +1378,45 @@ public class QueueImplTest extends UnitTestCase server.stop(); } } + + private QueueImpl getNonDurableQueue() + { + return getQueue(QueueImplTest.queue1, false, false, null); + } + + private QueueImpl getDurableQueue() + { + return getQueue(QueueImplTest.queue1, true, false, null); + } + + private QueueImpl getNamedQueue(SimpleString name) + { + return getQueue(name, false, true, null); + } + + private QueueImpl getFilteredQueue(Filter filter) + { + return getQueue(QueueImplTest.queue1, false, true, filter); + } + + private QueueImpl getTemporaryQueue() + { + return getQueue(QueueImplTest.queue1, false, true, null); + } + + private QueueImpl getQueue(SimpleString name, boolean durable, boolean temporary, Filter filter) + { + return new QueueImpl(1, + QueueImplTest.address1, + name, + filter, + durable, + temporary, + false, + scheduledExecutor, + new FakePostOffice(), + null, + null, + executor); + } } diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/fakes/FakeQueueFactory.java b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/fakes/FakeQueueFactory.java index 3bc337d3a3..1b4da2cdda 100644 --- a/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/fakes/FakeQueueFactory.java +++ b/tests/unit-tests/src/test/java/org/apache/activemq/tests/unit/core/server/impl/fakes/FakeQueueFactory.java @@ -49,7 +49,8 @@ public class FakeQueueFactory implements QueueFactory final Filter filter, final PageSubscription subscription, final boolean durable, - final boolean temporary) + final boolean temporary, + final boolean autoCreated) { return new QueueImpl(persistenceID, address, @@ -58,6 +59,7 @@ public class FakeQueueFactory implements QueueFactory subscription, durable, temporary, + autoCreated, scheduledExecutor, postOffice, null, From 41fed219c015080558703601e67098edbecc84fe Mon Sep 17 00:00:00 2001 From: Andy Taylor Date: Tue, 13 Jan 2015 10:37:47 +0000 Subject: [PATCH 6/8] added data dir exclude for Rat plugin --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 0f861f7805..cee5074952 100644 --- a/pom.xml +++ b/pom.xml @@ -916,6 +916,7 @@ etc/org.eclipse.* docs/user-manual/en/*.json **/target/ + **/data/ **/*.bindings **/*.lock **/META-INF/services/* From 5595e0a9fc2ef613beede95676b85417bbdf379d Mon Sep 17 00:00:00 2001 From: Andy Taylor Date: Tue, 13 Jan 2015 15:07:41 +0000 Subject: [PATCH 7/8] fix maven plugin to wait until stop thread has been called by making thread non deamon --- .../main/java/org/apache/activemq/server/ActiveMQBootstrap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activemq-maven-plugin/src/main/java/org/apache/activemq/server/ActiveMQBootstrap.java b/activemq-maven-plugin/src/main/java/org/apache/activemq/server/ActiveMQBootstrap.java index 49b16c89b4..ae7ecfb8e2 100644 --- a/activemq-maven-plugin/src/main/java/org/apache/activemq/server/ActiveMQBootstrap.java +++ b/activemq-maven-plugin/src/main/java/org/apache/activemq/server/ActiveMQBootstrap.java @@ -135,7 +135,7 @@ public class ActiveMQBootstrap { restartFile.delete(); } - final Timer timer = new Timer("ActiveMQ Server Shutdown Timer", true); + final Timer timer = new Timer("ActiveMQ Server Shutdown Timer", false); timer.scheduleAtFixedRate(new ServerStopTimerTask(stopFile, killFile, restartFile, timer), 500, 500); } } From 2c61399b1138e7b18fc1e8868dc684a0369c3cd7 Mon Sep 17 00:00:00 2001 From: Andy Taylor Date: Tue, 13 Jan 2015 15:51:16 +0000 Subject: [PATCH 8/8] example fixes --- .../org/apache/activemq/jms/example/EmbeddedExample.java | 1 - .../activemq/jms/example/SymmetricClusterExample.java | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/jms/embedded-simple/src/main/java/org/apache/activemq/jms/example/EmbeddedExample.java b/examples/jms/embedded-simple/src/main/java/org/apache/activemq/jms/example/EmbeddedExample.java index 05f227cdab..8ef78faf0e 100644 --- a/examples/jms/embedded-simple/src/main/java/org/apache/activemq/jms/example/EmbeddedExample.java +++ b/examples/jms/embedded-simple/src/main/java/org/apache/activemq/jms/example/EmbeddedExample.java @@ -57,7 +57,6 @@ public class EmbeddedExample extends ActiveMQExample System.out.println("Started Embedded JMS Server"); JMSServerManager jmsServerManager = jmsServer.getJMSServerManager(); - jmsServerManager.addQueueToJndi("exampleQueue", "queue/exampleQueue"); List connectors = new ArrayList(); connectors.add("in-vm"); jmsServerManager.createConnectionFactory("ConnectionFactory", false, JMSFactoryType.CF, connectors, "ConnectionFactory"); diff --git a/examples/jms/symmetric-cluster/src/main/java/org/apache/activemq/jms/example/SymmetricClusterExample.java b/examples/jms/symmetric-cluster/src/main/java/org/apache/activemq/jms/example/SymmetricClusterExample.java index de4eb5e2c6..235226a49f 100644 --- a/examples/jms/symmetric-cluster/src/main/java/org/apache/activemq/jms/example/SymmetricClusterExample.java +++ b/examples/jms/symmetric-cluster/src/main/java/org/apache/activemq/jms/example/SymmetricClusterExample.java @@ -82,8 +82,10 @@ public class SymmetricClusterExample extends ActiveMQExample // connection factory directly we avoid having to worry about a JNDI look-up. // In an app server environment you could use HA-JNDI to lookup from the clustered JNDI servers without // having to know about a specific one. - UDPBroadcastGroupConfiguration udpCfg = new UDPBroadcastGroupConfiguration("231.7.7.7", 9876, null, -1); - DiscoveryGroupConfiguration groupConfiguration = new DiscoveryGroupConfiguration(ActiveMQClient.DEFAULT_DISCOVERY_INITIAL_WAIT_TIMEOUT, ActiveMQClient.DEFAULT_DISCOVERY_INITIAL_WAIT_TIMEOUT, udpCfg); + UDPBroadcastGroupConfiguration udpCfg = new UDPBroadcastGroupConfiguration(); + udpCfg.setGroupAddress("231.7.7.7").setGroupPort(9876); + DiscoveryGroupConfiguration groupConfiguration = new DiscoveryGroupConfiguration(); + groupConfiguration.setBroadcastEndpointFactoryConfiguration(udpCfg); ConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithHA(groupConfiguration, JMSFactoryType.CF);