Merge branch #62

This commit is contained in:
Martyn Taylor 2015-01-14 12:08:22 +00:00
commit 260f579c18
101 changed files with 2075 additions and 1726 deletions

View File

@ -48,6 +48,12 @@ public interface ClientSession extends XAResource, AutoCloseable
* Returns the names of the queues bound to the binding. * Returns the names of the queues bound to the binding.
*/ */
List<SimpleString> getQueueNames(); List<SimpleString> getQueueNames();
/**
* Returns <code>true</code> if auto-creation for this address is enabled and if the address queried is for a JMS
* queue, <code>false</code> else.
*/
boolean isAutoCreateJmsQueues();
} }
/** /**
@ -81,6 +87,12 @@ public interface ClientSession extends XAResource, AutoCloseable
*/ */
boolean isDurable(); boolean isDurable();
/**
* Returns <code>true</code> if auto-creation for this queue is enabled and if the queue queried is a JMS queue,
* <code>false</code> else.
*/
boolean isAutoCreateJmsQueues();
/** /**
* Returns the number of consumers attached to the queue. * Returns the number of consumers attached to the queue.
*/ */

View File

@ -565,7 +565,9 @@ public interface ActiveMQServerControl
@Parameter(desc = "the policy to use when the address is full", name = "addressFullMessagePolicy") String addressFullMessagePolicy, @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 = "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 = "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; void removeAddressSettings(String addressMatch) throws Exception;

View File

@ -60,6 +60,10 @@ public final class AddressSettingsInfo
private final String slowConsumerPolicy; private final String slowConsumerPolicy;
private final boolean autoCreateJmsQueues;
private final boolean autoDeleteJmsQueues;
// Static -------------------------------------------------------- // Static --------------------------------------------------------
public static AddressSettingsInfo from(final String jsonString) throws Exception public static AddressSettingsInfo from(final String jsonString) throws Exception
@ -80,7 +84,9 @@ public final class AddressSettingsInfo
object.getBoolean("sendToDLAOnNoRoute"), object.getBoolean("sendToDLAOnNoRoute"),
object.getLong("slowConsumerThreshold"), object.getLong("slowConsumerThreshold"),
object.getLong("slowConsumerCheckPeriod"), object.getLong("slowConsumerCheckPeriod"),
object.getString("slowConsumerPolicy")); object.getString("slowConsumerPolicy"),
object.getBoolean("autoCreateJmsQueues"),
object.getBoolean("autoDeleteJmsQueues"));
} }
// Constructors -------------------------------------------------- // Constructors --------------------------------------------------
@ -100,7 +106,9 @@ public final class AddressSettingsInfo
boolean sendToDLAOnNoRoute, boolean sendToDLAOnNoRoute,
long slowConsumerThreshold, long slowConsumerThreshold,
long slowConsumerCheckPeriod, long slowConsumerCheckPeriod,
String slowConsumerPolicy) String slowConsumerPolicy,
boolean autoCreateJmsQueues,
boolean autoDeleteJmsQueues)
{ {
this.addressFullMessagePolicy = addressFullMessagePolicy; this.addressFullMessagePolicy = addressFullMessagePolicy;
this.maxSizeBytes = maxSizeBytes; this.maxSizeBytes = maxSizeBytes;
@ -118,6 +126,8 @@ public final class AddressSettingsInfo
this.slowConsumerThreshold = slowConsumerThreshold; this.slowConsumerThreshold = slowConsumerThreshold;
this.slowConsumerCheckPeriod = slowConsumerCheckPeriod; this.slowConsumerCheckPeriod = slowConsumerCheckPeriod;
this.slowConsumerPolicy = slowConsumerPolicy; this.slowConsumerPolicy = slowConsumerPolicy;
this.autoCreateJmsQueues = autoCreateJmsQueues;
this.autoDeleteJmsQueues = autoDeleteJmsQueues;
} }
// Public -------------------------------------------------------- // Public --------------------------------------------------------
@ -206,5 +216,15 @@ public final class AddressSettingsInfo
{ {
return slowConsumerPolicy; return slowConsumerPolicy;
} }
public boolean isAutoCreateJmsQueues()
{
return autoCreateJmsQueues;
}
public boolean isAutoDeleteJmsQueues()
{
return autoDeleteJmsQueues;
}
} }

View File

@ -24,15 +24,17 @@ import org.apache.activemq.api.core.client.ClientSession;
public class AddressQueryImpl implements ClientSession.AddressQuery, ClientSession.BindingQuery public class AddressQueryImpl implements ClientSession.AddressQuery, ClientSession.BindingQuery
{ {
private final boolean exists; private final boolean exists;
private final ArrayList<SimpleString> queueNames; private final ArrayList<SimpleString> queueNames;
public AddressQueryImpl(final boolean exists, final List<SimpleString> queueNames) private final boolean autoCreateJmsQueues;
public AddressQueryImpl(final boolean exists, final List<SimpleString> queueNames, final boolean autoCreateJmsQueues)
{ {
this.exists = exists; this.exists = exists;
this.queueNames = new ArrayList<SimpleString>(queueNames); this.queueNames = new ArrayList<SimpleString>(queueNames);
this.autoCreateJmsQueues = autoCreateJmsQueues;
} }
public List<SimpleString> getQueueNames() public List<SimpleString> getQueueNames()
@ -44,4 +46,9 @@ public class AddressQueryImpl implements ClientSession.AddressQuery, ClientSessi
{ {
return exists; return exists;
} }
public boolean isAutoCreateJmsQueues()
{
return autoCreateJmsQueues;
}
} }

View File

@ -38,6 +38,8 @@ public class QueueQueryImpl implements ClientSession.QueueQuery
private final SimpleString name; private final SimpleString name;
private final boolean autoCreateJmsQueues;
public QueueQueryImpl(final boolean durable, public QueueQueryImpl(final boolean durable,
final boolean temporary, final boolean temporary,
final int consumerCount, final int consumerCount,
@ -47,7 +49,19 @@ public class QueueQueryImpl implements ClientSession.QueueQuery
final SimpleString name, final SimpleString name,
final boolean exists) 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.durable = durable;
this.temporary = temporary; this.temporary = temporary;
this.consumerCount = consumerCount; this.consumerCount = consumerCount;
@ -56,6 +70,7 @@ public class QueueQueryImpl implements ClientSession.QueueQuery
this.address = address; this.address = address;
this.name = name; this.name = name;
this.exists = exists; this.exists = exists;
this.autoCreateJmsQueues = autoCreateJmsQueues;
} }
public SimpleString getName() public SimpleString getName()
@ -88,6 +103,11 @@ public class QueueQueryImpl implements ClientSession.QueueQuery
return durable; return durable;
} }
public boolean isAutoCreateJmsQueues()
{
return autoCreateJmsQueues;
}
public boolean isTemporary() public boolean isTemporary()
{ {
return temporary; return temporary;

View File

@ -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.SessionAcknowledgeMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionAddMetaDataMessageV2; 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.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.SessionCloseMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionConsumerCloseMessage; 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.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.SessionProducerCreditsFailMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionProducerCreditsMessage; 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.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.SessionReceiveContinuationMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionReceiveLargeMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionReceiveLargeMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionReceiveMessage; 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 public ClientSession.QueueQuery queueQuery(final SimpleString queueName) throws ActiveMQException
{ {
SessionQueueQueryMessage request = new SessionQueueQueryMessage(queueName); 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(); return response.toQueueQuery();
} }
public ClientConsumerInternal createConsumer(SimpleString queueName, SimpleString filterString, public ClientConsumerInternal createConsumer(SimpleString queueName, SimpleString filterString,
int windowSize, int maxRate, int ackBatchSize, boolean browseOnly, int windowSize, int maxRate, int ackBatchSize, boolean browseOnly,
Executor executor, Executor flowControlExecutor) throws ActiveMQException Executor executor, Executor flowControlExecutor) throws ActiveMQException
@ -252,7 +250,7 @@ public class ActiveMQSessionContext extends SessionContext
browseOnly, browseOnly,
true); 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 // The actual windows size that gets used is determined by the user since
// could be overridden on the queue settings // 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 public ClientSession.AddressQuery addressQuery(final SimpleString address) throws ActiveMQException
{ {
SessionBindingQueryResponseMessage response = SessionBindingQueryResponseMessage_V2 response =
(SessionBindingQueryResponseMessage) sessionChannel.sendBlocking(new SessionBindingQueryMessage(address), PacketImpl.SESS_BINDINGQUERY_RESP); (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());
} }

View File

@ -161,6 +161,10 @@ public final class ChannelImpl implements Channel
return version >= 125; return version >= 125;
case PacketImpl.DISCONNECT_V2: case PacketImpl.DISCONNECT_V2:
return version >= 125; return version >= 125;
case PacketImpl.SESS_QUEUEQUERY_RESP_V2:
return version >= 126;
case PacketImpl.SESS_BINDINGQUERY_RESP_V2:
return version >= 126;
default: default:
return true; return true;
} }

View File

@ -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_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;
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;
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_CLOSE;
import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_COMMIT; 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; 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_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;
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;
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_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_ROLLBACK;
import static org.apache.activemq.core.protocol.core.impl.PacketImpl.SESS_SEND_CONTINUATION; 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.SessionAddMetaDataMessageV2;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryMessage; 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;
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.SessionCloseMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionCommitMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionCommitMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionConsumerCloseMessage; 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.SessionProducerCreditsMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryMessage; 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;
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.SessionReceiveContinuationMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionRequestProducerCreditsMessage; 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.SessionSendContinuationMessage;
@ -251,6 +255,11 @@ public abstract class PacketDecoder implements Serializable
packet = new SessionQueueQueryResponseMessage(); packet = new SessionQueueQueryResponseMessage();
break; break;
} }
case SESS_QUEUEQUERY_RESP_V2:
{
packet = new SessionQueueQueryResponseMessage_V2();
break;
}
case CREATE_QUEUE: case CREATE_QUEUE:
{ {
packet = new CreateQueueMessage(); packet = new CreateQueueMessage();
@ -276,6 +285,11 @@ public abstract class PacketDecoder implements Serializable
packet = new SessionBindingQueryResponseMessage(); packet = new SessionBindingQueryResponseMessage();
break; break;
} }
case SESS_BINDINGQUERY_RESP_V2:
{
packet = new SessionBindingQueryResponseMessage_V2();
break;
}
case SESS_XA_START: case SESS_XA_START:
{ {
packet = new SessionXAStartMessage(); packet = new SessionXAStartMessage();

View File

@ -246,6 +246,10 @@ public class PacketImpl implements Packet
public static final byte SCALEDOWN_ANNOUNCEMENT = -6; 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 -------------------------------------------------------- // Static --------------------------------------------------------
public PacketImpl(final byte type) public PacketImpl(final byte type)

View File

@ -32,9 +32,9 @@ import org.apache.activemq.core.protocol.core.impl.PacketImpl;
*/ */
public class SessionBindingQueryResponseMessage extends PacketImpl public class SessionBindingQueryResponseMessage extends PacketImpl
{ {
private boolean exists; protected boolean exists;
private List<SimpleString> queueNames; protected List<SimpleString> queueNames;
public SessionBindingQueryResponseMessage(final boolean exists, final List<SimpleString> queueNames) public SessionBindingQueryResponseMessage(final boolean exists, final List<SimpleString> queueNames)
{ {
@ -50,6 +50,11 @@ public class SessionBindingQueryResponseMessage extends PacketImpl
super(SESS_BINDINGQUERY_RESP); super(SESS_BINDINGQUERY_RESP);
} }
public SessionBindingQueryResponseMessage(byte v2)
{
super(v2);
}
@Override @Override
public boolean isResponse() public boolean isResponse()
{ {

View File

@ -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<SimpleString> 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;
}
}

View File

@ -32,21 +32,21 @@ import org.apache.activemq.core.server.QueueQueryResult;
*/ */
public class SessionQueueQueryResponseMessage extends PacketImpl 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) public SessionQueueQueryResponseMessage(final QueueQueryResult result)
{ {
@ -59,6 +59,11 @@ public class SessionQueueQueryResponseMessage extends PacketImpl
this(null, null, false, false, null, 0, 0, false); this(null, null, false, false, null, 0, 0, false);
} }
public SessionQueueQueryResponseMessage(byte v2)
{
super(v2);
}
private SessionQueueQueryResponseMessage(final SimpleString name, private SessionQueueQueryResponseMessage(final SimpleString name,
final SimpleString address, final SimpleString address,
final boolean durable, final boolean durable,

View File

@ -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;
}
}

View File

@ -43,29 +43,28 @@ public class QueueQueryResult
private boolean temporary; private boolean temporary;
private boolean autoCreateJmsQueues;
public QueueQueryResult(final SimpleString name, public QueueQueryResult(final SimpleString name,
final SimpleString address, final SimpleString address,
final boolean durable, final boolean durable,
final boolean temporary, final boolean temporary,
final SimpleString filterString, final SimpleString filterString,
final int consumerCount, 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() public QueueQueryResult(final SimpleString name,
{
this(null, null, false, false, null, 0, 0, false);
}
private QueueQueryResult(final SimpleString name,
final SimpleString address, final SimpleString address,
final boolean durable, final boolean durable,
final boolean temporary, final boolean temporary,
final SimpleString filterString, final SimpleString filterString,
final int consumerCount, final int consumerCount,
final long messageCount, final long messageCount,
final boolean autoCreateJmsQueues,
final boolean exists) final boolean exists)
{ {
this.durable = durable; this.durable = durable;
@ -82,6 +81,8 @@ public class QueueQueryResult
this.name = name; this.name = name;
this.autoCreateJmsQueues = autoCreateJmsQueues;
this.exists = exists; this.exists = exists;
} }
@ -125,4 +126,9 @@ public class QueueQueryResult
return temporary; return temporary;
} }
public boolean isAutoCreateJmsQueues()
{
return autoCreateJmsQueues;
}
} }

View File

@ -28,7 +28,7 @@ import java.util.Iterator;
* *
* *
*/ */
public interface LinkedListIterator<E> extends Iterator<E> public interface LinkedListIterator<E> extends Iterator<E>, AutoCloseable
{ {
void repeat(); void repeat();

View File

@ -21,4 +21,4 @@ activemq.version.microVersion=${activemq.version.microVersion}
activemq.version.incrementingVersion=${activemq.version.incrementingVersion} activemq.version.incrementingVersion=${activemq.version.incrementingVersion}
activemq.version.versionSuffix=${activemq.version.versionSuffix} activemq.version.versionSuffix=${activemq.version.versionSuffix}
activemq.version.versionTag=${activemq.version.versionTag} activemq.version.versionTag=${activemq.version.versionTag}
activemq.version.compatibleVersionList=121,122,123,124,125 activemq.version.compatibleVersionList=121,122,123,124,125,126

View File

@ -415,7 +415,14 @@ public class ActiveMQMessageProducer implements MessageProducer, QueueSender, To
ClientSession.AddressQuery query = clientSession.addressQuery(address); ClientSession.AddressQuery query = clientSession.addressQuery(address);
if (!query.isExists()) 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 else
{ {

View File

@ -326,7 +326,14 @@ public class ActiveMQSession implements QueueSession, TopicSession
if (!response.isExists()) 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()); connection.addKnownDestination(jbd.getSimpleAddress());
@ -730,7 +737,14 @@ public class ActiveMQSession implements QueueSession, TopicSession
if (!response.isExists()) 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()); connection.addKnownDestination(dest.getSimpleAddress());
@ -902,10 +916,17 @@ public class ActiveMQSession implements QueueSession, TopicSession
try try
{ {
AddressQuery message = session.addressQuery(new SimpleString(jbq.getAddress())); AddressQuery response = session.addressQuery(new SimpleString(jbq.getAddress()));
if (!message.isExists()) 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) catch (ActiveMQException e)
@ -1239,13 +1260,13 @@ public class ActiveMQSession implements QueueSession, TopicSession
QueueQuery response = session.queueQuery(queue.getSimpleAddress()); QueueQuery response = session.queueQuery(queue.getSimpleAddress());
if (response.isExists()) if (!response.isExists() && !response.isAutoCreateJmsQueues())
{ {
return queue; return null;
} }
else else
{ {
return null; return queue;
} }
} }

View File

@ -135,7 +135,7 @@ public class ActiveMQBootstrap
{ {
restartFile.delete(); 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); timer.scheduleAtFixedRate(new ServerStopTimerTask(stopFile, killFile, restartFile, timer), 500, 500);
} }
} }

