mirror of https://github.com/apache/activemq.git
https://issues.apache.org/jira/browse/AMQ-5956 - improve CLI commands error handling
This commit is contained in:
parent
c7b93d1232
commit
73f9131a62
|
@ -20,6 +20,7 @@ import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.ConnectException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionMetaData;
|
import org.apache.activemq.ActiveMQConnectionMetaData;
|
||||||
|
@ -159,4 +160,20 @@ public abstract class AbstractCommand implements Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void handleException(Throwable exception, String serviceUrl) {
|
||||||
|
Throwable cause = exception.getCause();
|
||||||
|
while (true) {
|
||||||
|
Throwable next = cause.getCause();
|
||||||
|
if (next == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cause = next;
|
||||||
|
}
|
||||||
|
if (cause instanceof ConnectException) {
|
||||||
|
context.printInfo("Broker not available at: " + serviceUrl);
|
||||||
|
} else {
|
||||||
|
context.printException(new RuntimeException("Failed to execute " + getName() + " task. Reason: " + exception));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.ConnectException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
@ -385,7 +386,10 @@ public abstract class AbstractJmxCommand extends AbstractCommand {
|
||||||
public void execute(List<String> tokens) throws Exception {
|
public void execute(List<String> tokens) throws Exception {
|
||||||
try {
|
try {
|
||||||
super.execute(tokens);
|
super.execute(tokens);
|
||||||
} finally {
|
} catch (Throwable exception) {
|
||||||
|
handleException(exception, jmxServiceUrl.toString());
|
||||||
|
return;
|
||||||
|
}finally {
|
||||||
closeJmxConnection();
|
closeJmxConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.StringTokenizer;
|
||||||
|
|
||||||
import javax.jms.Destination;
|
import javax.jms.Destination;
|
||||||
|
|
||||||
|
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
import org.apache.activemq.command.ActiveMQQueue;
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
import org.apache.activemq.command.ActiveMQTopic;
|
||||||
import org.apache.activemq.console.util.AmqMessagesUtil;
|
import org.apache.activemq.console.util.AmqMessagesUtil;
|
||||||
|
@ -39,11 +40,11 @@ public class AmqBrowseCommand extends AbstractAmqCommand {
|
||||||
public static final String VIEW_GROUP_BODY = "body:";
|
public static final String VIEW_GROUP_BODY = "body:";
|
||||||
|
|
||||||
protected String[] helpFile = new String[] {
|
protected String[] helpFile = new String[] {
|
||||||
"Task Usage: Main browse --amqurl <broker url> [browse-options] <destinations>",
|
"Task Usage: Main browse [browse-options] <destinations>",
|
||||||
"Description: Display selected destination's messages.",
|
"Description: Display selected destination's messages.",
|
||||||
"",
|
"",
|
||||||
"Browse Options:",
|
"Browse Options:",
|
||||||
" --amqurl <url> Set the broker URL to connect to.",
|
" --amqurl <url> Set the broker URL to connect to. Default tcp://localhost:61616",
|
||||||
" --msgsel <msgsel1,msglsel2> Add to the search list messages matched by the query similar to",
|
" --msgsel <msgsel1,msglsel2> Add to the search list messages matched by the query similar to",
|
||||||
" the messages selector format.",
|
" the messages selector format.",
|
||||||
" --factory <className> Load className as the javax.jms.ConnectionFactory to use for creating connections.",
|
" --factory <className> Load className as the javax.jms.ConnectionFactory to use for creating connections.",
|
||||||
|
@ -116,8 +117,7 @@ public class AmqBrowseCommand extends AbstractAmqCommand {
|
||||||
|
|
||||||
// If no broker url specified
|
// If no broker url specified
|
||||||
if (getBrokerUrl() == null) {
|
if (getBrokerUrl() == null) {
|
||||||
context.printException(new IllegalStateException("No broker url specified. Use the --amqurl option to specify a broker url."));
|
setBrokerUrl(ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the messages for each destination
|
// Display the messages for each destination
|
||||||
|
@ -151,9 +151,8 @@ public class AmqBrowseCommand extends AbstractAmqCommand {
|
||||||
context.printMessage(AmqMessagesUtil.filterMessagesView(addMsgs, groupViews, queryViews));
|
context.printMessage(AmqMessagesUtil.filterMessagesView(addMsgs, groupViews, queryViews));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception exception) {
|
||||||
context.printException(new RuntimeException("Failed to execute browse task. Reason: " + e));
|
handleException(exception, getBrokerUrl().toString());
|
||||||
throw new Exception(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,25 +97,20 @@ public class BrowseCommand extends AbstractJmxCommand {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected void runTask(List<String> tokens) throws Exception {
|
protected void runTask(List<String> tokens) throws Exception {
|
||||||
try {
|
// If there is no queue name specified, let's select all
|
||||||
// If there is no queue name specified, let's select all
|
if (tokens.isEmpty()) {
|
||||||
if (tokens.isEmpty()) {
|
tokens.add("*");
|
||||||
tokens.add("*");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate through the queue names
|
// Iterate through the queue names
|
||||||
for (Iterator<String> i = tokens.iterator(); i.hasNext();) {
|
for (Iterator<String> i = tokens.iterator(); i.hasNext(); ) {
|
||||||
List queueList = JmxMBeansUtil.queryMBeans(createJmxConnection(), "Type=Queue,Destination=" + i.next() + ",*");
|
List queueList = JmxMBeansUtil.queryMBeans(createJmxConnection(), "Type=Queue,Destination=" + i.next() + ",*");
|
||||||
|
|
||||||
// Iterate through the queue result
|
// Iterate through the queue result
|
||||||
for (Iterator j = queueList.iterator(); j.hasNext();) {
|
for (Iterator j = queueList.iterator(); j.hasNext(); ) {
|
||||||
List messages = JmxMBeansUtil.createMessageQueryFilter(createJmxConnection(), ((ObjectInstance)j.next()).getObjectName()).query(queryAddObjects);
|
List messages = JmxMBeansUtil.createMessageQueryFilter(createJmxConnection(), ((ObjectInstance) j.next()).getObjectName()).query(queryAddObjects);
|
||||||
context.printMessage(JmxMBeansUtil.filterMessagesView(messages, groupViews, queryViews));
|
context.printMessage(JmxMBeansUtil.filterMessagesView(messages, groupViews, queryViews));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
context.printException(new RuntimeException("Failed to execute browse task. Reason: " + e));
|
|
||||||
throw new Exception(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,20 +66,12 @@ public class DstatCommand extends AbstractJmxCommand {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void runTask(List<String> tokens) throws Exception {
|
protected void runTask(List<String> tokens) throws Exception {
|
||||||
try {
|
if (tokens.contains("topics")) {
|
||||||
|
displayTopicStats();
|
||||||
if (tokens.contains("topics")) {
|
} else if (tokens.contains("queues")) {
|
||||||
displayTopicStats();
|
displayQueueStats();
|
||||||
} else if (tokens.contains("queues")) {
|
} else {
|
||||||
displayQueueStats();
|
displayAllDestinations();
|
||||||
} else {
|
|
||||||
displayAllDestinations();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate through the queue names
|
|
||||||
} catch (Exception e) {
|
|
||||||
context.printException(new RuntimeException("Failed to execute dstat task. Reason: " + e.getMessage(), e));
|
|
||||||
throw new Exception(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,14 +55,9 @@ public class ListCommand extends AbstractJmxCommand {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected void runTask(List tokens) throws Exception {
|
protected void runTask(List tokens) throws Exception {
|
||||||
try {
|
Set<String> propsView = new HashSet<String>();
|
||||||
Set<String> propsView = new HashSet<String>();
|
propsView.add("brokerName");
|
||||||
propsView.add("brokerName");
|
context.printMBean(JmxMBeansUtil.filterMBeansView(JmxMBeansUtil.getAllBrokers(createJmxConnection()), propsView));
|
||||||
context.printMBean(JmxMBeansUtil.filterMBeansView(JmxMBeansUtil.getAllBrokers(createJmxConnection()), propsView));
|
|
||||||
} catch (Exception e) {
|
|
||||||
context.printException(new RuntimeException("Failed to execute list task. Reason: " + e));
|
|
||||||
throw new Exception(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -83,61 +83,56 @@ public class PurgeCommand extends AbstractJmxCommand {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void runTask(List<String> tokens) throws Exception {
|
protected void runTask(List<String> tokens) throws Exception {
|
||||||
try {
|
// If there is no queue name specified, let's select all
|
||||||
// If there is no queue name specified, let's select all
|
if (tokens.isEmpty()) {
|
||||||
if (tokens.isEmpty()) {
|
tokens.add("*");
|
||||||
tokens.add("*");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate through the queue names
|
// Iterate through the queue names
|
||||||
for (Iterator<String> i = tokens.iterator(); i.hasNext();) {
|
for (Iterator<String> i = tokens.iterator(); i.hasNext(); ) {
|
||||||
List queueList = JmxMBeansUtil.queryMBeans(createJmxConnection(), "type=Broker,brokerName=*,destinationType=Queue,destinationName=" + i.next());
|
List queueList = JmxMBeansUtil.queryMBeans(createJmxConnection(), "type=Broker,brokerName=*,destinationType=Queue,destinationName=" + i.next());
|
||||||
|
|
||||||
for (Iterator j = queueList.iterator(); j.hasNext();) {
|
for (Iterator j = queueList.iterator(); j.hasNext(); ) {
|
||||||
ObjectName queueName = ((ObjectInstance)j.next()).getObjectName();
|
ObjectName queueName = ((ObjectInstance) j.next()).getObjectName();
|
||||||
if (queryAddObjects.isEmpty()) {
|
if (queryAddObjects.isEmpty()) {
|
||||||
purgeQueue(queueName);
|
purgeQueue(queueName);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
QueueViewMBean proxy = MBeanServerInvocationHandler.
|
||||||
|
newProxyInstance(createJmxConnection(),
|
||||||
|
queueName,
|
||||||
|
QueueViewMBean.class,
|
||||||
|
true);
|
||||||
|
int removed = 0;
|
||||||
|
|
||||||
|
// AMQ-3404: We support two syntaxes for the message
|
||||||
|
// selector query:
|
||||||
|
// 1) AMQ specific:
|
||||||
|
// "JMSPriority>2,MyHeader='Foo'"
|
||||||
|
//
|
||||||
|
// 2) SQL-92 syntax:
|
||||||
|
// "(JMSPriority>2) AND (MyHeader='Foo')"
|
||||||
|
//
|
||||||
|
// If syntax style 1) is used, the comma separated
|
||||||
|
// criterias are broken into List<String> elements.
|
||||||
|
// We then need to construct the SQL-92 query out of
|
||||||
|
// this list.
|
||||||
|
|
||||||
|
String sqlQuery = null;
|
||||||
|
if (queryAddObjects.size() > 1) {
|
||||||
|
sqlQuery = convertToSQL92(queryAddObjects);
|
||||||
} else {
|
} else {
|
||||||
|
sqlQuery = queryAddObjects.get(0);
|
||||||
|
}
|
||||||
|
removed = proxy.removeMatchingMessages(sqlQuery);
|
||||||
|
context.printInfo("Removed: " + removed
|
||||||
|
+ " messages for message selector " + sqlQuery.toString());
|
||||||
|
|
||||||
QueueViewMBean proxy = MBeanServerInvocationHandler.
|
if (resetStatistics) {
|
||||||
newProxyInstance(createJmxConnection(),
|
proxy.resetStatistics();
|
||||||
queueName,
|
|
||||||
QueueViewMBean.class,
|
|
||||||
true);
|
|
||||||
int removed = 0;
|
|
||||||
|
|
||||||
// AMQ-3404: We support two syntaxes for the message
|
|
||||||
// selector query:
|
|
||||||
// 1) AMQ specific:
|
|
||||||
// "JMSPriority>2,MyHeader='Foo'"
|
|
||||||
//
|
|
||||||
// 2) SQL-92 syntax:
|
|
||||||
// "(JMSPriority>2) AND (MyHeader='Foo')"
|
|
||||||
//
|
|
||||||
// If syntax style 1) is used, the comma separated
|
|
||||||
// criterias are broken into List<String> elements.
|
|
||||||
// We then need to construct the SQL-92 query out of
|
|
||||||
// this list.
|
|
||||||
|
|
||||||
String sqlQuery = null;
|
|
||||||
if (queryAddObjects.size() > 1) {
|
|
||||||
sqlQuery = convertToSQL92(queryAddObjects);
|
|
||||||
} else {
|
|
||||||
sqlQuery = queryAddObjects.get(0);
|
|
||||||
}
|
|
||||||
removed = proxy.removeMatchingMessages(sqlQuery);
|
|
||||||
context.printInfo("Removed: " + removed
|
|
||||||
+ " messages for message selector " + sqlQuery.toString());
|
|
||||||
|
|
||||||
if (resetStatistics) {
|
|
||||||
proxy.resetStatistics();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
context.printException(new RuntimeException("Failed to execute purge task. Reason: " + e));
|
|
||||||
throw new Exception(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,23 +116,18 @@ public class QueryCommand extends AbstractJmxCommand {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected void runTask(List<String> tokens) throws Exception {
|
protected void runTask(List<String> tokens) throws Exception {
|
||||||
try {
|
// Query for the mbeans to add
|
||||||
// Query for the mbeans to add
|
Map<Object, List> addMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(), queryAddObjects, queryViews);
|
||||||
Map<Object,List> addMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(), queryAddObjects, queryViews);
|
// Query for the mbeans to sub
|
||||||
// Query for the mbeans to sub
|
if (querySubObjects.size() > 0) {
|
||||||
if (querySubObjects.size() > 0) {
|
Map<Object, List> subMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(), querySubObjects, queryViews);
|
||||||
Map<Object,List> subMBeans = JmxMBeansUtil.queryMBeansAsMap(createJmxConnection(), querySubObjects, queryViews);
|
addMBeans.keySet().removeAll(subMBeans.keySet());
|
||||||
addMBeans.keySet().removeAll(subMBeans.keySet());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (opAndParams.isEmpty()) {
|
if (opAndParams.isEmpty()) {
|
||||||
context.printMBean(JmxMBeansUtil.filterMBeansView(new ArrayList(addMBeans.values()), queryViews));
|
context.printMBean(JmxMBeansUtil.filterMBeansView(new ArrayList(addMBeans.values()), queryViews));
|
||||||
} else {
|
} else {
|
||||||
context.print(doInvoke(addMBeans.keySet(), opAndParams));
|
context.print(doInvoke(addMBeans.keySet(), opAndParams));
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
context.printException(new RuntimeException("Failed to execute query task. Reason: " + e));
|
|
||||||
throw new Exception(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,53 +69,48 @@ public class ShutdownCommand extends AbstractJmxCommand {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected void runTask(List brokerNames) throws Exception {
|
protected void runTask(List brokerNames) throws Exception {
|
||||||
try {
|
Collection mbeans;
|
||||||
Collection mbeans;
|
|
||||||
|
|
||||||
// Stop all brokers
|
// Stop all brokers
|
||||||
if (isStopAllBrokers) {
|
if (isStopAllBrokers) {
|
||||||
mbeans = JmxMBeansUtil.getAllBrokers(createJmxConnection());
|
mbeans = JmxMBeansUtil.getAllBrokers(createJmxConnection());
|
||||||
brokerNames.clear();
|
brokerNames.clear();
|
||||||
} else if (brokerNames.isEmpty()) {
|
} else if (brokerNames.isEmpty()) {
|
||||||
// Stop the default broker
|
// Stop the default broker
|
||||||
mbeans = JmxMBeansUtil.getAllBrokers(createJmxConnection());
|
mbeans = JmxMBeansUtil.getAllBrokers(createJmxConnection());
|
||||||
// If there is no broker to stop
|
// If there is no broker to stop
|
||||||
if (mbeans.isEmpty()) {
|
if (mbeans.isEmpty()) {
|
||||||
context.printInfo("There are no brokers to stop.");
|
context.printInfo("There are no brokers to stop.");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// There should only be one broker to stop
|
// There should only be one broker to stop
|
||||||
} else if (mbeans.size() > 1) {
|
} else if (mbeans.size() > 1) {
|
||||||
context.printInfo("There are multiple brokers to stop. Please select the broker(s) to stop or use --all to stop all brokers.");
|
context.printInfo("There are multiple brokers to stop. Please select the broker(s) to stop or use --all to stop all brokers.");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get the first broker only
|
// Get the first broker only
|
||||||
} else {
|
|
||||||
Object firstBroker = mbeans.iterator().next();
|
|
||||||
mbeans.clear();
|
|
||||||
mbeans.add(firstBroker);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Stop each specified broker
|
Object firstBroker = mbeans.iterator().next();
|
||||||
String brokerName;
|
mbeans.clear();
|
||||||
mbeans = new HashSet();
|
mbeans.add(firstBroker);
|
||||||
while (!brokerNames.isEmpty()) {
|
}
|
||||||
brokerName = (String)brokerNames.remove(0);
|
} else {
|
||||||
Collection matchedBrokers = JmxMBeansUtil.getBrokersByName(createJmxConnection(), brokerName);
|
// Stop each specified broker
|
||||||
if (matchedBrokers.isEmpty()) {
|
String brokerName;
|
||||||
context.printInfo(brokerName + " did not match any running brokers.");
|
mbeans = new HashSet();
|
||||||
} else {
|
while (!brokerNames.isEmpty()) {
|
||||||
mbeans.addAll(matchedBrokers);
|
brokerName = (String) brokerNames.remove(0);
|
||||||
}
|
Collection matchedBrokers = JmxMBeansUtil.getBrokersByName(createJmxConnection(), brokerName);
|
||||||
|
if (matchedBrokers.isEmpty()) {
|
||||||
|
context.printInfo(brokerName + " did not match any running brokers.");
|
||||||
|
} else {
|
||||||
|
mbeans.addAll(matchedBrokers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop all brokers in set
|
|
||||||
stopBrokers(createJmxConnection(), mbeans);
|
|
||||||
} catch (Exception e) {
|
|
||||||
context.printException(new RuntimeException("Failed to execute stop task. Reason: " + e));
|
|
||||||
throw new Exception(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stop all brokers in set
|
||||||
|
stopBrokers(createJmxConnection(), mbeans);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -657,37 +657,7 @@ case "$1" in
|
||||||
invoke_kill
|
invoke_kill
|
||||||
exit $?
|
exit $?
|
||||||
;;
|
;;
|
||||||
decrypt|encrypt|create)
|
*)
|
||||||
invoke_task checknotforrunning
|
invoke_task checknotforrunning
|
||||||
exit $?
|
exit $?
|
||||||
;;
|
|
||||||
export)
|
|
||||||
invoke_task checkfornotrunning
|
|
||||||
exit $?
|
|
||||||
;;
|
|
||||||
query|bstat|dstat|purge)
|
|
||||||
# Only check for a running broker if "--jmxurl" is part of the COMMANDLINE_ARGS
|
|
||||||
if (echo "$COMMANDLINE_ARGS"|grep -q -- "--jmxurl");then
|
|
||||||
invoke_task checknotforrunning
|
|
||||||
RET="$?"
|
|
||||||
else
|
|
||||||
invoke_task checkforrunning
|
|
||||||
RET="$?"
|
|
||||||
fi
|
|
||||||
exit $RET
|
|
||||||
;;
|
|
||||||
browse)
|
|
||||||
# Only check for a running broker if "--amqurl" is part of the COMMANDLINE_ARGS
|
|
||||||
if (echo "$COMMANDLINE_ARGS"|grep -q -- "--amqurl");then
|
|
||||||
invoke_task checknotforrunning
|
|
||||||
RET="$?"
|
|
||||||
else
|
|
||||||
invoke_task checkforrunning
|
|
||||||
RET="$?"
|
|
||||||
fi
|
|
||||||
exit $RET
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
invoke_task checkforrunning
|
|
||||||
exit $?
|
|
||||||
esac
|
esac
|
||||||
|
|
Loading…
Reference in New Issue