This closes #717

This commit is contained in:
John D. Ament 2016-08-10 19:54:12 -04:00
commit 2ab52da9ae
21 changed files with 111 additions and 68 deletions

View File

@ -24,15 +24,15 @@ import java.util.List;
import io.airlift.airline.Cli;
import org.apache.activemq.artemis.cli.commands.Action;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.Browse;
import org.apache.activemq.artemis.cli.commands.Consumer;
import org.apache.activemq.artemis.cli.commands.messages.Browse;
import org.apache.activemq.artemis.cli.commands.messages.Consumer;
import org.apache.activemq.artemis.cli.commands.Create;
import org.apache.activemq.artemis.cli.commands.CreateDestination;
import org.apache.activemq.artemis.cli.commands.DeleteDestination;
import org.apache.activemq.artemis.cli.commands.destination.CreateDestination;
import org.apache.activemq.artemis.cli.commands.destination.DeleteDestination;
import org.apache.activemq.artemis.cli.commands.HelpAction;
import org.apache.activemq.artemis.cli.commands.HelpDestination;
import org.apache.activemq.artemis.cli.commands.destination.HelpDestination;
import org.apache.activemq.artemis.cli.commands.Kill;
import org.apache.activemq.artemis.cli.commands.Producer;
import org.apache.activemq.artemis.cli.commands.messages.Producer;
import org.apache.activemq.artemis.cli.commands.Run;
import org.apache.activemq.artemis.cli.commands.Stop;
import org.apache.activemq.artemis.cli.commands.tools.CompactJournal;
@ -124,6 +124,7 @@ public class Artemis {
builder.withGroup("destination").withDescription("Destination tools group (create|delete) (example ./artemis destination create)").
withDefaultCommand(HelpDestination.class).withCommands(CreateDestination.class, DeleteDestination.class);
if (instance != null) {
builder.withGroup("data").withDescription("data tools group (print|exp|imp|exp|encode|decode|compact) (example ./artemis data print)").
withDefaultCommand(HelpData.class).withCommands(PrintData.class, XmlDataExporter.class, XmlDataImporter.class, DecodeJournal.class, EncodeJournal.class, CompactJournal.class);

View File

@ -23,7 +23,7 @@ import io.airlift.airline.Option;
public abstract class ActionAbstract implements Action {
@Option(name = "--verbose", description = "Adds more information on the execution")
boolean verbose;
public boolean verbose;
private String brokerInstance;

View File

@ -15,13 +15,14 @@
* limitations under the License.
*/
package org.apache.activemq.artemis.cli.commands;
package org.apache.activemq.artemis.cli.commands.destination;
import io.airlift.airline.Command;
import io.airlift.airline.Option;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.api.jms.management.JMSManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import javax.jms.Message;
@ -63,31 +64,31 @@ public class CreateDestination extends DestinationAction {
performJmsManagement(brokerURL, user, password, new ManagementCallback<Message>() {
@Override
public void setUpInvocation(Message message) throws Exception {
JMSManagementHelper.putOperationInvocation(message, "jms.server", "createTopic", name, bindings);
JMSManagementHelper.putOperationInvocation(message, "jms.server", "createTopic", getName(), bindings);
}
@Override
public void requestSuccessful(Message reply) throws Exception {
boolean result = (boolean) JMSManagementHelper.getResult(reply, Boolean.class);
if (result) {
context.out.println("Topic " + name + " created successfully.");
context.out.println("Topic " + getName() + " created successfully.");
}
else {
context.err.println("Failed to create topic " + name + ".");
context.err.println("Failed to create topic " + getName() + ".");
}
}
@Override
public void requestFailed(Message reply) throws Exception {
String errorMsg = (String) JMSManagementHelper.getResult(reply, String.class);
context.err.println("Failed to create topic " + name + ". Reason: " + errorMsg);
context.err.println("Failed to create topic " + getName() + ". Reason: " + errorMsg);
}
});
}
public String getAddress() {
if (address == null || "".equals(address.trim())) {
address = name;
address = getName();
}
return address.trim();
}
@ -97,18 +98,18 @@ public class CreateDestination extends DestinationAction {
@Override
public void setUpInvocation(ClientMessage message) throws Exception {
String address = getAddress();
ManagementHelper.putOperationInvocation(message, "core.server", "createQueue", address, name, filter, durable);
ManagementHelper.putOperationInvocation(message, "core.server", "createQueue", address, getName(), filter, durable);
}
@Override
public void requestSuccessful(ClientMessage reply) throws Exception {
context.out.println("Core queue " + name + " created successfully.");
context.out.println("Core queue " + getName() + " created successfully.");
}
@Override
public void requestFailed(ClientMessage reply) throws Exception {
String errMsg = (String) ManagementHelper.getResult(reply, String.class);
context.err.println("Failed to create queue " + name + ". Reason: " + errMsg);
context.err.println("Failed to create queue " + getName() + ". Reason: " + errMsg);
}
});
}
@ -119,24 +120,24 @@ public class CreateDestination extends DestinationAction {
@Override
public void setUpInvocation(Message message) throws Exception {
JMSManagementHelper.putOperationInvocation(message, "jms.server", "createQueue", name, bindings, filter, durable);
JMSManagementHelper.putOperationInvocation(message, "jms.server", "createQueue", getName(), bindings, filter, durable);
}
@Override
public void requestSuccessful(Message reply) throws Exception {
boolean result = (boolean) JMSManagementHelper.getResult(reply, Boolean.class);
if (result) {
context.out.println("Jms queue " + name + " created successfully.");
context.out.println("Jms queue " + getName() + " created successfully.");
}
else {
context.err.println("Failed to create jms queue " + name + ".");
context.err.println("Failed to create jms queue " + getName() + ".");
}
}
@Override
public void requestFailed(Message reply) throws Exception {
String errorMsg = (String) JMSManagementHelper.getResult(reply, String.class);
context.err.println("Failed to create jms queue " + name + ". Reason: " + errorMsg);
context.err.println("Failed to create jms queue " + getName() + ". Reason: " + errorMsg);
}
});
}