View File

@ -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 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 ---------------------------------------------------- // Attributes ----------------------------------------------------
private boolean validateAIO = false; private boolean validateAIO = false;
@ -1139,6 +1143,14 @@ public final class FileConfigurationParser extends XMLConfigurationUtil
SlowConsumerPolicy policy = Enum.valueOf(SlowConsumerPolicy.class, value); SlowConsumerPolicy policy = Enum.valueOf(SlowConsumerPolicy.class, value);
addressSettings.setSlowConsumerPolicy(policy); 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; return setting;
} }

View File

@ -1635,6 +1635,8 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active
policy = addressSettings.getSlowConsumerPolicy() == SlowConsumerPolicy.NOTIFY ? "NOTIFY" policy = addressSettings.getSlowConsumerPolicy() == SlowConsumerPolicy.NOTIFY ? "NOTIFY"
: "KILL"; : "KILL";
settings.put("slowConsumerPolicy", policy); settings.put("slowConsumerPolicy", policy);
settings.put("autoCreateJmsQueues", addressSettings.isAutoCreateJmsQueues());
settings.put("autoDeleteJmsQueues", addressSettings.isAutoDeleteJmsQueues());
JSONObject jsonObject = new JSONObject(settings); JSONObject jsonObject = new JSONObject(settings);
return jsonObject.toString(); return jsonObject.toString();
@ -1658,7 +1660,9 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active
final String addressFullMessagePolicy, final String addressFullMessagePolicy,
final long slowConsumerThreshold, final long slowConsumerThreshold,
final long slowConsumerCheckPeriod, final long slowConsumerCheckPeriod,
final String slowConsumerPolicy) throws Exception final String slowConsumerPolicy,
final boolean autoCreateJmsQueues,
final boolean autoDeleteJmsQueues) throws Exception
{ {
checkStarted(); checkStarted();
@ -1721,6 +1725,8 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active
{ {
addressSettings.setSlowConsumerPolicy(SlowConsumerPolicy.KILL); addressSettings.setSlowConsumerPolicy(SlowConsumerPolicy.KILL);
} }
addressSettings.setAutoCreateJmsQueues(autoCreateJmsQueues);
addressSettings.setAutoDeleteJmsQueues(autoDeleteJmsQueues);
server.getAddressSettingsRepository().addMatch(address, addressSettings); server.getAddressSettingsRepository().addMatch(address, addressSettings);
storageManager.storeAddressSetting(new PersistedAddressSetting(new SimpleString(address), addressSettings)); storageManager.storeAddressSetting(new PersistedAddressSetting(new SimpleString(address), addressSettings));

View File

@ -1247,6 +1247,8 @@ final class PageSubscriptionImpl implements PageSubscription
private volatile boolean isredelivery = false; private volatile boolean isredelivery = false;
private PagedReference currentDelivery = null;
private volatile PagedReference lastRedelivery = null; private volatile PagedReference lastRedelivery = null;
// We only store the position for redeliveries. They will be read from the SoftCache again during delivery. // 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) if (cachedNext != null)
{ {
PagedReference retPos = cachedNext; currentDelivery = cachedNext;
cachedNext = null; cachedNext = null;
return retPos; return currentDelivery;
} }
try try
@ -1310,7 +1312,8 @@ final class PageSubscriptionImpl implements PageSubscription
position = getStartPosition(); position = getStartPosition();
} }
return moveNext(); currentDelivery = moveNext();
return currentDelivery;
} }
catch (RuntimeException e) catch (RuntimeException e)
{ {
@ -1473,10 +1476,13 @@ final class PageSubscriptionImpl implements PageSubscription
public void remove() public void remove()
{ {
deliveredCount.incrementAndGet(); deliveredCount.incrementAndGet();
PageCursorInfo info = PageSubscriptionImpl.this.getPageInfo(position); if (currentDelivery != null)
if (info != null)
{ {
info.remove(position); PageCursorInfo info = PageSubscriptionImpl.this.getPageInfo(currentDelivery.getPosition());
if (info != null)
{
info.remove(currentDelivery.getPosition());
}
} }
} }

View File

@ -43,4 +43,6 @@ public interface QueueBindingInfo
SimpleString getFilterString(); SimpleString getFilterString();
boolean isAutoCreated();
} }

View File

@ -2014,7 +2014,8 @@ public class JournalStorageManager implements StorageManager
PersistentQueueBindingEncoding bindingEncoding = new PersistentQueueBindingEncoding(queue.getName(), PersistentQueueBindingEncoding bindingEncoding = new PersistentQueueBindingEncoding(queue.getName(),
binding.getAddress(), binding.getAddress(),
filterString); filterString,
queue.isAutoCreated());
readLock(); readLock();
try try
@ -3027,6 +3028,8 @@ public class JournalStorageManager implements StorageManager
public SimpleString filterString; public SimpleString filterString;
public boolean autoCreated;
public PersistentQueueBindingEncoding() public PersistentQueueBindingEncoding()
{ {
} }
@ -3041,16 +3044,20 @@ public class JournalStorageManager implements StorageManager
address + address +
", filterString=" + ", filterString=" +
filterString + filterString +
", autoCreated=" +
autoCreated +
"]"; "]";
} }
public PersistentQueueBindingEncoding(final SimpleString name, public PersistentQueueBindingEncoding(final SimpleString name,
final SimpleString address, final SimpleString address,
final SimpleString filterString) final SimpleString filterString,
final boolean autoCreated)
{ {
this.name = name; this.name = name;
this.address = address; this.address = address;
this.filterString = filterString; this.filterString = filterString;
this.autoCreated = autoCreated;
} }
public long getId() public long getId()
@ -3083,11 +3090,17 @@ public class JournalStorageManager implements StorageManager
return name; return name;
} }
public boolean isAutoCreated()
{
return autoCreated;
}
public void decode(final ActiveMQBuffer buffer) public void decode(final ActiveMQBuffer buffer)
{ {
name = buffer.readSimpleString(); name = buffer.readSimpleString();
address = buffer.readSimpleString(); address = buffer.readSimpleString();
filterString = buffer.readNullableSimpleString(); filterString = buffer.readNullableSimpleString();
autoCreated = buffer.readBoolean();
} }
public void encode(final ActiveMQBuffer buffer) public void encode(final ActiveMQBuffer buffer)
@ -3095,12 +3108,13 @@ public class JournalStorageManager implements StorageManager
buffer.writeSimpleString(name); buffer.writeSimpleString(name);
buffer.writeSimpleString(address); buffer.writeSimpleString(address);
buffer.writeNullableSimpleString(filterString); buffer.writeNullableSimpleString(filterString);
buffer.writeBoolean(autoCreated);
} }
public int getEncodeSize() public int getEncodeSize()
{ {
return SimpleString.sizeofString(name) + SimpleString.sizeofString(address) + return SimpleString.sizeofString(name) + SimpleString.sizeofString(address) +
SimpleString.sizeofNullableString(filterString); SimpleString.sizeofNullableString(filterString) + DataConstants.SIZE_BOOLEAN;
} }
} }

View File

@ -17,6 +17,7 @@
package org.apache.activemq.core.postoffice; package org.apache.activemq.core.postoffice;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.apache.activemq.api.core.SimpleString; import org.apache.activemq.api.core.SimpleString;
import org.apache.activemq.core.transaction.Transaction; import org.apache.activemq.core.transaction.Transaction;
@ -50,4 +51,6 @@ public interface AddressManager
Binding getBinding(SimpleString queueName); Binding getBinding(SimpleString queueName);
Map<SimpleString, Binding> getBindings(); Map<SimpleString, Binding> getBindings();
Set<SimpleString> getAddresses();
} }

View File

@ -17,6 +17,7 @@
package org.apache.activemq.core.postoffice; package org.apache.activemq.core.postoffice;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.apache.activemq.api.core.Pair; import org.apache.activemq.api.core.Pair;
import org.apache.activemq.api.core.SimpleString; import org.apache.activemq.api.core.SimpleString;
@ -95,4 +96,6 @@ public interface PostOffice extends ActiveMQComponent
boolean isAddressBound(final SimpleString address) throws Exception; boolean isAddressBound(final SimpleString address) throws Exception;
Set<SimpleString> getAddresses();
} }

View File

@ -861,6 +861,11 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding
return notificationLock; return notificationLock;
} }
public Set<SimpleString> getAddresses()
{
return addressManager.getAddresses();
}
public void sendQueueInfoToQueue(final SimpleString queueName, final SimpleString address) throws Exception 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 - // We send direct to the queue so we can send it to the same queue that is bound to the notifications address -

View File

@ -16,7 +16,9 @@
*/ */
package org.apache.activemq.core.postoffice.impl; package org.apache.activemq.core.postoffice.impl;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@ -151,6 +153,15 @@ public class SimpleAddressManager implements AddressManager
mappings.clear(); mappings.clear();
} }
@Override
public Set<SimpleString> getAddresses()
{
Set<SimpleString> addresses = new HashSet<>();
addresses.addAll(mappings.keySet());
return addresses;
}
protected void removeBindingInternal(final SimpleString address, final SimpleString bindableName) protected void removeBindingInternal(final SimpleString address, final SimpleString bindableName)
{ {
Bindings bindings = mappings.get(address); Bindings bindings = mappings.get(address);

View File

@ -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.SessionAddMetaDataMessageV2;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionBindingQueryMessage; 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;
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.SessionConsumerCloseMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionConsumerFlowCreditMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionConsumerFlowCreditMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionCreateConsumerMessage; 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.SessionIndividualAcknowledgeMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionQueueQueryMessage; 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;
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.SessionRequestProducerCreditsMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionSendContinuationMessage; import org.apache.activemq.core.protocol.core.impl.wireformat.SessionSendContinuationMessage;
import org.apache.activemq.core.protocol.core.impl.wireformat.SessionSendLargeMessage; 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 // We send back queue information on the queue as a response- this allows the queue to
// be automatically recreated on failover // 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; break;
@ -277,7 +287,14 @@ public class ServerSessionPacketHandler implements ChannelHandler
requiresResponse = true; requiresResponse = true;
SessionQueueQueryMessage request = (SessionQueueQueryMessage)packet; SessionQueueQueryMessage request = (SessionQueueQueryMessage)packet;
QueueQueryResult result = session.executeQueueQuery(request.getQueueName()); 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; break;
} }
case SESS_BINDINGQUERY: case SESS_BINDINGQUERY:
@ -285,7 +302,14 @@ public class ServerSessionPacketHandler implements ChannelHandler
requiresResponse = true; requiresResponse = true;
SessionBindingQueryMessage request = (SessionBindingQueryMessage)packet; SessionBindingQueryMessage request = (SessionBindingQueryMessage)packet;
BindingQueryResult result = session.executeBindingQuery(request.getAddress()); 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; break;
} }
case SESS_ACKNOWLEDGE: case SESS_ACKNOWLEDGE:

View File

@ -177,6 +177,13 @@ public interface ActiveMQServer extends ActiveMQComponent
boolean durable, boolean durable,
boolean temporary) throws Exception; boolean temporary) throws Exception;
Queue createQueue(SimpleString address,
SimpleString queueName,
SimpleString filter,
boolean durable,
boolean temporary,
boolean autoCreated) throws Exception;
Queue deployQueue(SimpleString address, Queue deployQueue(SimpleString address,
SimpleString queueName, SimpleString queueName,
SimpleString filterString, SimpleString filterString,

View File

@ -1366,4 +1366,8 @@ public interface ActiveMQServerLogger extends BasicLogger
@Message(id = 224064, value = "Setting <{0}> is invalid with this HA Policy Configuration. Please use <ha-policy> exclusively or remove. Ignoring <{0}> value.", format = Message.Format.MESSAGE_FORMAT) @Message(id = 224064, value = "Setting <{0}> is invalid with this HA Policy Configuration. Please use <ha-policy> exclusively or remove. Ignoring <{0}> value.", format = Message.Format.MESSAGE_FORMAT)
void incompatibleWithHAPolicyChosen(String parameter); 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);
} }

View File

@ -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();
}

View File

