summaryrefslogtreecommitdiff
path: root/qpid/tools/src/java/README-Java-Broker.txt
diff options
context:
space:
mode:
authorFraser Adams <fadams@apache.org>2013-04-08 15:19:04 +0000
committerFraser Adams <fadams@apache.org>2013-04-08 15:19:04 +0000
commit797fcaf14ca1bfeb5778cbe526b3110f256862f2 (patch)
tree052572627ac304f44bdf07458120fedf4e195ba4 /qpid/tools/src/java/README-Java-Broker.txt
parent7f1f7f7a01cfcbb892285dc3a7d9372d1fb1ff43 (diff)
downloadqpid-python-797fcaf14ca1bfeb5778cbe526b3110f256862f2.tar.gz
QPID-3675: Java QMF2 API, REST API, QMF GUI and Java Broker QMF Management Plugin added to <qpid>/tools/src/java
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1465662 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/tools/src/java/README-Java-Broker.txt')
-rw-r--r--qpid/tools/src/java/README-Java-Broker.txt350
1 files changed, 350 insertions, 0 deletions
diff --git a/qpid/tools/src/java/README-Java-Broker.txt b/qpid/tools/src/java/README-Java-Broker.txt
new file mode 100644
index 0000000000..fccf19a099
--- /dev/null
+++ b/qpid/tools/src/java/README-Java-Broker.txt
@@ -0,0 +1,350 @@
+
+The Qpid Java Broker by default uses either JMX or an HTTP Management GUI & REST API, however by building
+a QMF2 Agent as a Java Broker plugin it's possible to provide better synergy between the C++ and Java Brokers
+and allow the Java Broker to be controlled by the Qpid Command Line tools and also via the QMF2 REST API
+and GUI thus providing a unified view across a mixture of C++ and Java Brokers.
+
+
+To build and install the Java Broker QMF2 plugin do:
+
+ant all
+
+***********************************************************************************************************
+* Note that the QmfManagementPlugin requires a version of the Java Broker >= 0.22 *
+* *
+* The initial version of QmfManagementPlugin released to https://issues.apache.org/jira/browse/QPID-3675 *
+* uses the ManagementPlugin and ManagementFactory interfaces which were introduced in Qpid 0.20 but then *
+* dropped in Qpid 0.22 so the version linked to the Jira is the only version that will work with the 0.20 *
+* Java Broker. *
+* *
+* As of Qpid 0.22 the Java Broker Plugin and Configuration APIs have changed. The Plugin API implements *
+* org.apache.qpid.server.model.Plugin extending org.apache.qpid.server.model.adapter.AbstractPluginAdapter*
+* and uses org.apache.qpid.server.plugin.PluginFactory to create the Plugin instance. *
+* *
+* The Plugin uses the org.apache.qpid.server.model.* classes and maps them to QmfData. *
+* *
+* The intention is to track changes on Qpid Trunk, but the Plugin API is still under a bit of flux *
+***********************************************************************************************************
+
+N.B. this requires that the Qpid jars (preferably qpid-all.jar) are on your CLASSPATH and that the
+QPID_HOME environment variable is set to point to <qpid>/java/build (QPID_HOME is needed by the Java
+broker anyway).
+
+The ant all target compiles the Java Broker QMF2 plugin and copies the qpid-broker-plugins-management-qmf2.jar
+and qmf2.jar to $QPID_HOME/lib/plugins creating the plugins directory if it doesn't already exist. That
+directory is one read by the qpid-server broker startup script and placed on the broker's CLASSPATH.
+
+
+
+************************************************* Config **************************************************
+
+As of Qpid 0.22 the way of configuring the Java Broker has moved to an initial config.json file in
+$QPID_WORK and updates via the Management Plugins. It is IMPORTANT to ensure that the following:
+
+{
+ "name" : "qmf2Management",
+ "pluginType" : "MANAGEMENT-QMF2",
+ "connectionURL" : "amqp://guest:guest@/?brokerlist='tcp://0.0.0.0:5672'"
+ }
+
+is added to the "plugins" list of $QPID_WORK/config.json or the Plugin will not start. There is also an "id"
+property but if this is omitted it will get automatically created the first time the Plugin starts, which
+is probably more useful that trying to make a UUID up.
+
+The "connectionURL" property is particularly important. The Plugin connects to AMQP via the JMS Client so
+"connectionURL" represents a valid Java ConnectionURL to the Broker so the username/password and any other
+ConnectionURL configuration needs to be valid as for any other AMQP Connection to the Broker.
+
+
+If the QMF GUI is to be used then either the -p option of QpidRestAPI.sh should be used to set the REST Server's
+HTTP port to something other than 8080 or the "ports" list of $QPID_WORK/config.json should be modified from e.g.
+{
+ "id" : "1f2c4c7a-f33a-316b-b0e9-c02fab74469d",
+ "name" : "8080-HTTP",
+ "port" : 8080,
+ "protocols" : [ "HTTP" ]
+ }
+
+to
+
+{
+ "id" : "1f2c4c7a-f33a-316b-b0e9-c02fab74469d",
+ "name" : "9090-HTTP",
+ "port" : 9090,
+ "protocols" : [ "HTTP" ]
+ }
+
+So that the HTTP ports don't conflict.
+
+
+In the top-level Broker config the "defaultVirtualHost" *MUST* be set to the name of the default Virtual Host
+if this property is not set or is set to a name that doesn't match the name of one of the Virtual Hosts
+then the Plugin will not start correctly.
+
+
+******************************************** Troubleshooting **********************************************
+
+If all has gone well you should see
+
+[Broker] MNG-1001 : QMF2 Management Startup
+[Broker] MNG-1004 : QMF2 Management Ready
+
+in the Broker log messages when you run qpid-server, if you don't see these then there is likely to be a problem.
+
+1. Check the directory $QPID_HOME/lib/plugins
+That should contain qmf2.jar and qpid-broker-plugins-management-qmf2.jar if it doesn't then the Plugin hasn't been
+built or deployed try doing
+
+ant all
+
+again.
+
+2. If the jars mentioned above are present and correct in the plugins directory the most likely cause of failure
+is incorrect configuration - see the Config section above, in particular the "plugins" list and "defaultVirtualHost".
+
+
+
+******************************* Java Broker Management Plugin - mini HOWTO ********************************
+
+The procedure for writing Plugins for the Java Broker isn't documented yet, so the following mini HOWTO
+describes what I did. It may not be the *right* way but it seems to result in a Plugin that starts with the broker.
+
+1. Create a PluginFactory
+
+Management plugins are instantiated by Factory classes that implement the interface
+org.apache.qpid.server.plugin.PluginFactory e.g.
+
+
+package org.apache.qpid.server.qmf2;
+
+// Misc Imports
+import java.util.Map;
+import java.util.UUID;
+
+// Java Broker Management Imports
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Plugin;
+import org.apache.qpid.server.plugin.PluginFactory;
+
+public class QmfManagementFactory implements PluginFactory
+{
+ /**
+ * This factory method creates an instance of QmfManagementPlugin called via the QpidServiceLoader.
+ * @param id the UUID of the Plugin.
+ * @param attributes a Map containing configuration information for the Plugin.
+ * @param broker the root Broker Management Object from which the other Management Objects may be obtained.
+ * @return the QmfManagementPlugin instance which creates a QMF2 Agent able to interrogate the broker Management
+ * Objects and return their properties as QmfData.
+ */
+ @Override
+ public Plugin createInstance(UUID id, Map<String, Object> attributes, Broker broker)
+ {
+ if (QmfManagementPlugin.PLUGIN_TYPE.equals(attributes.get(PLUGIN_TYPE)))
+ {
+ return new QmfManagementPlugin(id, broker, attributes);
+ }
+ else
+ {
+ return null;
+ }
+ }
+}
+
+
+2. Create a Plugin
+
+Plugins implement the interface org.apache.qpid.server.model.Plugin which seems to be done by extending
+org.apache.qpid.server.model.adapter.AbstractPluginAdapter. The main APIs are to override the setState()
+and getName() methods and to implement a static initialiser to populate ConfiguredObject ATTRIBUTES.
+
+
+package org.apache.qpid.server.qmf2;
+
+// Misc Imports
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.UUID;
+
+// Java Broker Management Imports
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Plugin;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.adapter.AbstractPluginAdapter;
+
+import org.apache.qpid.server.plugin.PluginFactory;
+import org.apache.qpid.server.util.MapValueConverter;
+
+public class QmfManagementPlugin extends AbstractPluginAdapter
+{
+ private static final String OPERATIONAL_LOGGING_NAME = "QMF2";
+
+ /************* Static initialiser used to implement org.apache.qpid.server.model.Plugin *************/
+
+ public static final String PLUGIN_TYPE = "MANAGEMENT-QMF2";
+
+ // attributes
+ public static final String NAME = "name";
+ public static final String CONNECTION_URL = "connectionURL";
+
+ // default values
+ public static final String DEFAULT_NAME = "qmf2Management";
+ public static final String DEFAULT_CONNECTION_URL = "amqp://guest:guest@/?brokerlist='tcp://0.0.0.0:5672'";
+
+ @SuppressWarnings("serial")
+ private static final Collection<String> AVAILABLE_ATTRIBUTES = Collections.unmodifiableCollection(
+ new HashSet<String>(Plugin.AVAILABLE_ATTRIBUTES){{
+ add(NAME);
+ add(CONNECTION_URL);
+ add(PluginFactory.PLUGIN_TYPE);
+ }});
+
+ @SuppressWarnings("serial")
+ private static final Map<String, Object> DEFAULTS = new HashMap<String, Object>(){{
+ put(NAME, DEFAULT_NAME);
+ put(CONNECTION_URL, DEFAULT_CONNECTION_URL);
+ put(PluginFactory.PLUGIN_TYPE, PLUGIN_TYPE);
+ }};
+
+ @SuppressWarnings("serial")
+ private static final Map<String, Type> ATTRIBUTE_TYPES = new HashMap<String, Type>(){{
+ put(NAME, String.class);
+ put(CONNECTION_URL, String.class);
+ put(PluginFactory.PLUGIN_TYPE, String.class);
+ }};
+
+ /************************************ End of Static initialiser *************************************/
+
+ /**
+ * Constructor, called at broker startup by QmfManagementFactory.createInstance().
+ * @param id the UUID of the Plugin.
+ * @param attributes a Map containing configuration information for the Plugin.
+ * @param broker the root Broker Management Object from which the other Management Objects may be obtained.
+ */
+ public QmfManagementPlugin(UUID id, Broker broker, Map<String, Object> attributes)
+ {
+ super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), broker.getTaskExecutor());
+ addParent(Broker.class, broker);
+System.out.println("************ Constructing QmfManagementPlugin");
+ }
+
+ /**
+ * Set the state of the Plugin, I believe that this is called from the BrokerAdapter object when it
+ * has its own state set to State.ACTIVE or State.STOPPED.
+ * When State.ACTIVE is set this calls the start() method to startup the Plugin, when State.STOPPED
+ * is set this calls the stop() method to shutdown the Plugin.
+ * @param currentState the current state of the Plugin (ignored).
+ * @param desiredState the desired state of the Plugin (either State.ACTIVE or State.STOPPED).
+ * @return true if a valid state has been set, otherwise false.
+ */
+ @Override // From org.apache.qpid.server.model.adapter.AbstractAdapter
+ protected boolean setState(State currentState, State desiredState)
+ {
+ if (desiredState == State.ACTIVE)
+ {
+ start();
+ return true;
+ }
+ else if (desiredState == State.STOPPED)
+ {
+ stop();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private void start()
+ {
+ // Log "QMF2 Management Startup" message.
+ CurrentActor.get().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME));
+
+ // Log QMF2 Management Ready message.
+ CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME));
+ }
+
+ private void stop()
+ {
+ // Log "QMF2 Management Stopped" message (may not get displayed).
+ CurrentActor.get().message(ManagementConsoleMessages.STOPPED(OPERATIONAL_LOGGING_NAME));
+ }
+
+ /**
+ * Get the name of this Plugin.
+ * @return the Plugin name (default is "qmf2Management").
+ */
+ @Override // From org.apache.qpid.server.model.ConfiguredObject
+ public String getName()
+ {
+ return (String)getAttribute(NAME);
+ }
+
+ /**
+ * Accessor to retrieve the names of the available attributes. It is important to provide this overridden
+ * method because the Constructor uses this information when populating the underlying AbstractPlugin
+ * information. If we don't provide this override method getAttribute(name) will return the default values.
+ * @return the names of the available Plugin config attributes as a Collection.
+ */
+ @Override // From org.apache.qpid.server.model.adapter.AbstractPluginAdapter
+ public Collection<String> getAttributeNames()
+ {
+ return AVAILABLE_ATTRIBUTES;
+ }
+}
+
+3. Populate the META-INF
+
+Qpid Java broker Plugins seem to use a facade over java.util.ServiceLoader called
+org.apache.qpid.server.plugin.QpidServiceLoader. In order to use a ServiceLoader the jar containing the Plugin
+needs to contain a file:
+META-INF/services/org.apache.qpid.server.plugin.PluginFactory
+
+which contains the fully qualified class name of the class implementing PluginFactory e.g.
+
+org.apache.qpid.server.qmf2.QmfManagementFactory
+
+
+The most convenient way to achieve this is to include a ServiceProvider block in the jar ant task e.g.
+
+ <jar destfile="build/lib/qpid-broker-plugins-management-qmf2.jar"
+ basedir="build/scratch/qpid-broker-plugins-management-qmf2">
+
+ <service type="org.apache.qpid.server.plugin.PluginFactory"
+ provider="org.apache.qpid.server.qmf2.QmfManagementFactory"/>
+ </jar>
+
+
+4. Build the jar using your favourite method.
+
+5. Deploy the jar to $QPID_HOME/lib/plugins
+
+6. Ensure the config.json file in $QPID_WORK contains:
+{
+ "name" : "qmf2Management",
+ "pluginType" : "MANAGEMENT-QMF2",
+ "connectionURL" : "amqp://guest:guest@/?brokerlist='tcp://0.0.0.0:5672'"
+ }
+
+(or whatever the name/pluginType/etc. of the actual Plugin is)
+in the "plugins" list (the id property will be added automatically when the Broker starts)
+
+7. Start up the Java Broker via qpid-server
+
+
+If all has gone well the Plugin should start up. Clearly you'll probably want to add something to the Plugin so
+that it actually does something vaguely useful :-)
+
+
+
+