154 lines
7.6 KiB
Plaintext
154 lines
7.6 KiB
Plaintext
|
= Using Core
|
||
|
:idprefix:
|
||
|
:idseparator: -
|
||
|
|
||
|
Apache ActiveMQ Artemis core is a messaging system with its own API.
|
||
|
We call this the _core API_.
|
||
|
|
||
|
If you don't want to use the JMS API or any of the other supported protocols 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.
|
||
|
|
||
|
== Core Messaging Concepts
|
||
|
|
||
|
Some of the core messaging concepts are similar to JMS concepts, but core messaging concepts are also different in some ways as well.
|
||
|
In general the core 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.
|
||
|
|
||
|
Also refer to the xref:address-model.adoc#address-model[address model] chapter for a high-level overview of these concepts as well as configuration details.
|
||
|
|
||
|
=== Message
|
||
|
|
||
|
* A message is the unit of data which is sent between clients and servers.
|
||
|
* A message has a body which is a buffer containing convenient methods for reading and writing data into it.
|
||
|
* 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.
|
||
|
* A message has an _address_ it is being sent to.
|
||
|
When the message arrives on the server it is routed to any queues that are bound to the address.
|
||
|
The routing semantics (i.e. anycast or multicast) are determined by the "routing type" of the address and queue.
|
||
|
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 (e.g. _diverts_) bound to addresses.
|
||
|
* 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.
|
||
|
* Messages can be specified with a priority value between 0 and 9.
|
||
|
0 represents the lowest priority and 9 represents the highest.
|
||
|
The broker will attempt to deliver higher priority messages before lower priority ones.
|
||
|
* Messages can be specified with an optional expiry time.
|
||
|
The broker will not deliver messages after its expiry time has been exceeded.
|
||
|
* Messages also have an optional timestamp which represents the time the message was sent.
|
||
|
* Apache ActiveMQ Artemis also supports the sending/consuming of very large messages much larger than can fit in available RAM at any one time.
|
||
|
|
||
|
== Core API
|
||
|
|
||
|
=== ServerLocator
|
||
|
|
||
|
Clients use `ServerLocator` instances to create `ClientSessionFactory` instances.
|
||
|
`ServerLocator` instances are used to locate servers and create connections to them.
|
||
|
|
||
|
In JMS terms think of a `ServerLocator` in the same way you would a JMS Connection Factory.
|
||
|
|
||
|
`ServerLocator` instances are created using the `ActiveMQClient` factory class.
|
||
|
|
||
|
=== ClientSessionFactory
|
||
|
|
||
|
Clients use `ClientSessionFactory` instances to create `ClientSession` instances.
|
||
|
`ClientSessionFactory` instances are basically the connection to a server
|
||
|
|
||
|
In JMS terms think of them as JMS Connections.
|
||
|
|
||
|
`ClientSessionFactory` instances are created using the `ServerLocator` class.
|
||
|
|
||
|
=== ClientSession
|
||
|
|
||
|
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 `XAResource` interface so messaging operations can be performed as part of a http://www.oracle.com/technetwork/java/javaee/tech/jta-138684.html[JTA] transaction.
|
||
|
|
||
|
`ClientSession` instances group `ClientConsumer` instances and `ClientProducer` instances.
|
||
|
|
||
|
`ClientSession` instances can be registered with an optional `SendAcknowledgementHandler`.
|
||
|
This allows your client code to be notified asynchronously when sent messages have successfully reached the server.
|
||
|
This unique Apache ActiveMQ Artemis 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:send-guarantees.adoc#guarantees-of-sends-and-commits[Guarantees of sends and commits].
|
||
|
|
||
|
==== Identifying your session for management and debugging
|
||
|
|
||
|
Assigning IDs to your core sessions can help you with monitoring and debugging the cluster using the xref:management-console.adoc#management-console[management console].
|
||
|
|
||
|
[,java]
|
||
|
----
|
||
|
ClientSession session;
|
||
|
// ...
|
||
|
session.addMetaData(ClientSession.JMS_SESSION_IDENTIFIER_PROPERTY, "jms-client-id");
|
||
|
session.addMetaData("jms-client-id", "my-session");
|
||
|
----
|
||
|
|
||
|
Such ID will then appear in the *Client ID* column under the *Connections*, *Consumers* and *Producers* tabs.
|
||
|
|
||
|
If you are using the JMS API, the `setClientID` would give you the same effect.
|
||
|
|
||
|
=== ClientConsumer
|
||
|
|
||
|
Clients use `ClientConsumer` instances to consume messages from a queue.
|
||
|
Core messaging supports both synchronous and asynchronous message consumption semantics.
|
||
|
`ClientConsumer` instances can be configured with an optional filter expression and will only consume messages which match that expression.
|
||
|
|
||
|
=== ClientProducer
|
||
|
|
||
|
Clients create `ClientProducer` instances on `ClientSession` 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.
|
||
|
|
||
|
[WARNING]
|
||
|
====
|
||
|
Please note that `ClientSession`, `ClientProducer` and `ClientConsumer` instances are _designed to be re-used_.
|
||
|
|
||
|
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:perf-tuning.adoc#performance-tuning[Performance Tuning].
|
||
|
====
|
||
|
|
||
|
== A simple example of using Core
|
||
|
|
||
|
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 _address_, and secondly, creating a _queue_ for the consumer using anycast routing, creating the consumer, and _starting_ it.
|
||
|
|
||
|
[,java]
|
||
|
----
|
||
|
ServerLocator locator = ActiveMQClient.createServerLocator("vm://0");
|
||
|
|
||
|
// 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", RoutingType.ANYCAST, "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();
|
||
|
----
|