@ -33,11 +33,15 @@ public class BindingQueryResult
private List<SimpleString> queueNames; private List<SimpleString> queueNames;
public BindingQueryResult(final boolean exists, final List<SimpleString> queueNames) private boolean autoCreateJmsQueues;
public BindingQueryResult(final boolean exists, final List<SimpleString> queueNames, final boolean autoCreateJmsQueues)
{ {
this.exists = exists; this.exists = exists;
this.queueNames = queueNames; this.queueNames = queueNames;
this.autoCreateJmsQueues = autoCreateJmsQueues;
} }
public boolean isExists() public boolean isExists()
@ -45,6 +49,11 @@ public class BindingQueryResult
return exists; return exists;
} }
public boolean isAutoCreateJmsQueues()
{
return autoCreateJmsQueues;
}
public List<SimpleString> getQueueNames() public List<SimpleString> getQueueNames()
{ {
return queueNames; return queueNames;

View File

@ -49,6 +49,8 @@ public interface Queue extends Bindable
boolean isTemporary(); boolean isTemporary();
boolean isAutoCreated();
void addConsumer(Consumer consumer) throws Exception; void addConsumer(Consumer consumer) throws Exception;
void removeConsumer(Consumer consumer); 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 * on shared subscriptions where the queue needs to be deleted when all the
* consumers are closed. * consumers are closed.
*/ */
void setConsumersRefCount(ActiveMQServer server); void setConsumersRefCount(ReferenceCounter referenceCounter);
ReferenceCounter getConsumersRefCount(); ReferenceCounter getConsumersRefCount();
@ -176,6 +178,10 @@ public interface Queue extends Bindable
boolean checkRedelivery(MessageReference ref, long timeBase, boolean ignoreRedeliveryDelay) throws Exception; boolean checkRedelivery(MessageReference ref, long timeBase, boolean ignoreRedeliveryDelay) throws Exception;
/**
* It will iterate thorugh memory only (not paging)
* @return
*/
LinkedListIterator<MessageReference> iterator(); LinkedListIterator<MessageReference> iterator();
LinkedListIterator<MessageReference> totalIterator(); LinkedListIterator<MessageReference> totalIterator();
@ -228,7 +234,10 @@ public interface Queue extends Bindable
void incrementMesssagesAdded(); void incrementMesssagesAdded();
List<MessageReference> cancelScheduledMessages(); /**
* cancels scheduled messages and send them to the head of the queue.
*/
void deliverScheduledMessages();
void postAcknowledge(MessageReference ref); void postAcknowledge(MessageReference ref);

View File

@ -39,7 +39,8 @@ public interface QueueFactory
Filter filter, Filter filter,
PageSubscription pageSubscription, PageSubscription pageSubscription,
boolean durable, boolean durable,
boolean temporary); boolean temporary,
boolean autoCreated);
/** /**
* This is required for delete-all-reference to work correctly with paging * This is required for delete-all-reference to work correctly with paging

View File

@ -1193,9 +1193,18 @@ public class ActiveMQServerImpl implements ActiveMQServer
final boolean durable, final boolean durable,
final boolean temporary) throws Exception 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. * 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, final SimpleString filterString,
boolean durable) throws Exception 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)) if (!queue.getAddress().equals(address))
{ {
@ -1263,7 +1272,7 @@ public class ActiveMQServerImpl implements ActiveMQServer
{ {
ActiveMQServerLogger.LOGGER.deployQueue(queueName); 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 public void destroyQueue(final SimpleString queueName) throws Exception
@ -1981,7 +1990,8 @@ public class ActiveMQServerImpl implements ActiveMQServer
final boolean durable, final boolean durable,
final boolean temporary, final boolean temporary,
final boolean ignoreIfExists, final boolean ignoreIfExists,
final boolean transientQueue) throws Exception final boolean transientQueue,
final boolean autoCreated) throws Exception
{ {
QueueBinding binding = (QueueBinding) postOffice.getBinding(queueName); QueueBinding binding = (QueueBinding) postOffice.getBinding(queueName);
@ -2021,11 +2031,16 @@ public class ActiveMQServerImpl implements ActiveMQServer
filter, filter,
pageSubscription, pageSubscription,
durable, durable,
temporary); temporary,
autoCreated);
if (transientQueue) 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()); binding = new LocalQueueBinding(address, queue, nodeManager.getNodeId());

View File

@ -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;
}
}

View File

@ -90,7 +90,7 @@ public class BackupRecoveryJournalLoader extends PostOfficeJournalLoader
@Override @Override
public void postLoad(Journal messageJournal, ResourceManager resourceManager, Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception public void postLoad(Journal messageJournal, ResourceManager resourceManager, Map<SimpleString, List<Pair<byte[], Long>>> 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()); locator.setProtocolManagerFactory(ActiveMQServerSideProtocolManagerFactory.getInstance());
try (ClientSessionFactory sessionFactory = locator.createSessionFactory()) try (ClientSessionFactory sessionFactory = locator.createSessionFactory())

View File

@ -55,6 +55,7 @@ public class LastValueQueue extends QueueImpl
final PageSubscription pageSubscription, final PageSubscription pageSubscription,
final boolean durable, final boolean durable,
final boolean temporary, final boolean temporary,
final boolean autoCreated,
final ScheduledExecutorService scheduledExecutor, final ScheduledExecutorService scheduledExecutor,
final PostOffice postOffice, final PostOffice postOffice,
final StorageManager storageManager, final StorageManager storageManager,
@ -68,6 +69,7 @@ public class LastValueQueue extends QueueImpl
pageSubscription, pageSubscription,
durable, durable,
temporary, temporary,
autoCreated,
scheduledExecutor, scheduledExecutor,
postOffice, postOffice,
storageManager, storageManager,

View File

@ -187,7 +187,8 @@ public class LiveOnlyActivation extends Activation
ScaleDownHandler scaleDownHandler = new ScaleDownHandler(activeMQServer.getPagingManager(), ScaleDownHandler scaleDownHandler = new ScaleDownHandler(activeMQServer.getPagingManager(),
activeMQServer.getPostOffice(), activeMQServer.getPostOffice(),
activeMQServer.getNodeManager(), activeMQServer.getNodeManager(),
activeMQServer.getClusterManager().getClusterController()); activeMQServer.getClusterManager().getClusterController(),
activeMQServer.getStorageManager());
ConcurrentMap<SimpleString, DuplicateIDCache> duplicateIDCaches = ((PostOfficeImpl) activeMQServer.getPostOffice()).getDuplicateIDCaches(); ConcurrentMap<SimpleString, DuplicateIDCache> duplicateIDCaches = ((PostOfficeImpl) activeMQServer.getPostOffice()).getDuplicateIDCaches();
Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap = new HashMap<>(); Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap = new HashMap<>();
for (SimpleString address : duplicateIDCaches.keySet()) for (SimpleString address : duplicateIDCaches.keySet())

View File

@ -46,6 +46,7 @@ import org.apache.activemq.core.postoffice.Binding;
import org.apache.activemq.core.postoffice.DuplicateIDCache; import org.apache.activemq.core.postoffice.DuplicateIDCache;
import org.apache.activemq.core.postoffice.PostOffice; import org.apache.activemq.core.postoffice.PostOffice;
import org.apache.activemq.core.postoffice.impl.LocalQueueBinding; 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.ActiveMQServerLogger;
import org.apache.activemq.core.server.MessageReference; import org.apache.activemq.core.server.MessageReference;
import org.apache.activemq.core.server.NodeManager; import org.apache.activemq.core.server.NodeManager;
@ -155,7 +156,13 @@ public class PostOfficeJournalLoader implements JournalLoader
filter, filter,
subscription, subscription,
true, 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()); Binding binding = new LocalQueueBinding(queueBindingInfo.getAddress(), queue, nodeManager.getNodeId());

View File

@ -75,7 +75,8 @@ public class QueueFactoryImpl implements QueueFactory
final Filter filter, final Filter filter,
final PageSubscription pageSubscription, final PageSubscription pageSubscription,
final boolean durable, final boolean durable,
final boolean temporary) final boolean temporary,
final boolean autoCreated)
{ {
AddressSettings addressSettings = addressSettingsRepository.getMatch(address.toString()); AddressSettings addressSettings = addressSettingsRepository.getMatch(address.toString());
@ -89,6 +90,7 @@ public class QueueFactoryImpl implements QueueFactory
pageSubscription, pageSubscription,
durable, durable,
temporary, temporary,
autoCreated,
scheduledExecutor, scheduledExecutor,
postOffice, postOffice,
storageManager, storageManager,
@ -104,6 +106,7 @@ public class QueueFactoryImpl implements QueueFactory
pageSubscription, pageSubscription,
durable, durable,
temporary, temporary,
autoCreated,
scheduledExecutor, scheduledExecutor,
postOffice, postOffice,
storageManager, storageManager,

View File

@ -61,7 +61,6 @@ import org.apache.activemq.core.server.ActiveMQServerLogger;
import org.apache.activemq.core.server.Consumer; import org.apache.activemq.core.server.Consumer;
import org.apache.activemq.core.server.HandleStatus; import org.apache.activemq.core.server.HandleStatus;
import org.apache.activemq.core.server.ActiveMQMessageBundle; 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.MessageReference;
import org.apache.activemq.core.server.Queue; import org.apache.activemq.core.server.Queue;
import org.apache.activemq.core.server.RoutingContext; import org.apache.activemq.core.server.RoutingContext;
@ -131,6 +130,8 @@ public class QueueImpl implements Queue
private final boolean temporary; private final boolean temporary;
private final boolean autoCreated;
private final PostOffice postOffice; private final PostOffice postOffice;
private volatile boolean queueDestroyed = false; private volatile boolean queueDestroyed = false;
@ -315,6 +316,7 @@ public class QueueImpl implements Queue
final Filter filter, final Filter filter,
final boolean durable, final boolean durable,
final boolean temporary, final boolean temporary,
final boolean autoCreated,
final ScheduledExecutorService scheduledExecutor, final ScheduledExecutorService scheduledExecutor,
final PostOffice postOffice, final PostOffice postOffice,
final StorageManager storageManager, final StorageManager storageManager,
@ -328,6 +330,7 @@ public class QueueImpl implements Queue
null, null,
durable, durable,
temporary, temporary,
autoCreated,
scheduledExecutor, scheduledExecutor,
postOffice, postOffice,
storageManager, storageManager,
@ -342,6 +345,7 @@ public class QueueImpl implements Queue
final PageSubscription pageSubscription, final PageSubscription pageSubscription,
final boolean durable, final boolean durable,
final boolean temporary, final boolean temporary,
final boolean autoCreated,
final ScheduledExecutorService scheduledExecutor, final ScheduledExecutorService scheduledExecutor,
final PostOffice postOffice, final PostOffice postOffice,
final StorageManager storageManager, final StorageManager storageManager,
@ -362,6 +366,8 @@ public class QueueImpl implements Queue
this.temporary = temporary; this.temporary = temporary;
this.autoCreated = autoCreated;
this.postOffice = postOffice; this.postOffice = postOffice;
this.storageManager = storageManager; this.storageManager = storageManager;
@ -425,11 +431,11 @@ public class QueueImpl implements Queue
} }
// Queue implementation ---------------------------------------------------------------------------------------- // Queue implementation ----------------------------------------------------------------------------------------
public synchronized void setConsumersRefCount(final ActiveMQServer server) public synchronized void setConsumersRefCount(final ReferenceCounter referenceCounter)
{ {
if (refCountForConsumers == null) if (refCountForConsumers == null)
{ {
this.refCountForConsumers = new TransientQueueManagerImpl(server, this.name); this.refCountForConsumers = referenceCounter;
} }
} }
@ -449,6 +455,11 @@ public class QueueImpl implements Queue
return temporary; return temporary;
} }
public boolean isAutoCreated()
{
return autoCreated;
}
public SimpleString getName() public SimpleString getName()
{ {
return name; return name;
@ -1220,9 +1231,18 @@ public class QueueImpl implements Queue
} }
@Override @Override
public List<MessageReference> cancelScheduledMessages() public void deliverScheduledMessages()
{ {
return scheduledDeliveryHandler.cancel(null); List<MessageReference> 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() public long getMessagesAdded()
@ -3105,6 +3125,8 @@ public class QueueImpl implements Queue
Iterator<MessageReference> interIterator = null; Iterator<MessageReference> interIterator = null;
LinkedListIterator<MessageReference> messagesIterator = null; LinkedListIterator<MessageReference> messagesIterator = null;
Iterator lastIterator = null;
public TotalQueueIterator() public TotalQueueIterator()
{ {
if (pageSubscription != null) if (pageSubscription != null)
@ -3118,18 +3140,21 @@ public class QueueImpl implements Queue
@Override @Override
public boolean hasNext() public boolean hasNext()
{ {
if (messagesIterator.hasNext()) if (messagesIterator != null && messagesIterator.hasNext())
{ {
lastIterator = messagesIterator;
return true; return true;
} }
if (interIterator.hasNext()) if (interIterator.hasNext())
{ {
lastIterator = interIterator;
return true; return true;
} }
if (pageIter != null) if (pageIter != null)
{ {
if (pageIter.hasNext()) if (pageIter.hasNext())
{ {
lastIterator = pageIter;
return true; return true;
} }
} }
@ -3140,18 +3165,21 @@ public class QueueImpl implements Queue
@Override @Override
public MessageReference next() public MessageReference next()
{ {
if (messagesIterator.hasNext()) if (messagesIterator != null && messagesIterator.hasNext())
{ {
return messagesIterator.next(); MessageReference msg = messagesIterator.next();
return msg;
} }
if (interIterator.hasNext()) if (interIterator.hasNext())
{ {
lastIterator = interIterator;
return interIterator.next(); return interIterator.next();
} }
if (pageIter != null) if (pageIter != null)
{ {
if (pageIter.hasNext()) if (pageIter.hasNext())
{ {
lastIterator = pageIter;
return pageIter.next(); return pageIter.next();
} }
} }
@ -3162,6 +3190,10 @@ public class QueueImpl implements Queue
@Override @Override
public void remove() public void remove()
{ {
if (lastIterator != null)
{
lastIterator.remove();
}
} }
@Override @Override
@ -3172,8 +3204,14 @@ public class QueueImpl implements Queue
@Override @Override
public void close() public void close()
{ {
if (pageIter != null) pageIter.close(); if (pageIter != null)
messagesIterator.close(); {
pageIter.close();
}
if (messagesIterator != null)
{
messagesIterator.close();
}
} }
} }

View File

@ -20,11 +20,13 @@ import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid; import javax.transaction.xa.Xid;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; 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.Message;
import org.apache.activemq.api.core.Pair; 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.PagingStore;
import org.apache.activemq.core.paging.cursor.PageSubscription; import org.apache.activemq.core.paging.cursor.PageSubscription;
import org.apache.activemq.core.paging.cursor.PagedReference; 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.Binding;
import org.apache.activemq.core.postoffice.Bindings;
import org.apache.activemq.core.postoffice.PostOffice; import org.apache.activemq.core.postoffice.PostOffice;
import org.apache.activemq.core.postoffice.impl.LocalQueueBinding; import org.apache.activemq.core.postoffice.impl.LocalQueueBinding;
import org.apache.activemq.core.postoffice.impl.PostOfficeImpl; 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.ResourceManager;
import org.apache.activemq.core.transaction.Transaction; import org.apache.activemq.core.transaction.Transaction;
import org.apache.activemq.core.transaction.TransactionOperation; import org.apache.activemq.core.transaction.TransactionOperation;
import org.apache.activemq.core.transaction.impl.TransactionImpl;
import org.apache.activemq.utils.LinkedListIterator; import org.apache.activemq.utils.LinkedListIterator;
public class ScaleDownHandler public class ScaleDownHandler
@ -64,20 +69,22 @@ public class ScaleDownHandler
final PostOffice postOffice; final PostOffice postOffice;
private NodeManager nodeManager; private NodeManager nodeManager;
private final ClusterController clusterController; private final ClusterController clusterController;
private final StorageManager storageManager;
private String targetNodeId; 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.pagingManager = pagingManager;
this.postOffice = postOffice; this.postOffice = postOffice;
this.nodeManager = nodeManager; this.nodeManager = nodeManager;
this.clusterController = clusterController; this.clusterController = clusterController;
this.storageManager = storageManager;
} }
public long scaleDown(ClientSessionFactory sessionFactory, public long scaleDown(ClientSessionFactory sessionFactory,
ResourceManager resourceManager, ResourceManager resourceManager,
Map<SimpleString, Map<SimpleString,
List<Pair<byte[], Long>>> duplicateIDMap, List<Pair<byte[], Long>>> duplicateIDMap,
SimpleString managementAddress, SimpleString managementAddress,
SimpleString targetNodeId) throws Exception SimpleString targetNodeId) throws Exception
{ {
@ -91,218 +98,239 @@ public class ScaleDownHandler
return num; return num;
} }
private long scaleDownMessages(ClientSessionFactory sessionFactory, SimpleString nodeId) throws Exception public long scaleDownMessages(ClientSessionFactory sessionFactory, SimpleString nodeId) throws Exception
{ {
long messageCount = 0; long messageCount = 0;
targetNodeId = nodeId != null ? nodeId.toString() : getTargetNodeId(sessionFactory); targetNodeId = nodeId != null ? nodeId.toString() : getTargetNodeId(sessionFactory);
ClientSession session = sessionFactory.createSession(false, true, true); try (ClientSession session = sessionFactory.createSession(false, true, true))
Map<String, Long> queueIDs = new HashMap<>();
ClientProducer producer = session.createProducer();
List<SimpleString> addresses = new ArrayList<>();
for (Map.Entry<SimpleString, Binding> entry : postOffice.getAllBindings().entrySet())
{ {
if (entry.getValue() instanceof LocalQueueBinding) ClientProducer producer = session.createProducer();
{
SimpleString address = entry.getValue().getAddress();
// There is a special case involving store-and-forward queues used for clustering. // perform a loop per address
// If this queue is supposed to forward messages to the server that I'm scaling down to I need to handle these messages differently. for (SimpleString address : postOffice.getAddresses())
boolean storeAndForward = false; {
if (address.toString().startsWith("sf.")) 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<Queue> queues = new TreeSet<>(new OrderQueueByNumberOfReferencesComparator());
for (Binding binding : bindings.getBindings())
{ {
// these get special treatment later if (binding instanceof LocalQueueBinding)
storeAndForward = true; {
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 return messageCount;
List<Queue> queues = new ArrayList<>(); }
Map<SimpleString, LinkedListIterator<MessageReference>> queueIterators = new HashMap<>();
for (Binding binding : postOffice.getBindingsForAddress(address).getBindings()) public long scaleDownRegularMessages(final SimpleString address, final Set<Queue> queues, final ClientSession clientSession, final ClientProducer producer) throws Exception
{
ActiveMQServerLogger.LOGGER.debug("Scaling down messages on address " + address);
long messageCount = 0;
final HashMap<Queue, QueuesXRefInnerManager> controls = new HashMap<Queue, QueuesXRefInnerManager>();
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<MessageReference> 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<QueuesXRefInnerManager> queuesFound = new HashSet<>();
for (Map.Entry<Queue, QueuesXRefInnerManager> controlEntry : controls.entrySet())
{ {
Queue queue = ((LocalQueueBinding) binding).getQueue(); if (controlEntry.getKey() == loopQueue)
//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<MessageReference> messageReferences = queue.cancelScheduledMessages();
for (MessageReference ref : messageReferences)
{ {
ref.getMessage().putLongProperty(MessageImpl.HDR_SCHEDULED_DELIVERY_TIME, ref.getScheduledDeliveryTime()); // no need to lookup on itself, we just add it
ref.setScheduledDeliveryTime(0); queuesFound.add(controlEntry.getValue());
} }
queue.addHead(messageReferences); else if (controlEntry.getValue().lookup(messageReference))
queues.add(queue); {
queueIterators.put(queue.getName(), queue.totalIterator()); 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<Queue> 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<MessageReference> 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<SimpleString> 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 // TODO: what if oldRouteToIDs == null ??
Collections.sort(queues, new OrderQueueByNumberOfReferencesComparator());
// loop through every queue on this address for (SimpleString propertyToRemove : propertiesToRemove)
List<SimpleString> checkedQueues = new ArrayList<>();
for (Queue bigLoopQueue : queues)
{ {
checkedQueues.add(bigLoopQueue.getName()); message.removeProperty(propertyToRemove);
LinkedListIterator<MessageReference> 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<SimpleString> 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<SimpleString> 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<Queue> 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();
}
} }
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(); tx.commit();
session.close();
return messageCount; return messageCount;
} }
@ -324,6 +352,8 @@ public class ScaleDownHandler
Transaction transaction = resourceManager.getTransaction(xid); Transaction transaction = resourceManager.getTransaction(xid);
session.start(xid, XAResource.TMNOFLAGS); session.start(xid, XAResource.TMNOFLAGS);
List<TransactionOperation> allOperations = transaction.getAllOperations(); List<TransactionOperation> allOperations = transaction.getAllOperations();
// Get the information of the Prepared TXs so it could replay the TXs
Map<ServerMessage, Pair<List<Long>, List<Long>>> queuesToSendTo = new HashMap<>(); Map<ServerMessage, Pair<List<Long>, List<Long>>> queuesToSendTo = new HashMap<>();
for (TransactionOperation operation : allOperations) for (TransactionOperation operation : allOperations)
{ {
@ -387,6 +417,7 @@ public class ScaleDownHandler
} }
} }
} }
ClientProducer producer = session.createProducer(); ClientProducer producer = session.createProducer();
for (Map.Entry<ServerMessage, Pair<List<Long>, List<Long>>> entry : queuesToSendTo.entrySet()) for (Map.Entry<ServerMessage, Pair<List<Long>, List<Long>>> entry : queuesToSendTo.entrySet())
{ {
@ -436,78 +467,6 @@ public class ScaleDownHandler
} }
session.close(); 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<Queue> queues, Map<SimpleString, LinkedListIterator<MessageReference>> queueIterators, List<SimpleString> checkedQueues, Queue bigLoopQueue, List<Queue> 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<MessageReference> 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 * 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 * 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 == 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 BEFORE;
if (queue1.getMessageCount() < queue2.getMessageCount()) return AFTER; if (queue1.getMessageCount() < queue2.getMessageCount()) return AFTER;
return result; 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<MessageReference> 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;
}
}
} }

View File

@ -37,6 +37,7 @@ import org.apache.activemq.api.core.Pair;
import org.apache.activemq.api.core.SimpleString; import org.apache.activemq.api.core.SimpleString;
import org.apache.activemq.api.core.management.CoreNotificationType; import org.apache.activemq.api.core.management.CoreNotificationType;
import org.apache.activemq.api.core.management.ManagementHelper; 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.client.impl.ClientMessageImpl;
import org.apache.activemq.core.exception.ActiveMQXAException; import org.apache.activemq.core.exception.ActiveMQXAException;
import org.apache.activemq.core.filter.Filter; 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); 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) if (temporary)
{ {
@ -676,6 +685,8 @@ public class ServerSessionImpl implements ServerSession, FailureListener
public QueueQueryResult executeQueueQuery(final SimpleString name) throws Exception 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) if (name == null)
{ {
throw ActiveMQMessageBundle.BUNDLE.queueNameIsNull(); throw ActiveMQMessageBundle.BUNDLE.queueNameIsNull();
@ -699,16 +710,21 @@ public class ServerSessionImpl implements ServerSession, FailureListener
queue.isTemporary(), queue.isTemporary(),
filterString, filterString,
queue.getConsumerCount(), queue.getConsumerCount(),
queue.getMessageCount()); queue.getMessageCount(),
autoCreateJmsQueues);
} }
// make an exception for the management address (see HORNETQ-29) // make an exception for the management address (see HORNETQ-29)
else if (name.equals(managementAddress)) 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 else
{ {
response = new QueueQueryResult(); response = new QueueQueryResult(null, null, false, false, null, 0, 0, false, false);
} }
return response; return response;
@ -716,6 +732,8 @@ public class ServerSessionImpl implements ServerSession, FailureListener
public BindingQueryResult executeBindingQuery(final SimpleString address) throws Exception 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) if (address == null)
{ {
throw ActiveMQMessageBundle.BUNDLE.addressIsNull(); throw ActiveMQMessageBundle.BUNDLE.addressIsNull();
@ -726,7 +744,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener
// make an exception for the management address (see HORNETQ-29) // make an exception for the management address (see HORNETQ-29)
if (address.equals(managementAddress)) if (address.equals(managementAddress))
{ {
return new BindingQueryResult(true, names); return new BindingQueryResult(true, names, autoCreateJmsQueues);
} }
Bindings bindings = postOffice.getMatchingBindings(address); 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 public void forceConsumerDelivery(final long consumerID, final long sequence) throws Exception

View File

@ -56,6 +56,10 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
public static final boolean DEFAULT_LAST_VALUE_QUEUE = false; 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_REDISTRIBUTION_DELAY = -1;
public static final long DEFAULT_EXPIRY_DELAY = -1; public static final long DEFAULT_EXPIRY_DELAY = -1;
@ -106,6 +110,10 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
private SlowConsumerPolicy slowConsumerPolicy = null; private SlowConsumerPolicy slowConsumerPolicy = null;
private Boolean autoCreateJmsQueues = null;
private Boolean autoDeleteJmsQueues = null;
public AddressSettings(AddressSettings other) public AddressSettings(AddressSettings other)
{ {
this.addressFullMessagePolicy = other.addressFullMessagePolicy; this.addressFullMessagePolicy = other.addressFullMessagePolicy;
@ -127,6 +135,8 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
this.slowConsumerThreshold = other.slowConsumerThreshold; this.slowConsumerThreshold = other.slowConsumerThreshold;
this.slowConsumerCheckPeriod = other.slowConsumerCheckPeriod; this.slowConsumerCheckPeriod = other.slowConsumerCheckPeriod;
this.slowConsumerPolicy = other.slowConsumerPolicy; this.slowConsumerPolicy = other.slowConsumerPolicy;
this.autoCreateJmsQueues = other.autoCreateJmsQueues;
this.autoDeleteJmsQueues = other.autoDeleteJmsQueues;
} }
public AddressSettings() public AddressSettings()
@ -134,6 +144,26 @@ public class AddressSettings implements Mergeable<AddressSettings>, 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() public boolean isLastValueQueue()
{ {
return lastValueQueue != null ? lastValueQueue : AddressSettings.DEFAULT_LAST_VALUE_QUEUE; return lastValueQueue != null ? lastValueQueue : AddressSettings.DEFAULT_LAST_VALUE_QUEUE;
@ -398,6 +428,14 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
{ {
slowConsumerPolicy = merged.slowConsumerPolicy; slowConsumerPolicy = merged.slowConsumerPolicy;
} }
if (autoCreateJmsQueues == null)
{
autoCreateJmsQueues = merged.autoCreateJmsQueues;
}
if (autoDeleteJmsQueues == null)
{
autoDeleteJmsQueues = merged.autoDeleteJmsQueues;
}
} }
@Override @Override
@ -458,6 +496,10 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
{ {
slowConsumerPolicy = null; slowConsumerPolicy = null;
} }
autoCreateJmsQueues = BufferHelper.readNullableBoolean(buffer);
autoDeleteJmsQueues = BufferHelper.readNullableBoolean(buffer);
} }
@Override @Override
@ -482,7 +524,9 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
BufferHelper.sizeOfNullableBoolean(sendToDLAOnNoRoute) + BufferHelper.sizeOfNullableBoolean(sendToDLAOnNoRoute) +
BufferHelper.sizeOfNullableLong(slowConsumerCheckPeriod) + BufferHelper.sizeOfNullableLong(slowConsumerCheckPeriod) +
BufferHelper.sizeOfNullableLong(slowConsumerThreshold) + BufferHelper.sizeOfNullableLong(slowConsumerThreshold) +
BufferHelper.sizeOfNullableSimpleString(slowConsumerPolicy != null ? slowConsumerPolicy.toString() : null); BufferHelper.sizeOfNullableSimpleString(slowConsumerPolicy != null ? slowConsumerPolicy.toString() : null) +
BufferHelper.sizeOfNullableBoolean(autoCreateJmsQueues) +
BufferHelper.sizeOfNullableBoolean(autoDeleteJmsQueues);
} }
@Override @Override
@ -526,6 +570,10 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
BufferHelper.writeNullableLong(buffer, slowConsumerCheckPeriod); BufferHelper.writeNullableLong(buffer, slowConsumerCheckPeriod);
buffer.writeNullableSimpleString(slowConsumerPolicy != null ? new SimpleString(slowConsumerPolicy.toString()) : null); buffer.writeNullableSimpleString(slowConsumerPolicy != null ? new SimpleString(slowConsumerPolicy.toString()) : null);
BufferHelper.writeNullableBoolean(buffer, autoCreateJmsQueues);
BufferHelper.writeNullableBoolean(buffer, autoDeleteJmsQueues);
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -556,6 +604,8 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
result = prime * result + ((slowConsumerThreshold == null) ? 0 : slowConsumerThreshold.hashCode()); result = prime * result + ((slowConsumerThreshold == null) ? 0 : slowConsumerThreshold.hashCode());
result = prime * result + ((slowConsumerCheckPeriod == null) ? 0 : slowConsumerCheckPeriod.hashCode()); result = prime * result + ((slowConsumerCheckPeriod == null) ? 0 : slowConsumerCheckPeriod.hashCode());
result = prime * result + ((slowConsumerPolicy == null) ? 0 : slowConsumerPolicy.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; return result;
} }
@ -705,6 +755,20 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
} }
else if (!slowConsumerPolicy.equals(other.slowConsumerPolicy)) else if (!slowConsumerPolicy.equals(other.slowConsumerPolicy))
return false; 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; return true;
} }
@ -751,6 +815,10 @@ public class AddressSettings implements Mergeable<AddressSettings>, Serializable
slowConsumerCheckPeriod + slowConsumerCheckPeriod +
", slowConsumerPolicy=" + ", slowConsumerPolicy=" +
slowConsumerPolicy + slowConsumerPolicy +
", autoCreateJmsQueues=" +
autoCreateJmsQueues +
", autoDeleteJmsQueues=" +
autoDeleteJmsQueues +
"]"; "]";
} }
} }

View File

@ -2258,6 +2258,23 @@
</xsd:documentation> </xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:element> </xsd:element>
<xsd:element name="auto-create-jms-queues" type="xsd:boolean" default="true" maxOccurs="1" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
whether or not to automatically create JMS queues when a producer sends or a consumer connects to a
queue
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="auto-delete-jms-queues" type="xsd:boolean" default="true" maxOccurs="1" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
whether or not to delete auto-created JMS queues when the queue has 0 consumers and 0 messages
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:all> </xsd:all>
<xsd:attribute name="match" type="xsd:string" use="required"> <xsd:attribute name="match" type="xsd:string" use="required">

View File

@ -297,6 +297,8 @@ public class FileConfigurationTest extends ConfigurationImplTest
assertEquals(10, conf.getAddressesSettings().get("a1").getSlowConsumerThreshold()); assertEquals(10, conf.getAddressesSettings().get("a1").getSlowConsumerThreshold());
assertEquals(5, conf.getAddressesSettings().get("a1").getSlowConsumerCheckPeriod()); assertEquals(5, conf.getAddressesSettings().get("a1").getSlowConsumerCheckPeriod());
assertEquals(SlowConsumerPolicy.NOTIFY, conf.getAddressesSettings().get("a1").getSlowConsumerPolicy()); 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.1", conf.getAddressesSettings().get("a2").getDeadLetterAddress().toString());
assertEquals("a2.2", conf.getAddressesSettings().get("a2").getExpiryAddress().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(20, conf.getAddressesSettings().get("a2").getSlowConsumerThreshold());
assertEquals(15, conf.getAddressesSettings().get("a2").getSlowConsumerCheckPeriod()); assertEquals(15, conf.getAddressesSettings().get("a2").getSlowConsumerCheckPeriod());
assertEquals(SlowConsumerPolicy.KILL, conf.getAddressesSettings().get("a2").getSlowConsumerPolicy()); 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()); assertEquals(2, conf.getQueueConfigurations().size());

View File

@ -42,7 +42,6 @@ import org.apache.activemq.core.message.BodyEncoder;
import org.apache.activemq.core.paging.PagingStore; import org.apache.activemq.core.paging.PagingStore;
import org.apache.activemq.core.paging.cursor.PageSubscription; import org.apache.activemq.core.paging.cursor.PageSubscription;
import org.apache.activemq.core.server.Consumer; 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.MessageReference;
import org.apache.activemq.core.server.Queue; import org.apache.activemq.core.server.Queue;
import org.apache.activemq.core.server.RoutingContext; import org.apache.activemq.core.server.RoutingContext;
@ -1053,6 +1052,12 @@ public class ScheduledDeliveryHandlerTest extends Assert
return false; return false;
} }
@Override
public boolean isAutoCreated()
{
return false;
}
@Override @Override
public void addConsumer(Consumer consumer) throws Exception public void addConsumer(Consumer consumer) throws Exception
{ {
@ -1072,7 +1077,7 @@ public class ScheduledDeliveryHandlerTest extends Assert
} }
@Override @Override
public void setConsumersRefCount(ActiveMQServer server) public void setConsumersRefCount(ReferenceCounter referenceCounter)
{ {
} }
@ -1483,9 +1488,9 @@ public class ScheduledDeliveryHandlerTest extends Assert
} }
@Override @Override
public List<MessageReference> cancelScheduledMessages() public void deliverScheduledMessages()
{ {
return null;
} }
@Override @Override

View File

@ -46,7 +46,8 @@ public class AddressSettingsTest extends UnitTestCase
Assert.assertEquals(AddressSettings.DEFAULT_SLOW_CONSUMER_THRESHOLD, addressSettings.getSlowConsumerThreshold()); 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_CHECK_PERIOD, addressSettings.getSlowConsumerCheckPeriod());
Assert.assertEquals(AddressSettings.DEFAULT_SLOW_CONSUMER_POLICY, addressSettings.getSlowConsumerPolicy()); 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 @Test

View File

@ -972,7 +972,7 @@ public abstract class ServiceTestBase extends UnitTestCase
protected HashMap<Integer, AtomicInteger> countJournal(Configuration config) throws Exception protected HashMap<Integer, AtomicInteger> countJournal(Configuration config) throws Exception
{ {
final HashMap<Integer, AtomicInteger> recordsType = new HashMap<Integer, AtomicInteger>(); final HashMap<Integer, AtomicInteger> recordsType = new HashMap<Integer, AtomicInteger>();
SequentialFileFactory messagesFF = new NIOSequentialFileFactory(getJournalDir(), null); SequentialFileFactory messagesFF = new NIOSequentialFileFactory(config.getJournalDirectory(), null);
JournalImpl messagesJournal = new JournalImpl(config.getJournalFileSize(), JournalImpl messagesJournal = new JournalImpl(config.getJournalFileSize(),
config.getJournalMinFiles(), config.getJournalMinFiles(),

View File

@ -271,6 +271,8 @@
<slow-consumer-threshold>10</slow-consumer-threshold> <slow-consumer-threshold>10</slow-consumer-threshold>
<slow-consumer-check-period>5</slow-consumer-check-period> <slow-consumer-check-period>5</slow-consumer-check-period>
<slow-consumer-policy>NOTIFY</slow-consumer-policy> <slow-consumer-policy>NOTIFY</slow-consumer-policy>
<auto-create-jms-queues>true</auto-create-jms-queues>
<auto-delete-jms-queues>true</auto-delete-jms-queues>
</address-setting> </address-setting>
<address-setting match="a2"> <address-setting match="a2">
<dead-letter-address>a2.1</dead-letter-address> <dead-letter-address>a2.1</dead-letter-address>
@ -283,6 +285,8 @@
<slow-consumer-threshold>20</slow-consumer-threshold> <slow-consumer-threshold>20</slow-consumer-threshold>
<slow-consumer-check-period>15</slow-consumer-check-period> <slow-consumer-check-period>15</slow-consumer-check-period>
<slow-consumer-policy>KILL</slow-consumer-policy> <slow-consumer-policy>KILL</slow-consumer-policy>
<auto-create-jms-queues>false</auto-create-jms-queues>
<auto-delete-jms-queues>false</auto-delete-jms-queues>
</address-setting> </address-setting>
</address-settings> </address-settings>
<connector-services> <connector-services>

View File

@ -20,10 +20,10 @@ on your client classpath.
## JMS Client ## JMS Client
If you are using JMS on the client side, then you will also need to 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** > **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 > for the `javax.jms.*` classes. If you already have a jar with these
> interface classes on your classpath, you will not need it. > interface classes on your classpath, you will not need it.

View File

@ -95,6 +95,8 @@ entry that would be found in the `activemq-configuration.xml` file.
<slow-consumer-threshold>-1</slow-consumer-threshold> <slow-consumer-threshold>-1</slow-consumer-threshold>
<slow-consumer-policy>NOTIFY</slow-consumer-policy> <slow-consumer-policy>NOTIFY</slow-consumer-policy>
<slow-consumer-check-period>5</slow-consumer-check-period> <slow-consumer-check-period>5</slow-consumer-check-period>
<auto-create-queues>true</auto-create-queues>
<auto-delete-queues>true</auto-delete-queues>
</address-setting> </address-setting>
</address-settings> </address-settings>
@ -176,3 +178,13 @@ on this notification.
`slow-consumer-check-period`. How often to check for slow consumers on a `slow-consumer-check-period`. How often to check for slow consumers on a
particular queue. Measured in minutes. Default is 5. See ? for more particular queue. Measured in minutes. Default is 5. See ? for more
information about slow consumer detection. 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.

View File

@ -52,11 +52,6 @@ under the License.
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.javaee</groupId>
<artifactId>jboss-jms-api</artifactId>
<version>1.1.0.GA</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_2.0_spec</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>

View File

@ -52,11 +52,6 @@ under the License.
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.javaee</groupId>
<artifactId>jboss-jms-api</artifactId>
<version>1.1.0.GA</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_2.0_spec</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>

View File

@ -48,11 +48,6 @@ under the License.
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
<version>${netty.version}</version> <version>${netty.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.javaee</groupId>
<artifactId>jboss-jms-api</artifactId>
<version>1.1.0.GA</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.activemq.examples.jms</groupId> <groupId>org.apache.activemq.examples.jms</groupId>
<artifactId>activemq-jms-examples-common</artifactId> <artifactId>activemq-jms-examples-common</artifactId>
@ -128,11 +123,6 @@ under the License.
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
<version>${netty.version}</version> <version>${netty.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.javaee</groupId>
<artifactId>jboss-jms-api</artifactId>
<version>1.1.0.GA</version>
</dependency>
</dependencies> </dependencies>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -57,9 +57,8 @@ under the License.
<version>${netty.version}</version> <version>${netty.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jboss.javaee</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>jboss-jms-api</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>
<version>1.1.0.GA</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
@ -158,11 +157,6 @@ under the License.
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
<version>${netty.version}</version> <version>${netty.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.javaee</groupId>
<artifactId>jboss-jms-api</artifactId>
<version>1.1.0.GA</version>
</dependency>
<dependency> <dependency>
<groupId>io.vertx</groupId> <groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId> <artifactId>vertx-core</artifactId>

View File

@ -51,12 +51,8 @@ under the License.
<artifactId>geronimo-jms_2.0_spec</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>
</exclusion> </exclusion>
<exclusion> <exclusion>
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-ejb_3.0_spec</artifactId> <artifactId>geronimo-ejb_3.0_spec</artifactId>
</exclusion>
<exclusion>
<groupId>jboss.jbossts.jts</groupId>
<artifactId>jbossjts-jacorb</artifactId>
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>

View File

@ -140,7 +140,6 @@ under the License.
<dependency> <dependency>
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_2.0_spec</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>
<version>${geronimo.jms.2.spec.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<configuration> <configuration>

View File

@ -30,7 +30,7 @@ under the License.
<applet code="org.apache.activemq.jms.example.AppletExample.class" <applet code="org.apache.activemq.jms.example.AppletExample.class"
codebase="build/classes/" codebase="build/classes/"
archive="activemq-core-client.jar,activemq-jms-client.jar,jboss-jms-api.jar,netty.jar" archive="activemq-core-client.jar,activemq-jms-client.jar,geronimo-jms_2.0_spec.jar,netty.jar"
width="640" height="480"></applet> width="640" height="480"></applet>
</body> </body>
</html> </html>

View File

@ -70,8 +70,6 @@ under the License.
<goal>start</goal> <goal>start</goal>
</goals> </goals>
<configuration> <configuration>
<jndiPort>1199</jndiPort>
<jndiRmiPort>1198</jndiRmiPort>
<configurationDir>${basedir}/target/classes/activemq/server1</configurationDir> <configurationDir>${basedir}/target/classes/activemq/server1</configurationDir>
<fork>true</fork> <fork>true</fork>
</configuration> </configuration>

View File

@ -57,7 +57,6 @@ public class EmbeddedExample extends ActiveMQExample
System.out.println("Started Embedded JMS Server"); System.out.println("Started Embedded JMS Server");
JMSServerManager jmsServerManager = jmsServer.getJMSServerManager(); JMSServerManager jmsServerManager = jmsServer.getJMSServerManager();
jmsServerManager.addQueueToJndi("exampleQueue", "queue/exampleQueue");
List<String> connectors = new ArrayList<String>(); List<String> connectors = new ArrayList<String>();
connectors.add("in-vm"); connectors.add("in-vm");
jmsServerManager.createConnectionFactory("ConnectionFactory", false, JMSFactoryType.CF, connectors, "ConnectionFactory"); jmsServerManager.createConnectionFactory("ConnectionFactory", false, JMSFactoryType.CF, connectors, "ConnectionFactory");

View File

@ -71,8 +71,6 @@ under the License.
<goal>start</goal> <goal>start</goal>
</goals> </goals>
<configuration> <configuration>
<jndiPort>1199</jndiPort>
<jndiRmiPort>1198</jndiRmiPort>
<configurationDir>${basedir}/target/classes/activemq/server1</configurationDir> <configurationDir>${basedir}/target/classes/activemq/server1</configurationDir>
<fork>true</fork> <fork>true</fork>
<systemProperties> <systemProperties>

View File

@ -118,7 +118,12 @@ under the License.
InitialContext sourceContext = createContext(sourceServer); InitialContext sourceContext = createContext(sourceServer);
InitialContext targetContext = createContext(targetServer); InitialContext targetContext = createContext(targetServer);
</pre> </pre>
<li>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</li> <li>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.
<pre class="prettyprint"> <pre class="prettyprint">
JMSBridge jmsBridge = new JMSBridgeImpl( JMSBridge jmsBridge = new JMSBridgeImpl(
new JNDIConnectionFactoryFactory(sourceJndiParams, "source/ConnectionFactory"), new JNDIConnectionFactoryFactory(sourceJndiParams, "source/ConnectionFactory"),
@ -132,13 +137,12 @@ under the License.
null, null,
5000, 5000,
10, 10,
QualityOfServiceMode.ONCE_AND_ONLY_ONCE, QualityOfServiceMode.DUPLICATES_OK,
1, 1,
-1, -1,
null, null,
null, null,
true); true);
jmsBridge.setTransactionManager(new TransactionManagerImple());
.... ....
jmsBridge.start(); jmsBridge.start();
</pre> </pre>

View File

@ -16,7 +16,6 @@
*/ */
package org.apache.activemq.jms.example; 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.JMSBridge;
import org.apache.activemq.jms.bridge.QualityOfServiceMode; import org.apache.activemq.jms.bridge.QualityOfServiceMode;
import org.apache.activemq.jms.bridge.impl.JMSBridgeImpl; import org.apache.activemq.jms.bridge.impl.JMSBridgeImpl;
@ -77,13 +76,12 @@ public class JMSBridgeExample
null, null,
5000, 5000,
10, 10,
QualityOfServiceMode.ONCE_AND_ONLY_ONCE, QualityOfServiceMode.DUPLICATES_OK,
1, 1,
-1, -1,
null, null,
null, null,
true); true);
jmsBridge.setTransactionManager(new TransactionManagerImple());
Connection sourceConnection = null; Connection sourceConnection = null;
Connection targetConnection = null; Connection targetConnection = null;

