225 lines
14 KiB
XML
225 lines
14 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!-- ============================================================================= -->
|
||
<!-- Copyright © 2009 Red Hat, Inc. and others. -->
|
||
<!-- -->
|
||
<!-- The text of and illustrations in this document are licensed by Red Hat under -->
|
||
<!-- a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). -->
|
||
<!-- -->
|
||
<!-- An explanation of CC-BY-SA is available at -->
|
||
<!-- -->
|
||
<!-- http://creativecommons.org/licenses/by-sa/3.0/. -->
|
||
<!-- -->
|
||
<!-- In accordance with CC-BY-SA, if you distribute this document or an adaptation -->
|
||
<!-- of it, you must provide the URL for the original version. -->
|
||
<!-- -->
|
||
<!-- Red Hat, as the licensor of this document, waives the right to enforce, -->
|
||
<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent -->
|
||
<!-- permitted by applicable law. -->
|
||
<!-- ============================================================================= -->
|
||
<chapter id="using-core">
|
||
<title>Using Core</title>
|
||
<para>ActiveMQ core is a completely JMS-agnostic messaging system with its own non-JMS API. We
|
||
call this the <emphasis>core API</emphasis>.</para>
|
||
<para>If you don't want to use JMS you can use the core API directly. The core API provides all
|
||
the functionality of JMS but without much of the complexity. It also provides features that
|
||
are not available using JMS.</para>
|
||
<section>
|
||
<title>Core Messaging Concepts</title>
|
||
<para>Some of the core messaging concepts are similar to JMS concepts, but core messaging
|
||
concepts differ in some ways. In general the core messaging API is simpler than the JMS
|
||
API, since we remove distinctions between queues, topics and subscriptions. We'll
|
||
discuss each of the major core messaging concepts in turn, but to see the API in detail,
|
||
please consult the Javadoc.</para>
|
||
<section>
|
||
<title>Message</title>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>A message is the unit of data which is sent between clients and
|
||
servers.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>A message has a body which is a buffer containing convenient methods for
|
||
reading and writing data into it.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>A message has a set of properties which are key-value pairs. Each property
|
||
key is a string and property values can be of type integer, long, short,
|
||
byte, byte[], String, double, float or boolean.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>A message has an <emphasis>address</emphasis> it is being sent to. When
|
||
the message arrives on the server it is routed to any queues that are bound
|
||
to the address - if the queues are bound with any filter, the message will
|
||
only be routed to that queue if the filter matches. An address may have many
|
||
queues bound to it or even none. There may also be entities other than
|
||
queues, like <emphasis role="italic">diverts</emphasis> bound to
|
||
addresses.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Messages can be either durable or non durable. Durable messages in a
|
||
durable queue will survive a server crash or restart. Non durable messages
|
||
will never survive a server crash or restart.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Messages can be specified with a priority value between 0 and 9. 0
|
||
represents the lowest priority and 9 represents the highest. ActiveMQ will
|
||
attempt to deliver higher priority messages before lower priority
|
||
ones.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Messages can be specified with an optional expiry time. ActiveMQ will not
|
||
deliver messages after its expiry time has been exceeded.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>Messages also have an optional timestamp which represents the time the
|
||
message was sent.</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>ActiveMQ also supports the sending/consuming of very large messages - much
|
||
larger than can fit in available RAM at any one time.</para>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</section>
|
||
<section>
|
||
<title>Address</title>
|
||
<para>A server maintains a mapping between an address and a set of queues. Zero or more
|
||
queues can be bound to a single address. Each queue can be bound with an optional
|
||
message filter. When a message is routed, it is routed to the set of queues bound to
|
||
the message's address. If any of the queues are bound with a filter expression, then
|
||
the message will only be routed to the subset of bound queues which match that
|
||
filter expression.</para>
|
||
<para>Other entities, such as <emphasis role="italic">diverts</emphasis> can also be
|
||
bound to an address and messages will also be routed there.</para>
|
||
<note>
|
||
<para>In core, there is no concept of a Topic, Topic is a JMS only term. Instead, in
|
||
core, we just deal with <emphasis>addresses</emphasis> and
|
||
<emphasis>queues</emphasis>.</para>
|
||
<para>For example, a JMS topic would be implemented by a single address to which
|
||
many queues are bound. Each queue represents a subscription of the topic. A JMS
|
||
Queue would be implemented as a single address to which one queue is bound -
|
||
that queue represents the JMS queue.</para>
|
||
</note>
|
||
</section>
|
||
<section>
|
||
<title>Queue</title>
|
||
<para>Queues can be durable, meaning the messages they contain survive a server crash or
|
||
restart, as long as the messages in them are durable. Non durable queues do not
|
||
survive a server restart or crash even if the messages they contain are
|
||
durable.</para>
|
||
<para>Queues can also be temporary, meaning they are automatically deleted when the
|
||
client connection is closed, if they are not explicitly deleted before that.</para>
|
||
<para>Queues can be bound with an optional filter expression. If a filter expression is
|
||
supplied then the server will only route messages that match that filter expression
|
||
to any queues bound to the address.</para>
|
||
<para>Many queues can be bound to a single address. A particular queue is only bound to
|
||
a maximum of one address.</para>
|
||
</section>
|
||
<section>
|
||
<title>ServerLocator</title>
|
||
<para>Clients use <literal>ServerLocator</literal> instances to create <literal
|
||
>ClientSessionFactory</literal> instances. <literal>ServerLocator</literal>
|
||
instances are used to locate servers and create connections to them. </para>
|
||
<para>In JMS terms think of a <literal>ServerLocator</literal> in the same way you would
|
||
a JMS Connection Factory.</para>
|
||
<para><literal>ServerLocator</literal> instances are created using the <literal
|
||
>ActiveMQClient</literal> factory class.</para>
|
||
</section>
|
||
<section>
|
||
<title>ClientSessionFactory</title>
|
||
<para>Clients use <literal>ClientSessionFactory</literal> instances to create <literal
|
||
>ClientSession</literal> instances. <literal>ClientSessionFactory</literal>
|
||
instances are basically the connection to a server</para>
|
||
<para> In JMS terms think of them as JMS Connections.</para>
|
||
<para><literal>ClientSessionFactory</literal> instances are created using the <literal
|
||
>ServerLocator</literal> class.</para>
|
||
</section>
|
||
<section>
|
||
<title>ClientSession</title>
|
||
<para>A client uses a ClientSession for consuming and producing messages and for
|
||
grouping them in transactions. ClientSession instances can support both
|
||
transactional and non transactional semantics and also provide an <literal
|
||
>XAResource</literal> interface so messaging operations can be performed as part
|
||
of a <ulink url="http://www.oracle.com/technetwork/java/javaee/tech/jta-138684.html">JTA</ulink>
|
||
transaction.</para>
|
||
<para>ClientSession instances group ClientConsumers and ClientProducers.</para>
|
||
<para>ClientSession instances can be registered with an optional <literal
|
||
>SendAcknowledgementHandler</literal>. This allows your client code to be
|
||
notified asynchronously when sent messages have successfully reached the server.
|
||
This unique ActiveMQ feature, allows you to have full guarantees that sent messages
|
||
have reached the server without having to block on each message sent until a
|
||
response is received. Blocking on each messages sent is costly since it requires a
|
||
network round trip for each message sent. By not blocking and receiving send
|
||
acknowledgements asynchronously you can create true end to end asynchronous systems
|
||
which is not possible using the standard JMS API. For more information on this
|
||
advanced feature please see the section <xref linkend="send-guarantees"/>.</para>
|
||
</section>
|
||
<section>
|
||
<title>ClientConsumer</title>
|
||
<para>Clients use <literal>ClientConsumer</literal> instances to consume messages from a
|
||
queue. Core Messaging supports both synchronous and asynchronous message consumption
|
||
semantics. <literal>ClientConsumer</literal> instances can be configured with an
|
||
optional filter expression and will only consume messages which match that
|
||
expression.</para>
|
||
</section>
|
||
<section>
|
||
<title>ClientProducer</title>
|
||
<para>Clients create <literal>ClientProducer</literal> instances on <literal
|
||
>ClientSession</literal> instances so they can send messages. ClientProducer
|
||
instances can specify an address to which all sent messages are routed, or they can
|
||
have no specified address, and the address is specified at send time for the
|
||
message.</para>
|
||
</section>
|
||
<warning>
|
||
<para>Please note that ClientSession, ClientProducer and ClientConsumer instances are
|
||
<emphasis>designed to be re-used</emphasis>.</para>
|
||
<para>It's an anti-pattern to create new ClientSession, ClientProducer and
|
||
ClientConsumer instances for each message you produce or consume. If you do this,
|
||
your application will perform very poorly. This is discussed further in the section
|
||
on performance tuning <xref linkend="perf-tuning"/>.</para>
|
||
</warning>
|
||
</section>
|
||
<section>
|
||
<title>A simple example of using Core</title>
|
||
<para>Here's a very simple program using the core messaging API to send and receive a
|
||
message. Logically it's comprised of two sections: firstly setting up the producer to
|
||
write a message to an <emphasis>addresss</emphasis>, and secondly, creating a
|
||
<emphasis>queue</emphasis> for the consumer, creating the consumer and
|
||
<emphasis>starting</emphasis> it.</para>
|
||
<programlisting>
|
||
ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(new TransportConfiguration(
|
||
InVMConnectorFactory.class.getName()));
|
||
|
||
// In this simple example, we just use one session for both producing and receiving
|
||
|
||
ClientSessionFactory factory = locator.createClientSessionFactory();
|
||
ClientSession session = factory.createSession();
|
||
|
||
// A producer is associated with an address ...
|
||
|
||
ClientProducer producer = session.createProducer("example");
|
||
ClientMessage message = session.createMessage(true);
|
||
message.getBodyBuffer().writeString("Hello");
|
||
|
||
// We need a queue attached to the address ...
|
||
|
||
session.createQueue("example", "example", true);
|
||
|
||
// And a consumer attached to the queue ...
|
||
|
||
ClientConsumer consumer = session.createConsumer("example");
|
||
|
||
// Once we have a queue, we can send the message ...
|
||
|
||
producer.send(message);
|
||
|
||
// We need to start the session before we can -receive- messages ...
|
||
|
||
session.start();
|
||
ClientMessage msgReceived = consumer.receive();
|
||
|
||
System.out.println("message = " + msgReceived.getBodyBuffer().readString());
|
||
|
||
session.close();</programlisting>
|
||
</section>
|
||
</chapter>
|