View File

@ -15,13 +15,14 @@
* limitations under the License.
*/
package org.apache.activemq.artemis.cli.commands;
package org.apache.activemq.artemis.cli.commands.destination;
import io.airlift.airline.Command;
import io.airlift.airline.Option;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.api.jms.management.JMSManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import javax.jms.Message;
@ -54,24 +55,24 @@ public class DeleteDestination extends DestinationAction {
performJmsManagement(brokerURL, user, password, new ManagementCallback<Message>() {
@Override
public void setUpInvocation(Message message) throws Exception {
JMSManagementHelper.putOperationInvocation(message, "jms.server", "destroyTopic", name, removeConsumers);
JMSManagementHelper.putOperationInvocation(message, "jms.server", "destroyTopic", getName(), removeConsumers);
}
@Override
public void requestSuccessful(Message reply) throws Exception {
boolean result = (boolean) JMSManagementHelper.getResult(reply, Boolean.class);
if (result) {
context.out.println("Topic " + name + " deleted successfully.");
context.out.println("Topic " + getName() + " deleted successfully.");
}
else {
context.err.println("Failed to delete topic " + name);
context.err.println("Failed to delete topic " + getName());
}
}
@Override
public void requestFailed(Message reply) throws Exception {
String errorMsg = (String) JMSManagementHelper.getResult(reply, String.class);
context.err.println("Failed to delete topic " + name + ". Reason: " + errorMsg);
context.err.println("Failed to delete topic " + getName() + ". Reason: " + errorMsg);
}
});
}
@ -80,24 +81,24 @@ public class DeleteDestination extends DestinationAction {
performJmsManagement(brokerURL, user, password, new ManagementCallback<Message>() {
@Override
public void setUpInvocation(Message message) throws Exception {
JMSManagementHelper.putOperationInvocation(message, "jms.server", "destroyQueue", name, removeConsumers);
JMSManagementHelper.putOperationInvocation(message, "jms.server", "destroyQueue", getName(), removeConsumers);
}
@Override
public void requestSuccessful(Message reply) throws Exception {
boolean result = (boolean) JMSManagementHelper.getResult(reply, Boolean.class);
if (result) {
context.out.println("Jms queue " + name + " deleted successfully.");
context.out.println("Jms queue " + getName() + " deleted successfully.");
}
else {
context.err.println("Failed to delete queue " + name);
context.err.println("Failed to delete queue " + getName());
}
}
@Override
public void requestFailed(Message reply) throws Exception {
String errorMsg = (String) JMSManagementHelper.getResult(reply, String.class);
context.err.println("Failed to create " + name + " with reason: " + errorMsg);
context.err.println("Failed to create " + getName() + " with reason: " + errorMsg);
}
});
}
@ -106,18 +107,18 @@ public class DeleteDestination extends DestinationAction {
performCoreManagement(brokerURL, user, password, new ManagementCallback<ClientMessage>() {
@Override
public void setUpInvocation(ClientMessage message) throws Exception {
ManagementHelper.putOperationInvocation(message, "core.server", "destroyQueue", name);
ManagementHelper.putOperationInvocation(message, "core.server", "destroyQueue", getName());
}
@Override
public void requestSuccessful(ClientMessage reply) throws Exception {
context.out.println("Queue " + name + " deleted successfully.");
context.out.println("Queue " + getName() + " deleted successfully.");
}
@Override
public void requestFailed(ClientMessage reply) throws Exception {
String errMsg = (String) ManagementHelper.getResult(reply, String.class);
context.err.println("Failed to delete queue " + name + ". Reason: " + errMsg);
context.err.println("Failed to delete queue " + getName() + ". Reason: " + errMsg);
}
});
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.cli.commands;
package org.apache.activemq.artemis.cli.commands.destination;
import io.airlift.airline.Option;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
@ -26,6 +26,7 @@ import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.api.jms.management.JMSManagementHelper;
import org.apache.activemq.artemis.cli.commands.InputAbstract;
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
import org.apache.activemq.artemis.jms.client.ActiveMQConnection;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
@ -36,7 +37,7 @@ import javax.jms.Queue;
import javax.jms.QueueRequestor;
import javax.jms.Session;
public abstract class DestinationAction extends ActionAbstract {
public abstract class DestinationAction extends InputAbstract {
public static final String JMS_QUEUE = "jms-queue";
public static final String JMS_TOPIC = "topic";
@ -54,18 +55,18 @@ public abstract class DestinationAction extends ActionAbstract {
@Option(name = "--password", description = "Password used to connect")
String password;
@Option(name = "--name", description = "destination name", required = true)
@Option(name = "--name", description = "destination name")
String name;
public static void performJmsManagement(String brokerURL, String user, String password, ManagementCallback<Message> cb) throws Exception {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL, user, password);
ActiveMQConnection connection = (ActiveMQConnection) factory.createConnection();
ActiveMQSession session = (ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue managementQueue = ActiveMQJMSClient.createQueue("activemq.management");
QueueRequestor requestor = new QueueRequestor(session, managementQueue);
try (ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL, user, password);
ActiveMQConnection connection = (ActiveMQConnection) factory.createConnection();
ActiveMQSession session = (ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
Queue managementQueue = ActiveMQJMSClient.createQueue("activemq.management");
QueueRequestor requestor = new QueueRequestor(session, managementQueue);
try {
connection.start();
Message message = session.createMessage();
@ -83,18 +84,14 @@ public abstract class DestinationAction extends ActionAbstract {
cb.requestFailed(reply);
}
}
finally {
connection.close();
}
}
public static void performCoreManagement(String brokerURL, String user, String password, ManagementCallback<ClientMessage> cb) throws Exception {
ServerLocator locator = ServerLocatorImpl.newLocator(brokerURL);
ClientSessionFactory sessionFactory = locator.createSessionFactory();
ClientSession session = sessionFactory.createSession(user, password, false, true, true, false, ActiveMQClient.DEFAULT_ACK_BATCH_SIZE);
try {
try (ServerLocator locator = ServerLocatorImpl.newLocator(brokerURL);
ClientSessionFactory sessionFactory = locator.createSessionFactory();
ClientSession session = sessionFactory.createSession(user, password, false, true, true, false, ActiveMQClient.DEFAULT_ACK_BATCH_SIZE)) {
session.start();
ClientRequestor requestor = new ClientRequestor(session, "jms.queue.activemq.management");
ClientMessage message = session.createMessage(false);
@ -110,10 +107,6 @@ public abstract class DestinationAction extends ActionAbstract {
cb.requestFailed(reply);
}
}
finally {
session.close();
sessionFactory.close();
}
}
public void setName(String name) {
@ -121,6 +114,10 @@ public abstract class DestinationAction extends ActionAbstract {
}
public String getName() {
if (name == null) {
name = input("--name", "Please provide the destination name:", "");
}
return name;
}

View File

@ -15,15 +15,17 @@
* limitations under the License.
*/
package org.apache.activemq.artemis.cli.commands;
package org.apache.activemq.artemis.cli.commands.destination;
import io.airlift.airline.Help;
import org.apache.activemq.artemis.cli.commands.Action;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class HelpDestination extends Help implements Action {
public class HelpDestination extends Help implements Action {
@Override
public boolean isVerbose() {

View File

@ -15,10 +15,11 @@
* limitations under the License.
*/
package org.apache.activemq.artemis.cli.commands;
package org.apache.activemq.artemis.cli.commands.messages;
import io.airlift.airline.Command;
import io.airlift.airline.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.util.ConsumerThread;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.apache.activemq.artemis.cli.commands;
package org.apache.activemq.artemis.cli.commands.messages;
import javax.jms.Connection;
import javax.jms.Destination;
@ -23,6 +23,7 @@ import javax.jms.Session;
import io.airlift.airline.Command;
import io.airlift.airline.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.util.ConsumerThread;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;

View File

@ -15,9 +15,10 @@
* limitations under the License.
*/
package org.apache.activemq.artemis.cli.commands;
package org.apache.activemq.artemis.cli.commands.messages;
import io.airlift.airline.Option;
import org.apache.activemq.artemis.cli.commands.ActionAbstract;
public class DestAbstract extends ActionAbstract {

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.apache.activemq.artemis.cli.commands;
package org.apache.activemq.artemis.cli.commands.messages;
import javax.jms.Connection;
import javax.jms.Destination;
@ -23,6 +23,7 @@ import javax.jms.Session;
import io.airlift.airline.Command;
import io.airlift.airline.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.util.ProducerThread;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;

View File

@ -86,10 +86,6 @@ public interface ActiveMQClientLogger extends BasicLogger {
@Message(id = 212005, value = "Tried {0} times to connect. Now giving up on reconnecting it.", format = Message.Format.MESSAGE_FORMAT)
void failedToConnectToServer(Integer reconnectAttempts);
@LogMessage(level = Logger.Level.WARN)
@Message(id = 212006, value = "Waiting {0} milliseconds before next retry. RetryInterval={1} and multiplier={2}", format = Message.Format.MESSAGE_FORMAT)
void waitingForRetry(Long interval, Long retryInterval, Double multiplier);
@LogMessage(level = Logger.Level.WARN)
@Message(id = 212007,
value = "connector.create or connectorFactory.createConnector should never throw an exception, implementation is badly behaved, but we will deal with it anyway.",

View File

@ -825,7 +825,7 @@ public class ClientSessionFactoryImpl implements ClientSessionFactoryInternal, C
}
if (ClientSessionFactoryImpl.logger.isTraceEnabled()) {
ActiveMQClientLogger.LOGGER.waitingForRetry(interval, retryInterval, retryIntervalMultiplier);
ClientSessionFactoryImpl.logger.trace("Waiting " + interval + " milliseconds before next retry. RetryInterval=" + retryInterval + " and multiplier=" + retryIntervalMultiplier);
}
try {

View File

@ -56,6 +56,7 @@ import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.server.ActivateCallback;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.PostQueueCreationCallback;
import org.apache.activemq.artemis.core.server.PostQueueDeletionCallback;
import org.apache.activemq.artemis.core.server.Queue;
@ -1761,6 +1762,8 @@ public class JMSServerManagerImpl implements JMSServerManager, ActivateCallback
private final class JMSReloader implements ReloadCallback {
@Override
public void reload(URL url) throws Exception {
ActiveMQServerLogger.LOGGER.reloadingConfiguration("jms");
InputStream input = url.openStream();
Reader reader = new InputStreamReader(input);
String xml = XMLUtil.readerToString(reader);

View File

@ -328,6 +328,11 @@ public interface ActiveMQServerLogger extends BasicLogger {
format = Message.Format.MESSAGE_FORMAT)
void removingBackupData(String path);
@LogMessage(level = Logger.Level.INFO)
@Message(id = 221056, value = "Reloading configuration ...{0}",
format = Message.Format.MESSAGE_FORMAT)
void reloadingConfiguration(String module);
@LogMessage(level = Logger.Level.WARN)
@Message(id = 222000, value = "ActiveMQServer is being finalized and has not been stopped. Please remember to stop the server before letting it go out of scope",
format = Message.Format.MESSAGE_FORMAT)

View File

@ -2373,7 +2373,9 @@ public class ActiveMQServerImpl implements ActiveMQServer {
@Override
public void reload(URL uri) throws Exception {
Configuration config = new FileConfigurationParser().parseMainConfig(uri.openStream());
ActiveMQServerLogger.LOGGER.reloadingConfiguration("security");
securityRepository.swap(config.getSecurityRoles().entrySet());
ActiveMQServerLogger.LOGGER.reloadingConfiguration("address settings");
addressSettingsRepository.swap(config.getAddressesSettings().entrySet());
}
}

View File

@ -121,12 +121,13 @@ public class ReloadManagerImpl implements ReloadManager {
class ReloadRegistry {
private final File file;
private final URL uri;
private volatile long lastModified;
private long lastModified;
private final List<ReloadCallback> callbacks = new LinkedList<>();
ReloadRegistry(URL uri) {
this.file = new File(uri.getPath());
this.lastModified = file.lastModified();
this.uri = uri;
}

View File

@ -17,6 +17,7 @@
* [Filter Expressions](filter-expressions.md)
* [Persistence](persistence.md)
* [Configuring Transports](configuring-transports.md)
* [Configuration Reload](config-reload.md)
* [Detecting Dead Connections](connection-ttl.md)
* [Detecting Slow Consumers](slow-consumers.md)
* [Resource Manager Configuration](transaction-config.md)

View File

@ -0,0 +1,13 @@
# Configuration Reload
The system will perform a periodic check on the configuration files, configured by `configuration-file-refresh-period`, with the default at 5000, in milliseconds.
Once the configuration file is changed (broker.xml) the following modules will be reloaded automatically:
- Address Settings
- Security Settings
- JMS Queues
- JMS Topics
Notice: Queues and Topics won't be removed upon reload, given the risk of losing messages. You may execute explicit CLI or Management operations to remove destinations.

View File

@ -30,6 +30,7 @@ Name | Description
[bindings-directory](persistence.md "Configuring the bindings journal") | The folder in use for the bindings folder
[bridges](core-bridges.md "Core Bridges") | [a list of bridge](#bridge-type)
[broadcast-groups](clusters.md "Clusters") | [a list of broadcast-group](#broadcast-group-type)
[configuration-file-refresh-period](config-reload.md) | The frequency in milliseconds the configuration file is checked for changes (default 5000)
[check-for-live-server](ha.md) | Used for a live server to verify if there are other nodes with the same ID on the topology
[cluster-connections](clusters.md "Clusters") | [a list of cluster-connection](#cluster-connection-type)
[cluster-password](clusters.md "Clusters") | Cluster password. It applies to all cluster configurations.

View File

@ -69,6 +69,21 @@ finally
}
```
Or with using auto-closeable feature from Java, which can save a few lines of code:
``` java
try (
ActiveMQConnectionFactory jmsConnectionFactory = new ActiveMQConnectionFactory();
Connection jmsConnection = jmsConnectionFactory.createConnection())
{
... do some stuff with the connection...
}
```
Unfortunately users don't always write well behaved applications, and
sometimes clients just crash so they don't have a chance to clean up
their resources!
@ -205,4 +220,4 @@ thread adds a little more latency. These packets are:
To disable asynchronous connection execution, set the parameter
`async-connection-execution-enabled` in `broker.xml` to
`false` (default value is `true`).
`false` (default value is `true`).

View File

@ -18,9 +18,9 @@ package org.apache.activemq.artemis.tests.integration.cli;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.CreateDestination;
import org.apache.activemq.artemis.cli.commands.DeleteDestination;
import org.apache.activemq.artemis.cli.commands.DestinationAction;
import org.apache.activemq.artemis.cli.commands.destination.CreateDestination;
import org.apache.activemq.artemis.cli.commands.destination.DeleteDestination;
import org.apache.activemq.artemis.cli.commands.destination.DestinationAction;
import org.apache.activemq.artemis.core.filter.Filter;
import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.tests.util.JMSTestBase;