View File

@ -49,9 +49,8 @@ under the License.
<version>${netty.version}</version> <version>${netty.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jboss.javaee</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>jboss-jms-api</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>
<version>1.1.0.GA</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.activemq.examples.jms</groupId> <groupId>org.apache.activemq.examples.jms</groupId>
@ -129,9 +128,8 @@ under the License.
<version>${netty.version}</version> <version>${netty.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jboss.javaee</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>jboss-jms-api</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>
<version>1.1.0.GA</version>
</dependency> </dependency>
</dependencies> </dependencies>
</plugin> </plugin>

View File

@ -128,7 +128,6 @@ under the License.
<module>xa-heuristic</module> <module>xa-heuristic</module>
<module>xa-receive</module> <module>xa-receive</module>
<module>xa-send</module> <module>xa-send</module>
<module>xa-with-jta</module>
</modules> </modules>
</profile> </profile>
<profile> <profile>

View File

@ -48,11 +48,6 @@ under the License.
<artifactId>netty-all</artifactId> <artifactId>netty-all</artifactId>
<version>${netty.version}</version> <version>${netty.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.javaee</groupId>
<artifactId>jboss-jms-api</artifactId>
<version>1.1.0.GA</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_2.0_spec</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>
@ -130,9 +125,8 @@ under the License.
<version>${netty.version}</version> <version>${netty.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jboss.javaee</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>jboss-jms-api</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>
<version>1.1.0.GA</version>
</dependency> </dependency>
</dependencies> </dependencies>
</plugin> </plugin>

View File

@ -75,8 +75,6 @@ under the License.
<goal>start</goal> <goal>start</goal>
</goals> </goals>
<configuration> <configuration>
<jndiPort>1199</jndiPort>
<jndiRmiPort>1198</jndiRmiPort>
<configurationDir>${basedir}/target/classes/activemq/server1</configurationDir> <configurationDir>${basedir}/target/classes/activemq/server1</configurationDir>
<fork>true</fork> <fork>true</fork>
<systemProperties> <systemProperties>

View File

@ -82,8 +82,10 @@ public class SymmetricClusterExample extends ActiveMQExample
// connection factory directly we avoid having to worry about a JNDI look-up. // 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 // 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. // having to know about a specific one.
UDPBroadcastGroupConfiguration udpCfg = new UDPBroadcastGroupConfiguration("231.7.7.7", 9876, null, -1); UDPBroadcastGroupConfiguration udpCfg = new UDPBroadcastGroupConfiguration();
DiscoveryGroupConfiguration groupConfiguration = new DiscoveryGroupConfiguration(ActiveMQClient.DEFAULT_DISCOVERY_INITIAL_WAIT_TIMEOUT, ActiveMQClient.DEFAULT_DISCOVERY_INITIAL_WAIT_TIMEOUT, udpCfg); udpCfg.setGroupAddress("231.7.7.7").setGroupPort(9876);
DiscoveryGroupConfiguration groupConfiguration = new DiscoveryGroupConfiguration();
groupConfiguration.setBroadcastEndpointFactoryConfiguration(udpCfg);
ConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithHA(groupConfiguration, JMSFactoryType.CF); ConnectionFactory cf = ActiveMQJMSClient.createConnectionFactoryWithHA(groupConfiguration, JMSFactoryType.CF);

View File

@ -42,11 +42,6 @@ under the License.
<groupId>org.apache.geronimo.specs</groupId> <groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_2.0_spec</artifactId> <artifactId>geronimo-jms_2.0_spec</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.jbossts.jts</groupId>
<artifactId>jbossjts-jacorb</artifactId>
<version>4.17.4.Final</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -1,142 +0,0 @@
<?xml version='1.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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.activemq.examples.jms</groupId>
<artifactId>jms-examples</artifactId>
<version>6.0.0-SNAPSHOT</version>
</parent>
<artifactId>activemq-jms-xa-with-jta-example</artifactId>
<packaging>jar</packaging>
<name>ActiveMQ6 JMS XA with JTA Example</name>
<dependencies>
<dependency>
<groupId>org.apache.activemq.examples.jms</groupId>
<artifactId>activemq-jms-examples-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_2.0_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-ejb_3.0_spec</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.jbossts</groupId>
<artifactId>jbossjta</artifactId>
<version>4.16.4.Final</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.1_spec</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-maven-plugin</artifactId>
<executions>
<execution>
<id>start</id>
<goals>
<goal>start</goal>
</goals>
<configuration>
<systemProperties>
<property>
<name>build.directory</name>
<value>${basedir}/target/</value>
</property>
</systemProperties>
</configuration>
</execution>
<execution>
<id>runClient</id>
<goals>
<goal>runClient</goal>
</goals>
<configuration>
<clientClass>org.apache.activemq.jms.example.XAwithJTAExample</clientClass>
</configuration>
</execution>
<execution>
<id>stop</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.activemq.examples.jms</groupId>
<artifactId>activemq-jms-xa-with-jta-example</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-jms-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-jms-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_2.0_spec</artifactId>
<version>${geronimo.jms.2.spec.version}</version>
</dependency>
</dependencies>
<configuration>
<waitOnStart>false</waitOnStart>
<configurationDir>${basedir}/target/classes/activemq/server0</configurationDir>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -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.
-->
<html>
<head>
<title>ActiveMQ JMS XA with JTA Example</title>
<link rel="stylesheet" type="text/css" href="../common/common.css" />
<link rel="stylesheet" type="text/css" href="../common/prettify.css" />
<script type="text/javascript" src="../common/prettify.js"></script>
</head>
<body onload="prettyPrint()">
<h1>JMS XA with JTA Example</h1>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<h2>Example step-by-step</h2>
<p><i>To run the example, simply type <code>mvn verify</code> from this directory. It will download the JBoss JTA jars before
it launches the example.</i></p>
<ol>
<li>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 <code>client-jndi.properties</code> file in the directory <code>../common/config</code></li>
<pre class="prettyprint">
<code>InitialContext initialContext = getContext(0);</code>
</pre>
<li>We look-up the JMS queue object from JNDI</li>
<pre class="prettyprint">
<code>Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");</code>
</pre>
<li>We perform a lookup on the XA Connection Factory</li>
<pre class="prettyprint">
<code>XAConnectionFactory cf = (XAConnectionFactory) initialContext.lookup("/XAConnectionFactory");</code>
</pre>
<li>We create a JMS XAConnection</li>
<pre class="prettyprint">
<code>connection = cf.createXAConnection();</code>
</pre>
<li>We Start the connection</li>
<pre class="prettyprint">
<code>connection.start();</code>
</pre>
<li>We create a JMS XASession</li>
<pre class="prettyprint">
<code>XASession xaSession = connection.createXASession();</code>
</pre>
<li>We create a normal session</li>
<pre class="prettyprint">
<code>Session normalSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);</code>
</pre>
<li>We create a normal Message Producer</li>
<pre class="prettyprint">
<code>
MessageProducer normalProducer = normalSession.createProducer(queue);
</code>
</pre>
<li>We get the JMS Session</li>
<pre class="prettyprint">
<code>Session session = xaSession.getSession();</code>
</pre>
<li>We create a message consumer</li>
<pre class="prettyprint">
<code>MessageConsumer xaConsumer = session.createConsumer(queue); </code>
</pre>
<li>We create two Text Messages</li>
<pre class="prettyprint">
<code>
TextMessage helloMessage = session.createTextMessage("hello");
TextMessage worldMessage = session.createTextMessage("world");
</code>
</pre>
<li>We get the Transaction Manager</li>
<pre class="prettyprint">
<code>javax.transaction.TransactionManager txMgr = TransactionManager.transactionManager();</code>
</pre>
<li>We start a transaction</li>
<pre class="prettyprint">
<code>txMgr.begin();</code>
</pre>
<li>We get the JMS XAResource</li>
<pre class="prettyprint">
<code>XAResource xaRes = xaSession.getXAResource();</code>
</pre>
<li>We enlist the resources in the Transaction work</li>
<pre class="prettyprint">
<code>
Transaction transaction = txMgr.getTransaction();
transaction.enlistResource(new DummyXAResource());
transaction.enlistResource(xaRes);
</code>
</pre>
<li>We send two messages.</li>
<pre class="prettyprint">
<code>
normalProducer.send(helloMessage);
normalProducer.send(worldMessage);
</code>
</pre>
<li>We receive the messages</li>
<pre class="prettyprint">
<code>
TextMessage rm1 = (TextMessage)xaConsumer.receive();
System.out.println("Message received: " + rm1.getText());
TextMessage rm2 = (TextMessage)xaConsumer.receive();
System.out.println("Message received: " + rm2.getText());
</code>
</pre>
<li>We roll back the transaction</li>
<pre class="prettyprint">
<code>txMgr.rollback();</code>
</pre>
<li>We create another transaction </li>
<pre class="prettyprint">
<code>
txMgr.begin();
transaction = txMgr.getTransaction();
</code>
</pre>
<li>We enlist the resources to start the transaction work</li>
<pre class="prettyprint">
<code>
transaction.enlistResource(new DummyXAResource());
transaction.enlistResource(xaRes);
</code>
</pre>
<li>We receive those messages again</li>
<pre class="prettyprint">
<code>
rm1 = (TextMessage)xaConsumer.receive();
System.out.println("Message received again: " + rm1.getText());
rm2 = (TextMessage)xaConsumer.receive();
System.out.println("Message received again: " + rm2.getText());
</code>
</pre>
<li>We commit</li>
<pre class="prettyprint">
<code>txMgr.commit();</code>
</pre>
<li>We check that no more messages are received.</li>
<pre class="prettyprint">
<code>
TextMessage rm3 = (TextMessage)xaConsumer.receive(2000);
if (rm3 == null)
{
System.out.println("No message received after commit.");
}
else
{
result = false;
}
</code>
</pre>
<li>And finally, <b>always</b> remember to close your JMS connections and resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li>
<pre class="prettyprint">
<code>finally
{
if (initialContext != null)
{
initialContext.close();
}
if (connection != null)
{
connection.close();
}
}</code>
</pre>
</ol>
</body>
</html>

View File

@ -1,222 +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 com.arjuna.ats.jta.TransactionManager;
import org.apache.activemq.common.example.ActiveMQExample;
/**
* A simple JMS example showing the ActiveMQ XA support with JTA.
*
* @author <a href="hgao@redhat.com">Howard Gao</a>
*/
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);
}
}
}

