blob: 50e608c8feedd861394f36b2c444372da6a1fcb2 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.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.
Architecture
-->
<html lang="en">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<meta content="ActiveMQ's next generation of messaging" name="description"/>
<meta content="messaging,stomp,jms,activemq,apollo" name="keywords"/>
<meta content="Apollo" name="author"/>
<script src="../scripts/jquery.js"></script>
<link type="text/css" rel="stylesheet" href="../styles/impact/css/pygmentize.css"/>
<link type="text/css" rel="stylesheet" href="../styles/impact/css/site.css"/>
<title></title>
</head>
<body>
<div id="navigation">
<div class="wrapper">
<ul>
<li><a href="../index.html">Apollo 1.7.1</a></li>
<li><a href="../community/developers.html">Developers</a></li>
<li><a href="../community/index.html">Community</a></li>
<li><a href="../download.html">Download</a></li>
</ul> <div></div>
</div>
</div>
<div id="content">
<div class="wrapper">
<h1 id = "Apollo_1_7_1_Extending_Guide">Apollo 1.7.1 Extending Guide</h1>
<p><div class="toc"><ul style="list-style:none;">
<li><a href="#Overview">Overview</a></li>
<li><ul style="list-style:none;">
<li><a href="#Adding_your_Extensions_to_the_Apollo_Class_Path">Adding your Extensions to the Apollo Class Path</a></li>
<li><a href="#Extension_Discovery">Extension Discovery</a></li>
<li><a href="#Extending_the_Data_Model">Extending the Data Model</a></li>
<li><ul style="list-style:none;">
<li><a href="#Polymorphic_Data_Configuraiton_objects_Objects">Polymorphic Data/Configuraiton objects Objects</a></li>
</ul></li>
<li><a href="#Using_a_custom__code_VirtualHost__code__implementation">Using a custom <code>VirtualHost</code> implementation</a></li>
<li><a href="#Plugging_into_the_Broker_Lifecycle">Plugging into the Broker Lifecycle</a></li>
</ul></li>
</ul></div></p>
<h2 id = "Overview">Overview</h2>
<p>Apollo support being extended in several ways. This guide documents
all the supported extension points.</p>
<h3 id = "Adding_your_Extensions_to_the_Apollo_Class_Path">Adding your Extensions to the Apollo Class Path</h3>
<p>Just create a <code>.jar</code> out of out code and add it to the <code>${apollo.home}/lib</code>
directory. When Apollo restarts it will add the new jar to it's class path.</p>
<h3 id = "Extension_Discovery">Extension Discovery</h3>
<p>Apollo discovers your extensions by looking for extension resource files in
all the jar files in it's classpath. For example, the <code>apollo-broker</code> jar
file contains the following a resource file <code>META-INF/services/org.apache.activemq.apollo/protocol-codec-factory.index</code>
It contains the class names of the protocol codec factories that are implemented
in the <code>broker-core</code> module. It's contents are:</p>
<pre><code>org.apache.activemq.apollo.broker.protocol.AnyProtocolFactory
org.apache.activemq.apollo.broker.protocol.UdpProtocolFactory
org.apache.activemq.apollo.broker.protocol.RawProtocolFactory</code></pre>
<p>All three of the the listed classes implement the <a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.protocol.ProtocolFactory"><code>ProtocolFactory</code></a>
interface. Here's a list of extension points supported by Apollo:</p>
<ul>
<li><p>Data Model: <code>META-INF/services/org.apache.activemq.apollo/dto-module.index</code> &rarr;
<a href="api/apollo-util/index.html#org.apache.activemq.apollo.util.DtoModule"><code>org.apache.activemq.apollo.util.DtoModule</code></a></p></li>
<li><p>Transports: <code>META-INF/services/org.apache.activemq.apollo/transport-factory.index</code> &rarr;
<a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.transport.TransportFactory$$Provider"><code>org.apache.activemq.apollo.broker.transport.TransportFactory.Provider</code></a></p></li>
<li><p>Protocols: <code>META-INF/services/org.apache.activemq.apollo/protocol-factory.index</code> &rarr;
<a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.protocol.ProtocolFactory"><code>org.apache.activemq.apollo.broker.protocol.ProtocolFactory</code></a></p></li>
<li><p>Broker Factories: <code>META-INF/services/org.apache.activemq.apollo/broker-factory.index</code> &rarr;
<a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.BrokerFactoryTrait"><code>org.apache.activemq.apollo.broker.BrokerFactoryTrait</code></a></p></li>
<li><p>Connectors: <code>META-INF/services/org.apache.activemq.apollo/connector-factory.index</code> &rarr;
<a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.ConnectorFactory"><code>org.apache.activemq.apollo.broker.ConnectorFactory</code></a></p></li>
<li><p>Virtual Hosts: <code>META-INF/services/org.apache.activemq.apollo/virtual-host-factory.index</code> &rarr;
<a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.VirtualHostFactory"><code>org.apache.activemq.apollo.broker.VirtualHostFactory</code></a></p></li>
<li><p>Route Listeners: <code>META-INF/services/org.apache.activemq.apollo/router-listener-factory.index</code> &rarr;
<a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.RouterListenerFactory"><code>org.apache.activemq.apollo.broker.RouterListenerFactory</code></a></p></li>
<li><p>Stores: <code>META-INF/services/org.apache.activemq.apollo/store-factory.index</code> &rarr;
<a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.store.StoreFactory"><code>org.apache.activemq.apollo.broker.store.StoreFactory</code></a></p></li>
<li><p>Web Admin Components: <code>META-INF/services/org.apache.activemq.apollo/web-module.index</code> &rarr;
<code>org.apache.activemq.apollo.web.WebModule</code></p></li>
<li><p>Web Servers &rarr; <code>META-INF/services/org.apache.activemq.apollo/web-server-factory.index</code>&rarr;
<a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.web.WebServerFactory"><code>org.apache.activemq.apollo.broker.web.WebServerFactory</code></a></p></li>
</ul>
<!-- These might go away...
* `META-INF/services/org.apache.activemq.apollo/binding-factory.index`:
`org.apache.activemq.apollo.broker.BindingFactory`
* `META-INF/services/org.apache.activemq.apollo/protocol-codec-factory.index` :
`org.apache.activemq.apollo.broker.protocol.ProtocolCodecFactory.Provider`
-->
<h3 id = "Extending_the_Data_Model">Extending the Data Model</h3>
<p>If you want to extend the Apollo xml configuration model to understand some
custom JAXB object you have defined in your own packages, then you need
to implement a <code>Module</code> class and then create a <code>META-INF/services/org.apache.activemq.apollo/dto-module.index</code>
resource file in which you list it's class name.</p>
<p>Example module class:</p>
<div class="syntax"><pre name='code' class='brush: scala; gutter: false;'><code>
package org.example
import org.apache.activemq.apollo.util.DtoModule
class Module extends DtoModule {
def dto_package = &quot;org.apache.activemq.apollo.broker.store.leveldb.dto&quot;
def extension_classes = Array(classOf[LevelDBStoreDTO], classOf[LevelDBStoreStatusDTO])
}
</code></pre></div>
<p>Example <code>META-INF/services/org.apache.activemq.apollo/dto-module.index</code> resource:</p>
<pre><code>org.example.Module</code></pre>
<h4 id = "Polymorphic_Data_Configuraiton_objects_Objects">Polymorphic Data/Configuraiton objects Objects</h4>
<p>The following objects in the Apollo data model can be extended:</p>
<ul>
<li><a href="api/apollo-dto/org/apache/activemq/apollo/dto/VirtualHostDTO.html"><code>VirtualHostDTO</code></a></li>
<li><a href="api/apollo-dto/org/apache/activemq/apollo/dto/ConnectorTypeDTO.html"><code>ConnectorTypeDTO</code></a></li>
<li><a href="api/apollo-dto/org/apache/activemq/apollo/dto/ConnectionStatusDTO.html"><code>ConnectionStatusDTO</code></a></li>
<li><a href="api/apollo-dto/org/apache/activemq/apollo/dto/ProtocolDTO.html"><code>ProtocolDTO</code></a></li>
<li><a href="api/apollo-dto/org/apache/activemq/apollo/dto/StoreDTO.html"><code>StoreDTO</code></a></li>
<li><a href="api/apollo-dto/org/apache/activemq/apollo/dto/StoreStatusDTO.html"><code>StoreStatusDTO</code></a></li>
</ul>
<!-- Not sure we should expose this one...
* [`DestinationDTO`](api/apollo-dto/org/apache/activemq/apollo/dto/DestinationDTO.html)
-->
<h3 id = "Using_a_custom__code_VirtualHost__code__implementation">Using a custom <code>VirtualHost</code> implementation</h3>
<p>Virtual hosts control the lifescycle of destinations and how producers
and consumers are connected to those destinations. You can subclass the
default virtual host implemenation to override the default behaviour
that Apollo provides.</p>
<p>To create your own VirtualHost extension, you first extend the <a href="api/apollo-broker/index.html#org.apache.activemq.apollo.broker.VirtualHost"><code>org.apache.activemq.apollo.broker.VirtualHost</code></a> class and override it's implemenation suite your needs. Example:</p>
<pre><code>package example;
class MyVirtualHost(broker: Broker, id:String) extends VirtualHost(broker, id) {
// ... todo: override
}</code></pre>
<p>Then, to allow an <code>apollo.xml</code> configration file you your extended version of the virtual host you need to
extend the <a href="api/apollo-dto/org/apache/activemq/apollo/dto/VirtualHostDTO.html"><code>VirtualHostDTO</code></a> class to define
a new XML emlement for your new virtual host type. </p>
<pre><code>package example;
@XmlRootElement(name = "my_virtual_host")
@XmlAccessorType(XmlAccessType.FIELD)
class MyVirtualHostDTO extends VirtualHostDTO {
// example config attribute
@XmlAttribute(name="trace")
public Boolean trace;
}</code></pre>
<p>Since this is extending the data model, we follow the direction in the
<a href="#Extending&#95;the&#95;Data&#95;Model">'Extending the Data Model'</a> section of this guide and add a
<code>Module</code> class:</p>
<pre><code>package example;
class Module extends DtoModule {
def dto_package = "example"
def extension_classes = Array(classOf[MyVirtualHostDTO])
}</code></pre>
<p>and a <code>META-INF/services/org.apache.activemq.apollo/dto-module.index</code> resource file containing:</p>
<pre><code>example.Module</code></pre>
<p>Now that we can define an XML element to configure the custom virtual host and create it,
lets define a factory class which will be used to create a <code>MyVirtualHost</code> when a <code>&lt;my&#95;virtual&#95;host&gt;</code>
xml element is used in the configuration file:</p>
<pre><code>package example;
object MyVirtualHostFactory extends VirtualHostFactory {
def create(broker: Broker, dto: VirtualHostDTO): VirtualHost = dto match {
case dto:MyVirtualHostDTO =&gt;
val rc = new MyVirtualHostDTO(broker, dto.id)
rc.config = dto
rc
case _ =&gt; null
}
}</code></pre>
<p>and a <code>META-INF/services/org.apache.activemq.apollo/virtual-host-factory.index</code> resource file containing:</p>
<pre><code>example.MyVirtualHostFactory</code></pre>
<h3 id = "Plugging_into_the_Broker_Lifecycle">Plugging into the Broker Lifecycle</h3>
<p>You can implement custom <a href="api/apollo-util/index.html#org.apache.activemq.apollo.util.Service">Service</a>
objects which get started / stopped when
the broker starts and stops. Once you have packaged your custom
service, and added it to the Apollo class path, you can
update the <code>apollo.xml</code> to add the service so it gets started when
apollo starts:</p>
<div class="syntax"><pre name='code' class='brush: xml; gutter: false;'><code>
&lt;service id='myservice' kind='org.example.MyService'/&gt;
</code></pre></div>
<p>The <code>id</code> attribute is a unique service name of your service, and the
<code>kind</code> attribute is the class name of your service. </p>
<p>If your service needs a reference to the Broker object which is running
in, add the following field definition to your class:</p>
<div class="syntax"><pre name='code' class='brush: scala; gutter: false;'><code>
var broker:Broker = null
</code></pre></div>
<p>The broker instance will be injected into your class instance before it gets
started.</p>
<p>Your service can also get reference to to the configuration element used
to define it if it defines the following field.</p>
<div class="syntax"><pre name='code' class='brush: scala; gutter: false;'><code>
var config: CustomServiceDTO
</code></pre></div>
<p>This field will also get injected before getting started. The <code>CustomServiceDTO.other</code>
field will contain any additional configuration elements defined within service
element. For example, if you configured the service as follows:</p>
<div class="syntax"><pre name='code' class='brush: xml; gutter: false;'><code>
&lt;service id='myservice' kind='org.example.MyService'/&gt;
&lt;options xmlns=&quot;http://example.org/myservice&quot;&gt;
&lt;search&gt;google.com&lt;/search&gt;
&lt;/options&gt;
&lt;/service&gt;
</code></pre></div>
<p>Then you could access the options DOM element using:</p>
<div class="syntax"><pre name='code' class='brush: scala; gutter: false;'><code>
val options = config.other.get(1).asInstanceOf[Element]
</code></pre></div>
<p>If you had defined JAXB object mappings for the <code>&lt;options&gt;</code> class
then <code>config</code> will hold that object instead of generic
DOM <code>Element</code>.</p>
<div></div>
</div>
</div>
</body>
</html>