ARTEMIS-573 clarify filter documentation

This commit is contained in:
jbertram 2016-07-13 15:47:24 -05:00 committed by Andy Taylor
parent d7edf06689
commit 8a66d5f485
3 changed files with 107 additions and 0 deletions

View File

@ -49,3 +49,25 @@ refer to attributes of the core message in an expression:
Any other identifiers used in core filter expressions will be assumed to
be properties of the message.
The JMS spec states that a String property should not get converted to a
numeric when used in a selector. So for example, if a message has the `age`
property set to String `21` then the following selector should not match
it: `age > 18`. Since Apache ActiveMQ Artemis supports STOMP clients which
can only send messages with string properties, that restriction is a bit
limiting. Therefore, if you want your filter expressions to auto-convert String
properties the the appropriate number type, just prefix it with
`convert_string_expressions:`. If you changed the filter expression in the
previous example to be `convert_string_expressions:age > 18`, then it would
match the aforementioned message.
The JMS spec also states that property identifiers (and therefore the
identifiers which are valid for use in a filter expression) are an,
"unlimited-length sequence of letters and digits, the first of which must be
a letter. A letter is any character for which the method
`Character.isJavaLetter` returns `true`. This includes `_` and `$`. A letter
or digit is any character for which the method `Character.isJavaLetterOrDigit`
returns `true`." This constraint means that hyphens (i.e. `-`) cannot be used.
However, this constraint can be overcome by using the `hyphenated_props:`
prefix. For example, if a message had the `foo-bar` property set to `0` then
the filter expression `hyphenated_props:foo-bar = 0` would match it.

View File

@ -311,6 +311,13 @@ seconds.
> users can use heart-beats to maintain the life cycle of stomp
> connections.
### Selector/Filter expressions
Stomp subscribers can specify an expression used to select or filter
what the subscriber receives using the `selector` header. The filter
expression syntax follows the *core filter syntax* described in the
[Filter Expressions](filter-expressions.md) documentation.
### Stomp and JMS interoperability
#### Using JMS destinations

View File

@ -31,6 +31,12 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.core.management.ResourceNames;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
@ -435,6 +441,35 @@ public class StompTest extends StompTestBase {
Assert.assertEquals("bar", "123", message.getStringProperty("bar"));
}
@Test
public void testSendMessageWithCustomHeadersAndHyphenatedSelector() throws Exception {
MessageConsumer consumer = session.createConsumer(queue, "hyphenated_props:b-ar = '123'");
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
sendFrame(frame);
frame = receiveFrame(10000);
Assert.assertTrue(frame.startsWith("CONNECTED"));
frame = "SEND\n" + "foo:abc\n" +
"b-ar:123\n" +
"destination:" +
getQueuePrefix() +
getQueueName() +
"\n\n" +
"Hello World" +
Stomp.NULL;
sendFrame(frame);
TextMessage message = (TextMessage) consumer.receive(1000);
Assert.assertNotNull(message);
Assert.assertEquals("Hello World", message.getText());
Assert.assertEquals("foo", "abc", message.getStringProperty("foo"));
Assert.assertEquals("b-ar", "123", message.getStringProperty("b-ar"));
}
@Test
public void testSendMessageWithStandardHeaders() throws Exception {
@ -755,6 +790,49 @@ public class StompTest extends StompTestBase {
sendFrame(frame);
}
@Test
public void testSubscribeWithAutoAckAndHyphenatedSelector() throws Exception {
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
sendFrame(frame);
frame = receiveFrame(100000);
Assert.assertTrue(frame.startsWith("CONNECTED"));
frame = "SUBSCRIBE\n" + "destination:" +
getQueuePrefix() +
getQueueName() +
"\n" +
"selector: hyphenated_props:foo-bar = 'zzz'\n" +
"ack:auto\n\n" +
Stomp.NULL;
sendFrame(frame);
ServerLocator serverLocator = addServerLocator(ActiveMQClient.createServerLocator("vm://0"));
ClientSessionFactory clientSessionFactory = serverLocator.createSessionFactory();
ClientSession clientSession = clientSessionFactory.createSession(true, true);
ClientProducer producer = clientSession.createProducer(getQueuePrefix() + getQueueName());
ClientMessage ignoredMessage = clientSession.createMessage(false);
ignoredMessage.putStringProperty("foo-bar", "1234");
ignoredMessage.getBodyBuffer().writeNullableSimpleString(SimpleString.toSimpleString("Ignored message"));
ClientMessage realMessage = clientSession.createMessage(false);
realMessage.putStringProperty("foo-bar", "zzz");
realMessage.getBodyBuffer().writeNullableSimpleString(SimpleString.toSimpleString("Real message"));
producer.send(ignoredMessage);
producer.send(realMessage);
frame = receiveFrame(10000);
Assert.assertTrue(frame.startsWith("MESSAGE"));
Assert.assertTrue("Should have received the real message but got: " + frame, frame.indexOf("Real message") > 0);
frame = "DISCONNECT\n" + "\n\n" + Stomp.NULL;
sendFrame(frame);
}
@Test
public void testSubscribeWithClientAck() throws Exception {