View File

@ -1,54 +0,0 @@
<?xml version='1.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.
-->
<configuration xmlns="urn:activemq"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:activemq /schema/activemq-configuration.xsd">
<bindings-directory>${build.directory}/server0/data/messaging/bindings</bindings-directory>
<journal-directory>${build.directory}/server0/data/messaging/journal</journal-directory>
<large-messages-directory>${build.directory}/server0/data/messaging/largemessages</large-messages-directory>
<paging-directory>${build.directory}/server0/data/messaging/paging</paging-directory>
<!-- Acceptors -->
<acceptors>
<acceptor name="netty-acceptor">
<factory-class>org.apache.activemq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
</acceptor>
</acceptors>
<!-- Other config -->
<security-settings>
<!--security for example queue-->
<security-setting match="jms.queue.exampleQueue">
<permission type="createDurableQueue" roles="guest"/>
<permission type="deleteDurableQueue" roles="guest"/>
<permission type="createNonDurableQueue" roles="guest"/>
<permission type="deleteNonDurableQueue" roles="guest"/>
<permission type="consume" roles="guest"/>
<permission type="send" roles="guest"/>
</security-setting>
</security-settings>
</configuration>

View File

@ -1,28 +0,0 @@
<?xml version='1.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.
-->
<configuration xmlns="urn:activemq"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:activemq /schema/activemq-jms.xsd">
<!--the queue used by the example-->
<queue name="exampleQueue"/>
</configuration>

