diff options
| author | Fraser Adams <fadams@apache.org> | 2013-04-08 15:19:04 +0000 |
|---|---|---|
| committer | Fraser Adams <fadams@apache.org> | 2013-04-08 15:19:04 +0000 |
| commit | 797fcaf14ca1bfeb5778cbe526b3110f256862f2 (patch) | |
| tree | 052572627ac304f44bdf07458120fedf4e195ba4 /qpid/tools/src/java/README-Java-Broker.txt | |
| parent | 7f1f7f7a01cfcbb892285dc3a7d9372d1fb1ff43 (diff) | |
| download | qpid-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.txt | 350 |
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 :-) + + + + |
