activemq-artemis/docs/user-manual/en/using-core.xml

225 lines
14 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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 AttributionShare 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>