View File

@ -1,27 +0,0 @@
<?xml version='1.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.
-->
<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:activemq /schema/activemq-users.xsd">
<!-- the default user. this is used where username is null-->
<defaultuser name="guest" password="guest">
<role name="guest"/>
</defaultuser>
</configuration>

View File

@ -1,175 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<!--
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.
-->
<properties>
<!--
This is the JBossTS configuration file for running ArjunaJTS.
It should be called jbossts-properties.xml.
You need a different version for ArjunaCore or JTA usage.
***************************
Property values may be literals or be tokens of the form ${p1[,p2][:v]}
in which case the token values are substituted for the values of the corresponding system
properties as follows:
- Any occurrence of ${p} with the System.getProperty(p) value.
If there is no such property p defined, then the ${p} reference will remain unchanged.
- If the property reference is of the form ${p:v} and there is no such property p,
then the default value v will be returned.
- If the property reference is of the form ${p1,p2} or ${p1,p2:v} then
the primary and the secondary properties will be tried in turn, before
returning either the unchanged input, or the default value.
The property ${/} is replaced with System.getProperty("file.separator")
value and the property ${:} is replaced with System.getProperty("path.separator").
Note this substitution applies to property values only at the point they are read from
the config file. Tokens in system properties won't be substituted.
-->
<!-- (default is YES) -->
<entry key="CoordinatorEnvironmentBean.commitOnePhase">YES</entry>
<!-- default is under user.home - must be writeable!) -->
<entry key="ObjectStoreEnvironmentBean.objectStoreDir">PutObjectStoreDirHere</entry>
<!-- (default is ON) -->
<entry key="ObjectStoreEnvironmentBean.transactionSync">ON</entry>
<!-- (Must be unique across all Arjuna instances.) -->
<entry key="CoreEnvironmentBean.nodeIdentifier">1</entry>
<!-- Which Xid types to recover -->
<entry key="JTAEnvironmentBean.xaRecoveryNodes">1</entry>
<entry key="JTAEnvironmentBean.xaResourceOrphanFilterClassNames">
com.arjuna.ats.internal.jta.recovery.arjunacore.JTATransactionLogXAResourceOrphanFilter
com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter
</entry>
<!--
Base port number for determining a unique number to associate with an instance of the transaction service
(which is needed in order to support multiple instances on the same machine).
Use the value 0 to allow the system to select the first available port number.
If the port number is non-zero and the port is in use then the value will be incremented until either a successful binding
to the loopback address is created or until the the maximum number of ports (specified by the
CoreEnvironmentBean.socketProcessIdMaxPorts property) have been tried or until the port number
reaches the maximum possible port number.
-->
<entry key="CoreEnvironmentBean.socketProcessIdPort">0</entry>
<!--
Periodic recovery modules to use. Invoked in the order they appear in the list.
Check http://www.jboss.org/community/docs/DOC-10788 for more information
on recovery modules and their configuration when running in various
deployments.
-->
<entry key="RecoveryEnvironmentBean.recoveryModuleClassNames">
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
</entry>
<!-- Expiry scanners to use (order of invocation is random). -->
<entry key="RecoveryEnvironmentBean.expiryScannerClassNames">
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
</entry>
<!--
Add the following to the set of expiryScannerClassNames above to move logs that cannot be completed by failure recovery.
But be sure you know what you are doing and why!
com.arjuna.ats.internal.arjuna.recovery.AtomicActionExpiryScanner
-->
<!--
The address and port number on which the recovery manager listens
If running within an AS then the address the AS is bound to (jboss.bind.address) takes precedence
-->
<entry key="RecoveryEnvironmentBean.recoveryPort">4712</entry>
<entry key="RecoveryEnvironmentBean.recoveryAddress"></entry>
<!--
Use this to fix the port on which the TransactionStatusManager listens,
The default behaviour is to use any free port.
-->
<entry key="RecoveryEnvironmentBean.transactionStatusManagerPort">0</entry>
<!--
Use this to fix the address on which the TransactionStatusManager binds,
The default behaviour is to use the loopback address (ie localhost).
If running within an AS then the address the AS is bound to (jboss.bind.address) takes precedence
-->
<entry key="RecoveryEnvironmentBean.transactionStatusManagerAddress"></entry>
<!--
For cases where the recovery manager is in process with the transaction manager and nothing else uses
the ObjectStore, it is possible to disable the socket based recovery listener by setting this to NO.
Caution: use of this property can allow multiple recovery processes to run on the same ObjectStore
if you are not careful. That in turn can lead to incorrect transaction processing. Use with care.
-->
<entry key="RecoveryEnvironmentBean.recoveryListener">YES</entry>
<!-- Recovery Activators to use. -->
<entry key="RecoveryEnvironmentBean.recoveryActivatorClassNames">com.arjuna.ats.internal.jts.orbspecific.recovery.RecoveryEnablement</entry>
<entry key="JTAEnvironmentBean.transactionManagerClassName">com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple</entry>
<entry key="JTAEnvironmentBean.userTransactionClassName">com.arjuna.ats.internal.jta.transaction.arjunacore.UserTransactionImple</entry>
<entry key="JTAEnvironmentBean.transactionSynchronizationRegistryClassName">com.arjuna.ats.internal.jta.transaction.jts.TransactionSynchronizationRegistryImple</entry>
<entry key="OrbPortabilityEnvironmentBean.bindMechanism">CONFIGURATION_FILE</entry>
<entry key="OrbPortabilityEnvironmentBean.orbInitializationProperties">
<!-- This class handles context propagation issues, and should never be commented out or removed. -->
com.arjuna.orbportability.orb.PreInit1=com.arjuna.ats.internal.jts.context.ContextPropagationManager
<!-- This property ensures the JTS knows which ORB to use and should never be commented out or removed -->
com.arjuna.orbportability.orb.PostInit=com.arjuna.ats.jts.utils.ORBSetup
<!-- This property ensures the crash recovery is initialised correctly and should never be commented out or removed -->
com.arjuna.orbportability.orb.PostInit2=com.arjuna.ats.internal.jts.recovery.RecoveryInit
<!-- This property ensures the JTS knows which ORB to use and should never be commented out or removed -->
com.arjuna.orbportability.orb.PostSet1=com.arjuna.ats.jts.utils.ORBSetup
</entry>
<!--
This property controls the port on which the Recovery ORB listens
-->
<entry key="JTSEnvironmentBean.recoveryManagerPort">4711</entry>
<!--
This property controls the address on which the Recovery ORB binds - defaults to the loopback connection
If running within an AS then the address the AS is bound to (jboss.bind.address) takes precedence
-->
<entry key="JTSEnvironmentBean.recoveryManagerAddress"></entry>
</properties>

View File

@ -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

View File

@ -49,7 +49,7 @@
<activemq.version.majorVersion>6</activemq.version.majorVersion> <activemq.version.majorVersion>6</activemq.version.majorVersion>
<activemq.version.minorVersion>0</activemq.version.minorVersion> <activemq.version.minorVersion>0</activemq.version.minorVersion>
<activemq.version.microVersion>0</activemq.version.microVersion> <activemq.version.microVersion>0</activemq.version.microVersion>
<activemq.version.incrementingVersion>125,124,123,122</activemq.version.incrementingVersion> <activemq.version.incrementingVersion>126,125,124,123,122</activemq.version.incrementingVersion>
<activemq.version.versionSuffix>SNAPSHOT</activemq.version.versionSuffix> <activemq.version.versionSuffix>SNAPSHOT</activemq.version.versionSuffix>
<activemq.version.versionTag>SNAPSHOT</activemq.version.versionTag> <activemq.version.versionTag>SNAPSHOT</activemq.version.versionTag>
<ActiveMQ-Version> <ActiveMQ-Version>
@ -414,7 +414,7 @@
<repositories> <repositories>
<repository> <repository>
<snapshots> <snapshots>
<enabled>false</enabled> <enabled>true</enabled>
<updatePolicy>never</updatePolicy> <updatePolicy>never</updatePolicy>
</snapshots> </snapshots>
<releases> <releases>
@ -916,6 +916,7 @@
<exclude>etc/org.eclipse.*</exclude> <exclude>etc/org.eclipse.*</exclude>
<exclude>docs/user-manual/en/*.json</exclude> <exclude>docs/user-manual/en/*.json</exclude>
<exclude>**/target/</exclude> <exclude>**/target/</exclude>
<exclude>**/data/</exclude>
<exclude>**/*.bindings</exclude> <exclude>**/*.bindings</exclude>
<exclude>**/*.lock</exclude> <exclude>**/*.lock</exclude>
<exclude>**/META-INF/services/*</exclude> <exclude>**/META-INF/services/*</exclude>

View File

@ -77,6 +77,7 @@ public class QueueTest extends UnitTestCase
null, null,
null, null,
false, false,
false,
false); false);
FakeConsumer consumer = new FakeConsumer(); FakeConsumer consumer = new FakeConsumer();

View File

@ -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<Role> roles = new HashSet<Role>();
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<Role> roles = new HashSet<Role>();
roles.add(role);
server.getSecurityRepository().addMatch("#", roles);
}
protected boolean useSecurity()
{
return true;
}
}

View File

@ -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")));
}
}

View File

@ -16,7 +16,6 @@
*/ */
package org.apache.activemq.tests.integration.client; package org.apache.activemq.tests.integration.client;
import org.apache.activemq.api.core.ActiveMQException; import org.apache.activemq.api.core.ActiveMQException;
import org.apache.activemq.core.server.MessageReference;
import org.apache.activemq.core.server.ServerConsumer; import org.apache.activemq.core.server.ServerConsumer;
import org.junit.Before; import org.junit.Before;
import org.junit.After; import org.junit.After;
@ -24,7 +23,6 @@ import org.junit.Test;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@ -244,6 +242,7 @@ public class HangConsumerTest extends ServiceTestBase
final PageSubscription pageSubscription, final PageSubscription pageSubscription,
final boolean durable, final boolean durable,
final boolean temporary, final boolean temporary,
final boolean autoCreated,
final ScheduledExecutorService scheduledExecutor, final ScheduledExecutorService scheduledExecutor,
final PostOffice postOffice, final PostOffice postOffice,
final StorageManager storageManager, final StorageManager storageManager,
@ -257,6 +256,7 @@ public class HangConsumerTest extends ServiceTestBase
pageSubscription, pageSubscription,
durable, durable,
temporary, temporary,
autoCreated,
scheduledExecutor, scheduledExecutor,
postOffice, postOffice,
storageManager, storageManager,
@ -274,9 +274,8 @@ public class HangConsumerTest extends ServiceTestBase
} }
@Override @Override
public List<MessageReference> cancelScheduledMessages() public void deliverScheduledMessages()
{ {
return null;
} }
} }
@ -297,7 +296,8 @@ public class HangConsumerTest extends ServiceTestBase
final Filter filter, final Filter filter,
final PageSubscription pageSubscription, final PageSubscription pageSubscription,
final boolean durable, final boolean durable,
final boolean temporary) final boolean temporary,
final boolean autoCreated)
{ {
queue = new MyQueueWithBlocking(persistenceID, queue = new MyQueueWithBlocking(persistenceID,
address, address,
@ -306,6 +306,7 @@ public class HangConsumerTest extends ServiceTestBase
pageSubscription, pageSubscription,
durable, durable,
temporary, temporary,
autoCreated,
scheduledExecutor, scheduledExecutor,
postOffice, postOffice,
storageManager, storageManager,
@ -404,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 // 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().addQueueBinding(txID, newBinding);
server.getStorageManager().commitBindings(txID); server.getStorageManager().commitBindings(txID);

View File

@ -20,7 +20,6 @@ import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid; import javax.transaction.xa.Xid;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
@ -507,6 +506,7 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase
PageSubscription pageSubscription, PageSubscription pageSubscription,
boolean durable, boolean durable,
boolean temporary, boolean temporary,
boolean autoCreated,
ScheduledExecutorService scheduledExecutor, ScheduledExecutorService scheduledExecutor,
PostOffice postOffice, PostOffice postOffice,
StorageManager storageManager, StorageManager storageManager,
@ -520,6 +520,7 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase
pageSubscription, pageSubscription,
durable, durable,
temporary, temporary,
autoCreated,
scheduledExecutor, scheduledExecutor,
postOffice, postOffice,
storageManager, storageManager,
@ -534,9 +535,8 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase
} }
@Override @Override
public List<MessageReference> cancelScheduledMessages() public void deliverScheduledMessages()
{ {
return null;
} }
} }
@ -572,7 +572,8 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase
Filter filter, Filter filter,
PageSubscription pageSubscription, PageSubscription pageSubscription,
boolean durable, boolean durable,
boolean temporary) boolean temporary,
boolean autoCreated)
{ {
return new NoPostACKQueue(persistenceID, return new NoPostACKQueue(persistenceID,
@ -582,6 +583,7 @@ public class InterruptedLargeMessageTest extends LargeMessageTestBase
pageSubscription, pageSubscription,
durable, durable,
temporary, temporary,
autoCreated,
scheduledExecutor, scheduledExecutor,
postOffice, postOffice,
storageManager, storageManager,

View File

@ -749,7 +749,9 @@ public class PagingOrderTest extends ServiceTestBase
"PAGE", "PAGE",
-1, -1,
10, 10,
"KILL"); "KILL",
true,
true);
ActiveMQJMSConnectionFactory cf = (ActiveMQJMSConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, ActiveMQJMSConnectionFactory cf = (ActiveMQJMSConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF,
new TransportConfiguration(INVM_CONNECTOR_FACTORY)); new TransportConfiguration(INVM_CONNECTOR_FACTORY));
@ -824,7 +826,9 @@ public class PagingOrderTest extends ServiceTestBase
"PAGE", "PAGE",
-1, -1,
10, 10,
"KILL"); "KILL",
true,
true);
jmsServer.createQueue(true, "Q1", null, true, "/queue/Q1"); jmsServer.createQueue(true, "Q1", null, true, "/queue/Q1");

View File

@ -62,6 +62,7 @@ import org.apache.activemq.core.postoffice.Bindings;
import org.apache.activemq.core.postoffice.PostOffice; import org.apache.activemq.core.postoffice.PostOffice;
import org.apache.activemq.core.postoffice.QueueBinding; import org.apache.activemq.core.postoffice.QueueBinding;
import org.apache.activemq.core.postoffice.impl.LocalQueueBinding; 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.remoting.impl.netty.TransportConstants;
import org.apache.activemq.core.server.ActiveMQServer; import org.apache.activemq.core.server.ActiveMQServer;
import org.apache.activemq.core.server.ActiveMQServers; import org.apache.activemq.core.server.ActiveMQServers;
@ -1681,7 +1682,8 @@ public abstract class ClusterTestBase extends ServiceTestBase
.setThreadPoolMaxSize(10) .setThreadPoolMaxSize(10)
.clearAcceptorConfigurations() .clearAcceptorConfigurations()
.addAcceptorConfiguration(createTransportConfiguration(netty, true, generateParams(node, netty))) .addAcceptorConfiguration(createTransportConfiguration(netty, true, generateParams(node, netty)))
.setHAPolicyConfiguration(haPolicyConfiguration); .setHAPolicyConfiguration(haPolicyConfiguration)
.setResolveProtocols(false);
ActiveMQServer server; ActiveMQServer server;
@ -1708,6 +1710,8 @@ public abstract class ClusterTestBase extends ServiceTestBase
} }
} }
server.addProtocolManagerFactory(new CoreProtocolManagerFactory());
server.setIdentity(this.getClass().getSimpleName() + "/Live(" + node + ")"); server.setIdentity(this.getClass().getSimpleName() + "/Live(" + node + ")");
servers[node] = server; servers[node] = server;
} }

View File

@ -82,7 +82,7 @@ public class TopicCleanupTest extends JMSTestBase
{ {
long txid = storage.generateID(); 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()); storage, server.getAddressSettingsRepository(), server.getExecutorFactory().getExecutor());
LocalQueueBinding binding = new LocalQueueBinding(queue.getAddress(), queue, server.getNodeID()); LocalQueueBinding binding = new LocalQueueBinding(queue.getAddress(), queue, server.getNodeID());

View File

@ -62,7 +62,7 @@ public class NonExistentQueueTest extends JMSTestBase
@Test @Test
public void sendToNonExistantDestination() throws Exception public void sendToNonExistantDestination() throws Exception
{ {
Destination destination = ActiveMQJMSClient.createQueue("DoesNotExist"); Destination destination = ActiveMQJMSClient.createTopic("DoesNotExist");
TransportConfiguration transportConfiguration = new TransportConfiguration(InVMConnectorFactory.class.getName()); TransportConfiguration transportConfiguration = new TransportConfiguration(InVMConnectorFactory.class.getName());
ConnectionFactory localConnectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, ConnectionFactory localConnectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF,
transportConfiguration); transportConfiguration);

View File

@ -507,6 +507,8 @@ public class ActiveMQServerControlTest extends ManagementTestBase
long slowConsumerThreshold = 5; long slowConsumerThreshold = 5;
long slowConsumerCheckPeriod = 10; long slowConsumerCheckPeriod = 10;
String slowConsumerPolicy = SlowConsumerPolicy.KILL.toString(); String slowConsumerPolicy = SlowConsumerPolicy.KILL.toString();
boolean autoCreateJmsQueues = false;
boolean autoDeleteJmsQueues = false;
serverControl.addAddressSettings(addressMatch, serverControl.addAddressSettings(addressMatch,
DLA, DLA,
@ -525,7 +527,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase
addressFullMessagePolicy, addressFullMessagePolicy,
slowConsumerThreshold, slowConsumerThreshold,
slowConsumerCheckPeriod, slowConsumerCheckPeriod,
slowConsumerPolicy); slowConsumerPolicy,
autoCreateJmsQueues,
autoDeleteJmsQueues);
boolean ex = false; boolean ex = false;
@ -548,7 +552,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase
addressFullMessagePolicy, addressFullMessagePolicy,
slowConsumerThreshold, slowConsumerThreshold,
slowConsumerCheckPeriod, slowConsumerCheckPeriod,
slowConsumerPolicy); slowConsumerPolicy,
autoCreateJmsQueues,
autoDeleteJmsQueues);
} }
catch (Exception expected) catch (Exception expected)
{ {
@ -578,6 +584,8 @@ public class ActiveMQServerControlTest extends ManagementTestBase
assertEquals(slowConsumerThreshold, info.getSlowConsumerThreshold()); assertEquals(slowConsumerThreshold, info.getSlowConsumerThreshold());
assertEquals(slowConsumerCheckPeriod, info.getSlowConsumerCheckPeriod()); assertEquals(slowConsumerCheckPeriod, info.getSlowConsumerCheckPeriod());
assertEquals(slowConsumerPolicy, info.getSlowConsumerPolicy()); assertEquals(slowConsumerPolicy, info.getSlowConsumerPolicy());
assertEquals(autoCreateJmsQueues, info.isAutoCreateJmsQueues());
assertEquals(autoDeleteJmsQueues, info.isAutoDeleteJmsQueues());
serverControl.addAddressSettings(addressMatch, serverControl.addAddressSettings(addressMatch,
DLA, DLA,
@ -596,7 +604,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase
addressFullMessagePolicy, addressFullMessagePolicy,
slowConsumerThreshold, slowConsumerThreshold,
slowConsumerCheckPeriod, slowConsumerCheckPeriod,
slowConsumerPolicy); slowConsumerPolicy,
autoCreateJmsQueues,
autoDeleteJmsQueues);
jsonString = serverControl.getAddressSettingsAsJSON(exactAddress); jsonString = serverControl.getAddressSettingsAsJSON(exactAddress);
@ -618,6 +628,8 @@ public class ActiveMQServerControlTest extends ManagementTestBase
assertEquals(slowConsumerThreshold, info.getSlowConsumerThreshold()); assertEquals(slowConsumerThreshold, info.getSlowConsumerThreshold());
assertEquals(slowConsumerCheckPeriod, info.getSlowConsumerCheckPeriod()); assertEquals(slowConsumerCheckPeriod, info.getSlowConsumerCheckPeriod());
assertEquals(slowConsumerPolicy, info.getSlowConsumerPolicy()); assertEquals(slowConsumerPolicy, info.getSlowConsumerPolicy());
assertEquals(autoCreateJmsQueues, info.isAutoCreateJmsQueues());
assertEquals(autoDeleteJmsQueues, info.isAutoDeleteJmsQueues());
ex = false; ex = false;
@ -640,7 +652,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase
addressFullMessagePolicy, addressFullMessagePolicy,
slowConsumerThreshold, slowConsumerThreshold,
slowConsumerCheckPeriod, slowConsumerCheckPeriod,
slowConsumerPolicy); slowConsumerPolicy,
autoCreateJmsQueues,
autoDeleteJmsQueues);
} }
catch (Exception e) catch (Exception e)
{ {

View File

@ -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 = "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 = "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 = "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", proxy.invokeOperation("addAddressSettings",
addressMatch, addressMatch,
@ -602,7 +604,9 @@ public class ActiveMQServerControlUsingCoreTest extends ActiveMQServerControlTes
addressFullMessagePolicy, addressFullMessagePolicy,
slowConsumerThreshold, slowConsumerThreshold,
slowConsumerCheckPeriod, slowConsumerCheckPeriod,
slowConsumerPolicy); slowConsumerPolicy,
autoCreateJmsQueues,
autoDeleteJmsQueues);
} }
public void removeAddressSettings(String addressMatch) throws Exception public void removeAddressSettings(String addressMatch) throws Exception

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.activemq.tests.integration.persistence; package org.apache.activemq.tests.integration.persistence;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import java.io.StringReader; 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 // 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" + 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@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@AddRecordTX,txID@2,id@3,userRecordType@21,length@18,isUpdate@false,compactCount@0,data@AAAABEEAMQAAAAAEQQAxAAAA\n" +
"operation@AddRecord,id@20,userRecordType@24,length@8,isUpdate@false,compactCount@0,data@AAAAAAAAABQ=\n" + "operation@Commit,txID@2,numberOfRecords@1\n" +
"#File,JournalFileImpl: (activemq-bindings-2.bindings id = 2, recordID = 2)"; "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 // 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" + 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@AddRecordTX,txID@0,id@5,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfYEAQAAAAEAAAAGawBlAHkABgAAAAA=\n" +
"operation@UpdateTX,txID@0,id@4,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + "operation@UpdateTX,txID@0,id@5,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" +
"operation@AddRecordTX,txID@0,id@5,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP5EEAQAAAAEAAAAGawBlAHkABgAAAAE=\n" + "operation@AddRecordTX,txID@0,id@6,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABgEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfoEAQAAAAEAAAAGawBlAHkABgAAAAE=\n" +
"operation@UpdateTX,txID@0,id@5,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + "operation@UpdateTX,txID@0,id@6,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_wAAAAAAAAAAAAABLLxYP5EEAQAAAAEAAAAGawBlAHkABgAAAAI=\n" + "operation@AddRecordTX,txID@0,id@7,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAABwEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfoEAQAAAAEAAAAGawBlAHkABgAAAAI=\n" +
"operation@UpdateTX,txID@0,id@6,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + "operation@UpdateTX,txID@0,id@7,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_wAAAAAAAAAAAAABLLxYP5EEAQAAAAEAAAAGawBlAHkABgAAAAM=\n" + "operation@AddRecordTX,txID@0,id@8,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAACAEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfoEAQAAAAEAAAAGawBlAHkABgAAAAM=\n" +
"operation@UpdateTX,txID@0,id@7,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + "operation@UpdateTX,txID@0,id@8,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_wAAAAAAAAAAAAABLLxYP5EEAQAAAAEAAAAGawBlAHkABgAAAAQ=\n" + "operation@AddRecordTX,txID@0,id@9,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAACQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2CfoEAQAAAAEAAAAGawBlAHkABgAAAAQ=\n" +
"operation@UpdateTX,txID@0,id@8,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\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@Commit,txID@0,numberOfRecords@10\n" +
"operation@AddRecord,id@12,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADAEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP6gEAQAAAAEAAAAGawBlAHkABgAAAAU=\n" + "operation@AddRecord,id@13,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2Cg0EAQAAAAEAAAAGawBlAHkABgAAAAU=\n" +
"operation@Update,id@12,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + "operation@Update,id@13,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAM=\n" +
"operation@AddRecord,id@13,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABLLxYP6oEAQAAAAEAAAAGawBlAHkABgAAAAY=\n" + "operation@AddRecord,id@14,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADgEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2Cg8EAQAAAAEAAAAGawBlAHkABgAAAAY=\n" +
"operation@Update,id@13,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + "operation@Update,id@14,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_wAAAAAAAAAAAAABLLxYP6sEAQAAAAEAAAAGawBlAHkABgAAAAc=\n" + "operation@AddRecord,id@15,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAADwEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2ChMEAQAAAAEAAAAGawBlAHkABgAAAAc=\n" +
"operation@Update,id@14,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + "operation@Update,id@15,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_wAAAAAAAAAAAAABLLxYP60EAQAAAAEAAAAGawBlAHkABgAAAAg=\n" + "operation@AddRecord,id@16,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAAEAEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2ChcEAQAAAAEAAAAGawBlAHkABgAAAAg=\n" +
"operation@Update,id@15,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\n" + "operation@Update,id@16,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_wAAAAAAAAAAAAABLLxYP64EAQAAAAEAAAAGawBlAHkABgAAAAk=\n" + "operation@AddRecord,id@17,userRecordType@31,length@65,isUpdate@false,compactCount@0,data@AAAAEQAAAE4AAAAAAAAAEQEAAAAEQQAxAAAA_wAAAAAAAAAAAAABSuT2ChoEAQAAAAEAAAAGawBlAHkABgAAAAk=\n" +
"operation@Update,id@16,userRecordType@32,length@8,isUpdate@true,compactCount@0,data@AAAAAAAAAAI=\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)"; "#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); ActiveMQServer server = createServer(true);
server.start(); server.start();
@ -86,7 +90,7 @@ public class ExportFormatTest extends ServiceTestBase
ClientSessionFactory factory = createSessionFactory(locator); ClientSessionFactory factory = createSessionFactory(locator);
ClientSession session = factory.createSession(false, false, false); ClientSession session = factory.createSession(false, false, false);
session.createQueue("A1", "A1"); session.createQueue("A1", "A1", true);
ClientProducer producer = session.createProducer("A1"); ClientProducer producer = session.createProducer("A1");
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)

View File

@ -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());
}
}

View File

@ -30,8 +30,6 @@ import org.apache.activemq.api.core.client.ClientSessionFactory;
import org.apache.activemq.api.core.client.ActiveMQClient; import org.apache.activemq.api.core.client.ActiveMQClient;
import org.apache.activemq.core.config.ScaleDownConfiguration; import org.apache.activemq.core.config.ScaleDownConfiguration;
import org.apache.activemq.core.config.ha.LiveOnlyPolicyConfiguration; 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.Binding;
import org.apache.activemq.core.postoffice.impl.LocalQueueBinding; import org.apache.activemq.core.postoffice.impl.LocalQueueBinding;
import org.apache.activemq.core.settings.impl.AddressSettings; import org.apache.activemq.core.settings.impl.AddressSettings;
@ -119,13 +117,13 @@ public class ScaleDownTest extends ClusterTestBase
final String queueName2 = "testQueue2"; final String queueName2 = "testQueue2";
// create 2 queues on each node mapped to the same address // create 2 queues on each node mapped to the same address
createQueue(0, addressName, queueName1, null, false); createQueue(0, addressName, queueName1, null, true);
createQueue(0, addressName, queueName2, null, false); createQueue(0, addressName, queueName2, null, true);
createQueue(1, addressName, queueName1, null, false); createQueue(1, addressName, queueName1, null, true);
createQueue(1, addressName, queueName2, null, false); createQueue(1, addressName, queueName2, null, true);
// send messages to node 0 // 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 // consume a message from queue 2
addConsumer(1, 0, queueName2, null, false); addConsumer(1, 0, queueName2, null, false);
@ -375,32 +373,28 @@ public class ScaleDownTest extends ClusterTestBase
final String addressName = "testAddress"; final String addressName = "testAddress";
final String queueName = "testQueue"; final String queueName = "testQueue";
createQueue(0, addressName, queueName, null, false); createQueue(0, addressName, queueName, null, true);
createQueue(1, addressName, queueName, null, false); createQueue(1, addressName, queueName, null, true);
ClientSessionFactory sf = sfs[0]; ClientSessionFactory sf = sfs[0];
ClientSession session = addClientSession(sf.createSession(false, false)); ClientSession session = addClientSession(sf.createSession(false, false));
ClientProducer producer = addClientProducer(session.createProducer(addressName)); ClientProducer producer = addClientProducer(session.createProducer(addressName));
LargeServerMessageImpl fileMessage = new LargeServerMessageImpl((JournalStorageManager) servers[0].getStorageManager());
fileMessage.setMessageID(1005); byte[] buffer = new byte[2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE];
fileMessage.setDurable(true); for (int i = 0; i < buffer.length; i++)
for (int i = 0; i < 2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE; 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(); servers[0].stop();
@ -409,19 +403,23 @@ public class ScaleDownTest extends ClusterTestBase
ClientConsumer consumer = addClientConsumer(session.createConsumer(queueName)); ClientConsumer consumer = addClientConsumer(session.createConsumer(queueName));
session.start(); session.start();
ClientMessage msg = consumer.receive(250); for (int nmsg = 0; nmsg < 10; nmsg++)
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++)
{ {
Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg.getBodyBuffer().readByte()); ClientMessage msg = consumer.receive(250);
}
msg.acknowledge(); Assert.assertNotNull(msg);
session.commit();
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 @Test

View File

@ -34,6 +34,7 @@ import javax.jms.XAConnection;
import javax.jms.XASession; import javax.jms.XASession;
import org.apache.activemq.api.jms.JMSFactoryType; 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.apache.activemq.jms.tests.util.ProxyAssertSupport;
import org.junit.Test; import org.junit.Test;
@ -113,6 +114,10 @@ public class SessionTest extends ActiveMQServerTestCase
@Test @Test
public void testCreateNonExistentQueue() throws Exception public void testCreateNonExistentQueue() throws Exception
{ {
AddressSettings addressSettings = new AddressSettings();
addressSettings.setAutoCreateJmsQueues(false);
getJmsServer().getAddressSettingsRepository().addMatch("#", addressSettings);
Connection conn = getConnectionFactory().createConnection(); Connection conn = getConnectionFactory().createConnection();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
try try
@ -147,6 +152,10 @@ public class SessionTest extends ActiveMQServerTestCase
@Test @Test
public void testCreateQueueWhileTopicWithSameNameExists() throws Exception public void testCreateQueueWhileTopicWithSameNameExists() throws Exception
{ {
AddressSettings addressSettings = new AddressSettings();
addressSettings.setAutoCreateJmsQueues(false);
getJmsServer().getAddressSettingsRepository().addMatch("#", addressSettings);
Connection conn = getConnectionFactory().createConnection(); Connection conn = getConnectionFactory().createConnection();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
try try

View File

@ -81,6 +81,7 @@ public class QueueImplTest extends UnitTestCase
null, null,
false, false,
true, true,
false,
scheduledExecutor, scheduledExecutor,
null, null,
null, null,
@ -158,6 +159,7 @@ public class QueueImplTest extends UnitTestCase
null, null,
false, false,
true, true,
false,
scheduledExecutor, scheduledExecutor,
null, null,
null, null,
@ -273,6 +275,7 @@ public class QueueImplTest extends UnitTestCase
null, null,
false, false,
true, true,
false,
scheduledExecutor, scheduledExecutor,
null, null,
null, null,

View File

@ -25,7 +25,6 @@ import org.apache.activemq.api.core.SimpleString;
import org.apache.activemq.core.filter.Filter; import org.apache.activemq.core.filter.Filter;
import org.apache.activemq.core.paging.cursor.PageSubscription; import org.apache.activemq.core.paging.cursor.PageSubscription;
import org.apache.activemq.core.server.Consumer; 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.MessageReference;
import org.apache.activemq.core.server.Queue; import org.apache.activemq.core.server.Queue;
import org.apache.activemq.core.server.RoutingContext; import org.apache.activemq.core.server.RoutingContext;
@ -60,7 +59,7 @@ public class FakeQueue implements Queue
} }
@Override @Override
public void setConsumersRefCount(ActiveMQServer server) public void setConsumersRefCount(ReferenceCounter referenceCounter)
{ {
} }
@ -362,9 +361,9 @@ public class FakeQueue implements Queue
} }
@Override @Override
public List<MessageReference> cancelScheduledMessages() public void deliverScheduledMessages()
{ {
return null;
} }
@Override @Override
@ -427,6 +426,12 @@ public class FakeQueue implements Queue
return false; return false;
} }
@Override
public boolean isAutoCreated()
{
return false;
}
@Override @Override
public LinkedListIterator<MessageReference> iterator() public LinkedListIterator<MessageReference> iterator()
{ {

View File

@ -94,17 +94,7 @@ public class QueueImplTest extends UnitTestCase
{ {
final SimpleString name = new SimpleString("oobblle"); final SimpleString name = new SimpleString("oobblle");
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getNamedQueue(name);
QueueImplTest.address1,
name,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
Assert.assertEquals(name, queue.getName()); Assert.assertEquals(name, queue.getName());
} }
@ -112,31 +102,11 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testDurable() public void testDurable()
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getNonDurableQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
false,
scheduledExecutor,
null,
null,
null,
executor);
Assert.assertFalse(queue.isDurable()); Assert.assertFalse(queue.isDurable());
queue = new QueueImpl(1, queue = getDurableQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
true,
false,
scheduledExecutor,
null,
null,
null,
executor);
Assert.assertTrue(queue.isDurable()); Assert.assertTrue(queue.isDurable());
} }
@ -150,17 +120,7 @@ public class QueueImplTest extends UnitTestCase
Consumer cons3 = new FakeConsumer(); Consumer cons3 = new FakeConsumer();
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
Assert.assertEquals(0, queue.getConsumerCount()); Assert.assertEquals(0, queue.getConsumerCount());
@ -202,17 +162,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testGetFilter() public void testGetFilter()
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
Assert.assertNull(queue.getFilter()); Assert.assertNull(queue.getFilter());
@ -229,17 +179,7 @@ public class QueueImplTest extends UnitTestCase
} }
}; };
queue = new QueueImpl(1, queue = getFilteredQueue(filter);
QueueImplTest.address1,
QueueImplTest.queue1,
filter,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
Assert.assertEquals(filter, queue.getFilter()); Assert.assertEquals(filter, queue.getFilter());
@ -248,17 +188,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testSimpleadd() public void testSimpleadd()
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
final int numMessages = 10; final int numMessages = 10;
@ -278,17 +208,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testRate() throws InterruptedException public void testRate() throws InterruptedException
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
final int numMessages = 10; final int numMessages = 10;
@ -309,17 +229,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testSimpleNonDirectDelivery() throws Exception public void testSimpleNonDirectDelivery() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
final int numMessages = 10; final int numMessages = 10;
@ -358,17 +268,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testBusyConsumer() throws Exception public void testBusyConsumer() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
FakeConsumer consumer = new FakeConsumer(); FakeConsumer consumer = new FakeConsumer();
@ -413,17 +313,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testBusyConsumerThenAddMoreMessages() throws Exception public void testBusyConsumerThenAddMoreMessages() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
FakeConsumer consumer = new FakeConsumer(); FakeConsumer consumer = new FakeConsumer();
@ -491,17 +381,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testaddHeadadd() throws Exception public void testaddHeadadd() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
final int numMessages = 10; final int numMessages = 10;
@ -556,17 +436,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testChangeConsumersAndDeliver() throws Exception public void testChangeConsumersAndDeliver() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
new FakePostOffice(),
null,
null,
executor);
final int numMessages = 10; final int numMessages = 10;
@ -730,17 +600,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testRoundRobinWithQueueing() throws Exception public void testRoundRobinWithQueueing() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
final int numMessages = 10; final int numMessages = 10;
@ -793,17 +653,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testWithPriorities() throws Exception public void testWithPriorities() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
final int numMessages = 10; final int numMessages = 10;
@ -856,17 +706,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testConsumerWithFilterAddAndRemove() public void testConsumerWithFilterAddAndRemove()
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
Filter filter = new FakeFilter("fruit", "orange"); Filter filter = new FakeFilter("fruit", "orange");
@ -876,17 +716,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testIterator() public void testIterator()
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
final int numMessages = 20; final int numMessages = 20;
@ -925,17 +755,7 @@ public class QueueImplTest extends UnitTestCase
public void testConsumeWithFiltersAddAndRemoveConsumer() throws Exception public void testConsumeWithFiltersAddAndRemoveConsumer() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
new FakePostOffice(),
null,
null,
executor);
Filter filter = new FakeFilter("fruit", "orange"); Filter filter = new FakeFilter("fruit", "orange");
@ -1009,17 +829,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testBusyConsumerWithFilterFirstCallBusy() throws Exception public void testBusyConsumerWithFilterFirstCallBusy() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
FakeConsumer consumer = new FakeConsumer(FilterImpl.createFilter("color = 'green'")); FakeConsumer consumer = new FakeConsumer(FilterImpl.createFilter("color = 'green'"));
@ -1061,17 +871,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testBusyConsumerWithFilterThenAddMoreMessages() throws Exception public void testBusyConsumerWithFilterThenAddMoreMessages() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
FakeConsumer consumer = new FakeConsumer(FilterImpl.createFilter("color = 'green'")); FakeConsumer consumer = new FakeConsumer(FilterImpl.createFilter("color = 'green'"));
@ -1146,17 +946,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testConsumerWithFilterThenAddMoreMessages() throws Exception public void testConsumerWithFilterThenAddMoreMessages() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
final int numMessages = 10; final int numMessages = 10;
List<MessageReference> refs = new ArrayList<MessageReference>(); List<MessageReference> refs = new ArrayList<MessageReference>();
@ -1220,17 +1010,7 @@ public class QueueImplTest extends UnitTestCase
private void testConsumerWithFilters(final boolean direct) throws Exception private void testConsumerWithFilters(final boolean direct) throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
new FakePostOffice(),
null,
null,
executor);
Filter filter = new FakeFilter("fruit", "orange"); Filter filter = new FakeFilter("fruit", "orange");
@ -1323,17 +1103,7 @@ public class QueueImplTest extends UnitTestCase
public void testMessageOrder() throws Exception public void testMessageOrder() throws Exception
{ {
FakeConsumer consumer = new FakeConsumer(); FakeConsumer consumer = new FakeConsumer();
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2); MessageReference messageReference2 = generateReference(queue, 2);
MessageReference messageReference3 = generateReference(queue, 3); MessageReference messageReference3 = generateReference(queue, 3);
@ -1354,17 +1124,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testMessagesAdded() throws Exception public void testMessagesAdded() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2); MessageReference messageReference2 = generateReference(queue, 2);
MessageReference messageReference3 = generateReference(queue, 3); MessageReference messageReference3 = generateReference(queue, 3);
@ -1377,17 +1137,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testGetReference() throws Exception public void testGetReference() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2); MessageReference messageReference2 = generateReference(queue, 2);
MessageReference messageReference3 = generateReference(queue, 3); MessageReference messageReference3 = generateReference(queue, 3);
@ -1401,17 +1151,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testGetNonExistentReference() throws Exception public void testGetNonExistentReference() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2); MessageReference messageReference2 = generateReference(queue, 2);
MessageReference messageReference3 = generateReference(queue, 3); MessageReference messageReference3 = generateReference(queue, 3);
@ -1430,17 +1170,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testPauseAndResumeWithAsync() throws Exception public void testPauseAndResumeWithAsync() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
// pauses the queue // pauses the queue
queue.pause(); queue.pause();
@ -1498,17 +1228,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testPauseAndResumeWithDirect() throws Exception public void testPauseAndResumeWithDirect() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
// Now add a consumer // Now add a consumer
FakeConsumer consumer = new FakeConsumer(); FakeConsumer consumer = new FakeConsumer();
@ -1553,17 +1273,7 @@ public class QueueImplTest extends UnitTestCase
@Test @Test
public void testResetMessagesAdded() throws Exception public void testResetMessagesAdded() throws Exception
{ {
QueueImpl queue = new QueueImpl(1, QueueImpl queue = getTemporaryQueue();
QueueImplTest.address1,
QueueImplTest.queue1,
null,
false,
true,
scheduledExecutor,
null,
null,
null,
executor);
MessageReference messageReference = generateReference(queue, 1); MessageReference messageReference = generateReference(queue, 1);
MessageReference messageReference2 = generateReference(queue, 2); MessageReference messageReference2 = generateReference(queue, 2);
queue.addTail(messageReference); queue.addTail(messageReference);
@ -1668,4 +1378,45 @@ public class QueueImplTest extends UnitTestCase
server.stop(); 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);
}
} }

View File

@ -17,6 +17,7 @@
package org.apache.activemq.tests.unit.core.server.impl.fakes; package org.apache.activemq.tests.unit.core.server.impl.fakes;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.apache.activemq.api.core.Pair; import org.apache.activemq.api.core.Pair;
import org.apache.activemq.api.core.SimpleString; import org.apache.activemq.api.core.SimpleString;
@ -43,6 +44,12 @@ public class FakePostOffice implements PostOffice
return false; return false;
} }
@Override
public Set<SimpleString> getAddresses()
{
return null;
}
@Override @Override
public void start() throws Exception public void start() throws Exception
{ {

Some files were not shown because too many files have changed in this diff Show More