activemq/systest/jmscts/resources/requirements.xml

1859 lines
71 KiB
XML
Executable File

<?xml version="1.0"?>
<document>
<description>All JMS requirements as per 1.0.2b of the specification
</description>
<!-- TODO -->
<!-- . add test for durable subscriber where subscription starts with a
a selector, but is subsequently changed to no selector -->
<!-- . likewise for queues -->
<!-- . verify JMSXDeliveryCount is set/incremented for providers that
support it -->
<!-- . verify that JMSXUserID, JMSXAppID, JMSXProducerTXID, JMSXConsumerTXID
and JMSXRcvTimestamp are set for those providers that support it.
Also check that these properties are returned by metadata -->
<!-- . test behaviour of QueueBrowser for connection stop, connection close,
and session close -->
<!-- . add coverage of sections 4.4.8 - 4.4.10 -->
<!-- . add recover test that tests the redelivery flag for messages not
received earlier (higher priority maybe?) -->
<!-- . add recover & rollback test that test expiration -->
<!-- . add coverage of sections 4.4.12 - 4.4.15 -->
<!-- . add coverage of sections 4.5 - 4.10 -->
<!-- . add coverage of sections 5, 6 -->
<reference referenceId="implied">
<section name="Undefined" title="An implied requirement"/>
</reference>
<reference referenceId="section.2.10">
<section name="2.10" title="Request/Reply"/>
</reference>
<reference referenceId="section.3.4.1">
<section name="3.4.1" title="JMSDestination"/>
</reference>
<reference referenceId="section.3.4.3">
<section name="3.4.3" title="JMSMessageID"/>
</reference>
<reference referenceId="section.3.4.5">
<section name="3.4.5" title="JMSCorrelationID"/>
</reference>
<reference referenceId="section.3.4.7">
<section name="3.4.7" title="JMSRedelivered"/>
</reference>
<reference referenceId="section.3.4.9">
<section name="3.4.9" title="JMSExpiration"/>
</reference>
<reference referenceId="section.3.4.11">
<section name="3.4.11" title="How Message Header Values Are Set"/>
</reference>
<reference referenceId="section.3.5.1">
<section name="3.5.1" title="Property Names" />
</reference>
<reference referenceId="section.3.5.2">
<section name="3.5.2" title="Property Values" />
</reference>
<reference referenceId="section.3.5.4">
<section name="3.5.4" title="Property Value Conversion" />
</reference>
<reference referenceId="section.3.5.5">
<section name="3.5.5" title="Property Values as Objects" />
</reference>
<reference referenceId="section.3.5.6">
<section name="3.5.6" title="Property Iteration" />
</reference>
<reference referenceId="section.3.5.8">
<section name="3.5.8" title="Nonexistent Properties" />
</reference>
<reference referenceId="table.3-2">
<table>3-2</table>
</reference>
<reference referenceId="section.3.5.9">
<section name="3.5.9" title="JMS Defined Properties" />
</reference>
<reference referenceId="table.3-3">
<table>3-3</table>
</reference>
<reference referenceId="section.3.8.1.1">
<section name="3.8.1.1" title="Message Selector Syntax" />
</reference>
<reference referenceId="section.3.8.1.2">
<section name="3.8.1.2" title="Null Values" />
</reference>
<reference referenceId="section.3.8.1.3">
<section name="3.8.1.3" title="Special Notes" />
</reference>
<reference referenceId="section.3.11">
<section name="3.11"
title="JMS Message Body" />
</reference>
<reference referenceId="section.3.11.3">
<section name="3.11.3"
title="Conversions Provided by StreamMessage and MapMessage" />
</reference>
<reference referenceId="section.3.12">
<section name="3.12"
title="Provider Implementations of JMS Message Interfaces" />
</reference>
<reference referenceId="section.4.3.1">
<section name="4.3.1" title="Authentication" />
</reference>
<reference referenceId="section.4.3.2">
<section name="4.3.2" title="Client Identifier" />
</reference>
<reference referenceId="section.4.3.3">
<section name="4.3.3" title="Connection Setup" />
</reference>
<reference referenceId="section.4.3.4">
<section name="4.3.4" title="Pausing Delivery of Incoming Messages" />
</reference>
<reference referenceId="section.4.3.5">
<section name="4.3.5" title="Closing a Connection" />
</reference>
<reference referenceId="section.4.3.7">
<section name="4.3.7" title="ConnectionMetaData" />
</reference>
<reference referenceId="section.4.4.1">
<section name="4.4.1" title="Closing a Session" />
</reference>
<reference referenceId="section.4.4.7">
<section name="4.4.7" title="Transactions" />
</reference>
<reference referenceId="section.4.4.11">
<section name="4.4.11" title="Message Acknowledgment" />
</reference>
<reference referenceId="section.6.3">
<section name="6.3" title="Durable Subscription" />
</reference>
<reference referenceId="section.6.11">
<section name="6.11" title="Topic Subscriber" />
</reference>
<reference referenceId="section.6.11.1">
<section name="6.11.1" title="Durable Topic Subscriber" />
</reference>
<reference referenceId="section.7.3">
<section name="7.3" title="Standard Exceptions" />
</reference>
<reference referenceId="section.8.2.4">
<section name="8.2.4" title="ConnectionConsumer" />
</reference>
<reference referenceId="table.3-7">
<table>3-7</table>
</reference>
<reference referenceId="url.message.bytes">
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/BytesMessage.html</url>
</reference>
<reference referenceId="url.message.stream">
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/StreamMessage.html</url>
</reference>
<requirement requirementId="selector.null">
<description>
A null message selector indicates that there is no message selector for
the message consumer.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.empty">
<description>
If the value of a message selector is an empty string, the value is
treated as a null and indicates that there is no message selector for
the message consumer.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.evaluation.order">
<description>
The order of evaluation of a message selector is from left to right
within precedence level. Parentheses can be used to change this order.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.literal.string">
<description>
A string literal is enclosed in single quotes, with an included single
quote represented by doubled single quote; for example, 'literal' and
'literal''s'.<br/>
String literals use the Unicode character encoding.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.literal.exactnumeric">
<description>
An exact numeric literal is a numeric value without a decimal point,
such as 57, -957, +62; numbers in the range of Java long are supported.
Exact numeric literals use the Java integer literal syntax.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.literal.approxnumeric">
<description>
An approximate numeric literal is a numeric value in scientific notation,
such as 7E3 and -57.9E2, or a numeric value with a decimal, such as 7.,
-95.7, and +6.2; numbers in the range of Java double are supported.
Approximate literals use the Java floating-point literal syntax.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.literal.boolean">
<description>
A boolean literal is one of TRUE or FALSE.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.identifier.name">
<description>
An identifier is an unlimited-length character sequence that must begin
with a Java identifier start character; all following characters must be
Java identifier part characters. An identifier start character is any
character for which the method Character.isJavaIdentifierStart returns
true. This includes '_' and '$'. An identifier part character is any
character for which the method Character.isJavaIdentifierPart returns
true.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.identifier.case">
<description>
Identifiers are case sensitive.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.reservedwords">
<description>
Identifiers cannot be the words NULL, TRUE, FALSE, NOT, AND, OR, BETWEEN,
LIKE, IN, IS, or ESCAPE. These are case-insensitive reserved words.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.reservedwords.case">
<description>
Reserved words are case-insensitive.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.property.conversion">
<description>
The conversions that apply to the get methods for properties do not
apply when a property is used in a message selector expression. For
example, suppose you set a property as a string value, as in the
following:<br/>
<tt>myMessage.setStringProperty("NumberOfOrders", "2");</tt><br/>
The following expression in a message selector would evaluate to false,
because a string cannot be used in an arithmetic expression:
<tt>"NumberOfOrders > 1"</tt>
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.identifier.header">
<description>
Message header field references are restricted to JMSDeliveryMode,
JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and
JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be
null and if so are treated as a NULL value.
TODO - need to test some of these in code
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.properties.JMSprefixed">
<description>
Any name beginning with 'JMSX' is a JMS defined property name.<br/>
Any name beginning with 'JMS_' is a provider-specific property name.<br/>
Any name that does not begin with 'JMS' is an application-specific
property name.<br/>
NOTE: cannot realistically test JMS_ properties.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.whitespace">
<description>
Whitespace is the same as that defined for Java: space, horizontal tab,
form feed and line terminator.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.expression">
<description>
A selector is a conditional expression; a selector that evaluates to true
matches; a selector that evaluates to false or unknown does not match.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.expression.arithmetic">
<description>
Arithmetic expressions are composed of themselves, arithmetic
operations, identifiers with numeric values, and numeric literals.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.expression.condition">
<description>
Conditional expressions are composed of themselves, comparison
operations, logical operations, identifiers with boolean values, and
boolean literals.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.operator.logical.precedence">
<description>
Logical operators in order of precedence:
<ul>
<li>NOT</li>
<li>AND</li>
<li>OR</li>
</ul>
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.operator.comparison.precedence">
<description>
Comparison operators in order of precedence:
<ul>
<li>=</li>
<li>&gt;</li>
<li>&gt;=</li>
<li>&lt;</li>
<li>&lt;=</li>
<li>&lt;&gt; (not equal)</li>
</ul>
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.operator.arithmetic.precedence">
<description>
Arithmetic operators in order of precedence are:
<ul>
<li>+, - (unary)</li>
<li>*, / (multiplication and division)</li>
<li>+, - (addition and subtraction)</li>
</ul>
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.operator.comparison.types">
<description>
Only like type values can be compared. One exception is that it is valid
to compare exact numeric values and approximate numeric values (the type
conversion required is defined by the rules of Java numeric promotion).
If the comparison of non-like type values is attempted, the value of the
operation is false. If either of the type values evaluates to NULL, the
value of the expression is unknown.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.comparison.boolean">
<description>
Boolean comparison is restricted to = and &lt;&gt;
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.comparison.string">
<description>
String comparison is restricted to = and &lt;&gt; Two strings are
equal if and only if they contain the same sequence of characters.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.operator.between">
<description>
BETWEEN expressions are of the form:
arithmetic-expr1 [NOT] BETWEEN arithmetic-expr2 and arithmetic-expr3
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.operator.in">
<description>
IN expressions are of the form:
identifier [NOT] IN (string-literal1, string-literal2, ...)
where identifier has a String or NULL value.
If identifier is NULL, the value of the operation is unknown.
TODO - add tests where identifier is known to be a non-string value
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.operator.like">
<description>
LIKE expressions are of the form:
identifier [NOT] LIKE pattern-value [ESCAPE escape-character]
where identifier has a String value; pattern-value is a string literal
where '_' stands for any single character; '%' stands for any sequence of
characters, including the empty sequence, and all other characters stand
for themselves. The optional escape-character is a single-character
string literal whose character is used to escape the special meaning of
the '_' and '%' in pattern-value.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.operator.is">
<description>
IS expressions are of the form:
identifier IS [NOT] NULL
The IS NULL form tests for a null header field value or a missing
property value.
The IS NOT NULL form tests for the existence of a non-null header field
value or property value
The IS NULL and IS NOT NULL operators convert an unknown header or
property value into the respective TRUE and FALSE values.
</description>
<referenceId>section.3.8.1.1</referenceId>
<referenceId>section.3.8.1.2</referenceId>
</requirement>
<requirement requirementId="selector.validation">
<description>
JMS providers are required to verify the syntactic correctness of a
message selector at the time it is presented. A method providing a
syntactically incorrect selector must result in a JMS
InvalidSelectorException.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.operator.arithmetic.promotion">
<description>
Arithmetic operations must use Java numeric promotion.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="selector.values.null">
<description>
Header fields and property values may be NULL. Comparison or arithmetic
with an unknown value always yields an unknown value.
</description>
<referenceId>section.3.8.1.2</referenceId>
</requirement>
<requirement requirementId="selector.operator.and">
<description>
The AND operator evaluates as follows:
<table border="1">
<tr><th>AND</th><td>T</td><td>F</td><td>U</td></tr>
<tr><td>T</td><td>T</td><td>F</td><td>U</td></tr>
<tr><td>F</td><td>F</td><td>F</td><td>F</td></tr>
<tr><td>U</td><td>U</td><td>F</td><td>U</td></tr>
</table>
</description>
<reference>
<table>3-4</table>
</reference>
<referenceId>section.3.8.1.2</referenceId>
</requirement>
<requirement requirementId="selector.operator.or">
<description>
The OR operator evaluates as follows:
<table border="1">
<tr><th>OR</th><td>T</td><td>F</td><td>U</td></tr>
<tr><td>T</td><td>T</td><td>T</td><td>T</td></tr>
<tr><td>F</td><td>T</td><td>F</td><td>U</td></tr>
<tr><td>U</td><td>T</td><td>U</td><td>U</td></tr>
</table>
</description>
<reference>
<table>3-5</table>
</reference>
<referenceId>section.3.8.1.2</referenceId>
</requirement>
<requirement requirementId="selector.operator.not">
<description>
The NOT operator evaluates as follows:
<table border="1">
<tr><th>NOT</th><td></td></tr>
<tr><td>T</td><td>F</td></tr>
<tr><td>F</td><td>T</td></tr>
<tr><td>U</td><td>U</td></tr>
</table>
</description>
<reference>
<table>3-6</table>
</reference>
<referenceId>section.3.8.1.2</referenceId>
</requirement>
<requirement requirementId="selector.JMSDeliveryMode">
<description>
When used in a message selector JMSDeliveryMode is treated as having the
values 'PERSISTENT' and 'NON_PERSISTENT'.
</description>
<referenceId>section.3.8.1.3</referenceId>
</requirement>
<requirement requirementId="selector.datetime">
<description>
Date and time values should use the standard Java long millis value.
When a date or time literal is included in a message selector, it should
be an integer literal for a millis value.
</description>
<referenceId>section.3.8.1.3</referenceId>
</requirement>
<requirement requirementId="connection.authentication">
<description>
When creating a connection, a client may specify its credentials
as a name/password.
JMSSecurityException must be thrown when a provider rejects a
user name/password submitted by a client
</description>
<referenceId>section.4.3.1</referenceId>
<referenceId>section.7.3</referenceId>
</requirement>
<requirement requirementId="connection.clientID.administered">
<description>
The facility to explicitly set a connection's client identifier is not a
mechanism for overriding the identifier that has been administratively
configured. It is provided for the case where no administratively
specified identifier exists. If one does exist, an attempt to change it
by setting it must throw an IllegalStateException.
</description>
<referenceId>section.4.3.2</referenceId>
</requirement>
<requirement requirementId="connection.method.setClientID">
<description>
If a client explicitly sets the client identifer it must do this
immediately after creating the connection and before any other action on
the connection is taken. After this point, setting the client identifier
is a programming error that should throw an IllegalStateException.
</description>
<referenceId>section.4.3.2</referenceId>
</requirement>
<requirement requirementId="connection.clientID.duplicate">
<description>
The client state identified by a client identifier can be in use by only
one client at a time. A JMS provider must prevent concurrently executing
clients from using it.
This prevention may take the form of JMSExceptions thrown when such use
is attempted; it may result in the offending client being blocked; or
some other solution. A JMS provider must insure that such attempted
'sharing' of an individual client state does not result in messages
being lost or doubly processed.
TODO - don't handle the blocked scenario
</description>
<referenceId>section.4.3.2</referenceId>
</requirement>
<requirement requirementId="connection.creation">
<description>
When a Connection is created, it is in stopped mode. That means that no
messages are being delivered to it.
</description>
<referenceId>section.4.3.3</referenceId>
</requirement>
<requirement requirementId="connection.stopped">
<description>
No messages are delivered by a connection to its client until it has been
started.
</description>
<referenceId>section.4.3.3</referenceId>
</requirement>
<requirement requirementId="connection.stopped.send">
<description>
Stopping a connection has no effect on its ability to send messages.
</description>
<referenceId>section.4.3.4</referenceId>
</requirement>
<requirement requirementId="connection.stop.listeners">
<description>
A stop method call must not return until delivery of messages has paused.
This means a client can rely on the fact that none of its message
listeners will be called and all threads of control waiting for receive
to return will not return with a message until the connection is
restarted.
If MessageListeners are running when stop is invoked, stop must wait
until all of them have returned before it may return. While these
MessageListeners are completing, they must have the full services of the
connection available to them.
TODO - test behaviour of sending messages while a listener is active,
using a different session (i.e, not from the listener - undefined?)
TODO - add test where a thread stops a connection and another starts it
as the stop is in progress.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.stop.receivers">
<description>
The receive timers for a stopped connection continue to advance, so
receives may time out and return a null message while the connection is
stopped.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.stop.stopped">
<description>
Stopping a stopped connection is ignored.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.start.started">
<description>
Starting a started connection is ignored.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.close.receivers">
<description>
A close terminates all pending message receives on the connection's
session's consumers. The receives may return with a message or null
depending on whether or not there was a message available at the time of
the close.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.close.listeners">
<description>
If one or more of the connection's session's message listeners is
processing a message at the point when connection close is invoked, all
the facilities of the connection and its sessions must remain available
to those listeners until they return control to the JMS provider.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.close">
<description>
Once a connection has been closed, an attempt to use it or its sessions
or their message consumers and producers must throw an
IllegalStateException (calls to the close method of these objects must
be ignored).
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.close.resources">
<description>
If a connection is closed, there is no need to close its constituent
objects. The connection close is sufficient to signal the JMS provider
that all resources for the connection should be released.
TODO: probably the only meaningful way to test this in a provider
independent fashion is to attempt to use a temporary destination created
by the closed connection, on another connection. This should throw
InvalidDestinationException?
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.close.session.transacted">
<description>
Closing a connection must roll back the transactions in progress on its
transacted sessions.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.close.session.CLIENT_ACKNOWLEDGE">
<description>
Closing a connection does NOT force an acknowledgement of
client-acknowledged sessions.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.close.message">
<description>
It is valid to continue to use message objects created or received after
a connection has been closed with the exception of a received message's
acknowledge method.
Invoking the acknowledge method of a received message must throw an
IllegalStateException.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="connection.close.closed">
<description>
Closing a closed connection must NOT throw an exception.
</description>
<referenceId>section.4.3.5</referenceId>
</requirement>
<requirement requirementId="session.close.transacted">
<description>
Closing a transacted session must roll back its transaction in progress.
</description>
<referenceId>section.4.4.1</referenceId>
</requirement>
<requirement requirementId="session.close.CLIENT_ACKNOWLEDGE">
<description>
Closing a client-acknowledged session does NOT force an acknowledge.
</description>
<referenceId>section.4.4.1</referenceId>
</requirement>
<requirement requirementId="session.close">
<description>
Once a session has been closed, an attempt to use it or its message
consumers and producers must throw an IllegalStateException (calls to
the close method of these objects must be ignored).
</description>
<referenceId>section.4.4.1</referenceId>
</requirement>
<requirement requirementId="session.close.message">
<description>
It is valid to continue to use message objects created or received via
the session, with the exception of a received message'acknowledge method.
Invoking the acknowledge method of a received message must throw an
IllegalStateException.
</description>
<referenceId>section.4.4.1</referenceId>
</requirement>
<requirement requirementId="session.close.closed">
<description>
Closing a closed session must NOT throw an exception.
</description>
<referenceId>section.4.4.1</referenceId>
</requirement>
<requirement requirementId="session.close.receivers">
<description>
A close terminates all pending message receives on the connection's
session's consumers. The receives may return with a message or null
depending on whether or not there was a message available at the time of
the close.
</description>
<referenceId>section.4.4.1</referenceId>
</requirement>
<requirement requirementId="session.close.listeners">
<description>
If one or more of the connection's session's message listeners is
processing a message at the point when connection close is invoked, all
the facilities of the connection and its sessions must remain available
to those listeners until they return control to the JMS provider.
</description>
<referenceId>section.4.4.1</referenceId>
</requirement>
<requirement requirementId="session.transactions">
<description>
Each transacted session supports a single series of transactions.
Each transaction groups a set of produced messages and a set of consumed
messages into an atomic unit of work.
In effect, transactions organize a session's input message stream and
output message stream into series of atomic units. When a transaction
commits, its atomic unit of input is acknowledged and its associated
atomic unit of output is sent.
</description>
<referenceId>section.4.4.7</referenceId>
</requirement>
<requirement requirementId="session.rollback">
<description>
If a transacted session is rolled back, its produced messages are
destroyed and its consumed messages are automatically recovered.
</description>
<referenceId>section.4.4.7</referenceId>
</requirement>
<requirement requirementId="session.DUPS_OK_ACKNOWLEDGE">
<description>
With the DUPS_OK_ACKNOWLEDGE session acknowledgement mode, the session
lazily acknowledges the delivery of messages. This is likely to result
in the delivery of some duplicate messages if JMS fails, so it should be
used only by consumers that are tolerant of duplicate messages. Its
benefit is the reduction of session overhead achieved by minimizing the
work the session does to prevent duplicates.
</description>
<referenceId>section.4.4.11</referenceId>
</requirement>
<requirement requirementId="session.AUTO_ACKNOWLEDGE">
<description>
With the AUTO_ACKNOWLEDGE session acknowledgement mode, the session
automatically acknowledges a client's receipt of a message when it has
either successfully returned from a call to receive or the
MessageListener it has called to process the message successfully
returns.
</description>
<referenceId>section.4.4.11</referenceId>
</requirement>
<requirement requirementId="session.CLIENT_ACKNOWLEDGE">
<description>
With the CLIENT_ACKNOWLEDGE session acknowledgement mode, a client
acknowledges a message by calling the message's acknowledge method.
Acknowledging a consumed message automatically acknowledges the receipt
of all messages that have been delivered by its session.
</description>
<referenceId>section.4.4.11</referenceId>
</requirement>
<requirement requirementId="session.recover">
<description>
A session's recover method is used to stop a session and restart it with
its first unacknowledged message. In effect, the session's series of
delivered messages is reset to the point after its last acknowledged
message. The messages it now delivers may be different from those that
were originally delivered due to message expiration and the arrival of
higher-priority messages.<br/>
A session must set the redelivered flag of messages it redelivers due to
a recovery.
</description>
<referenceId>section.4.4.11</referenceId>
<referenceId>section.3.4.7</referenceId>
</requirement>
<requirement requirementId="session.transactions.transactioninprogress">
<description>
A TransactionInProgressException exception is thrown when an operation
is invalid because a transaction is in progress. For instance,
attempting to call Session.commit() when a session is part of a
distributed transaction.
</description>
<referenceId>section.7.3</referenceId>
</requirement>
<requirement requirementId="session.transactions.commitrolledback">
<description>
A TransactionRolledBackException exception must be thrown when a call to
Session.commit() results in a rollback of the current transaction.
</description>
<referenceId>section.7.3</referenceId>
</requirement>
<requirement requirementId="session.ack.closedconsumer">
<description>
A message can be acknowledged after its message consumer has closed as
message acknowledgement is performed at the session level
TODO - need to test this for single message acknowledgement via
CLIENT_ACKWNOWLEDGE etc
</description>
<reference>
<url>http://java.sun.com/products/jms/faq.html#msg_ack_close</url>
</reference>
</requirement>
<requirement requirementId="session.listener.serialization">
<description>
A session serializes all asynchronous delivery of messages.
While the session is busy executing one listener, all other messages to
be asynchronously delivered to the session must wait.
</description>
<reference>
<section name="4.4.14" title="Serial Execution of Client Code" />
</reference>
</requirement>
<requirement requirementId="session.commit.IllegalStateException">
<description>
Invoking commit() on a non-transacted session should throw
IllegalStateException
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/Session.html#commit()</url>
</reference>
<referenceId>section.7.3</referenceId>
</requirement>
<requirement requirementId="session.rollback.IllegalStateException">
<description>
Invoking rollback() on a non-transacted session should throw
IllegalStateException
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/Session.html#rollback()</url>
</reference>
</requirement>
<requirement requirementId="session.recover.IllegalStateException">
<description>
Invoking recover() on a transacted session should throw
IllegalStateException
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/Session.html#recover()</url>
</reference>
</requirement>
<requirement requirementId="producer.ttl.default">
<description>
If not specified, the default time-to-live for a producer equals
<code>0</code>
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/MessageProducer.html#getTimeToLive()</url>
</reference>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/MessageProducer.html#setTimeToLive()</url>
</reference>
</requirement>
<requirement requirementId="producer.ttl.set">
<description>
A client can specify a default time-to-live for messages sent by a
message producer, to be used when a time-to-live isn't specified per
message.
<p>
<strong>Note:</strong> the specification doesn't mention min or max
values for time-to-live, or if any exceptions will be thrown if
an invalid time-to-live is specified.
</p>
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/MessageProducer.html</url>
</reference>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/TopicPublisher.html#publish(javax.jms.Message)</url>
</reference>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/TopicPublisher.html#publish(javax.jms.Topic,%20javax.jms.Message)</url>
</reference>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/QueueSender.html#send(javax.jms.Message)</url>
</reference>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/QueueSender.html#send(javax.jms.Queue,%20javax.jms.Message)</url>
</reference>
</requirement>
<requirement requirementId="message.destination">
<description>
When a message is sent, JMSDestination is ignored. After completion of
the send it holds the destination object specified by the sending method.
When a message is received, its destination value must be equivalent to
the value assigned when it was sent.
</description>
<referenceId>section.3.4.1</referenceId>
<referenceId>section.3.4.11</referenceId>
</requirement>
<requirement requirementId="message.identifier">
<description>
When a message is sent, JMSMessageID is ignored. When the send method
returns it contains a provider-assigned value.
</description>
<referenceId>section.3.4.3</referenceId>
<referenceId>section.3.4.11</referenceId>
</requirement>
<requirement requirementId="message.identifier.prefix">
<description>
All JMSMessageID values must start with the prefix 'ID:'
</description>
<referenceId>section.3.4.3</referenceId>
</requirement>
<requirement requirementId="message.correlation">
<description>
The JMSCorrelationID header field may be used to link one message with
another. It can contain a provider-specific message ID, an
application-specific string, or a provider-native byte[] value.
The application-specific string must not start with the 'ID:' prefix:
this is reserved for provider generated messages Ids.
</description>
<referenceId>section.2.10</referenceId>
<referenceId>section.3.4.5</referenceId>
<referenceId>section.3.4.11</referenceId>
</requirement>
<requirement requirementId="message.correlation.bytes" optional="true">
<description>
If a provider supports the native concept of correlation ID, a JMS
client may need to assign specific JMSCorrelationID values to match
those expected by non-JMS clients. A byte[] value is used for this
purpose. JMS providers without native correlation ID values are not
required to support byte[] values - in this case
setJMSCorrelationIDAsBytes() and getJMSCorrelationIDAsBytes() may throw
java.lang.UnsupportedOperationException.
</description>
<referenceId>section.3.4.5</referenceId>
</requirement>
<requirement requirementId="message.redelivered.receive">
<description>
If a client receives a message with the JMSRedelivered indicator set, it
is likely, but not guaranteed, that this message was delivered but not
acknowledged in the past. In general, a provider must set the
JMSRedelivered message header field of a message whenever it is
redelivering a message.
</description>
<referenceId>section.3.4.7</referenceId>
<referenceId>section.3.4.11</referenceId>
</requirement>
<requirement requirementId="message.redelivered.send">
<description>
The JMSRedelivered header field has no meaning on send and is left
unassigned by the sending method.
</description>
<referenceId>section.3.4.7</referenceId>
</requirement>
<requirement requirementId="message.expiration.send">
<description>
When a message is sent, its expiration time is calculated as the sum of
the time-to-live value specified on the send method and the current GMT
value. On return from the send method, the message's JMSExpiration header
field contains this value.
</description>
<referenceId>section.3.4.9</referenceId>
</requirement>
<requirement requirementId="message.expiration.receive">
<description>
When a message is received its JMSExpiration header field contains the
expiration as that on send.
</description>
<referenceId>section.3.4.9</referenceId>
</requirement>
<requirement requirementId="message.expiration.zero">
<description>
If the time-to-live is specified as zero, expiration is set to zero to
indicate that the message does not expire.
</description>
<referenceId>section.3.4.9</referenceId>
</requirement>
<requirement requirementId="message.expiration.expired">
<description>
When GMT is later than an undelivered message's expiration time, the
message should be destroyed.
Clients should not receive messages that have expired; however, JMS does
not guarantee that this will not happen.
</description>
<referenceId>section.3.4.9</referenceId>
</requirement>
<requirement requirementId="message.replyTo">
<description>
The JMSReplyTo header field contains a Destination supplied by a client
when a message is sent. It is the destination where a reply to the
message should be sent.<br/>
Messages sent with a null JMSReplyTo value may be a notification of some
event or they may just be some data the sender thinks is of interest.
</description>
<referenceId>section.2.10</referenceId>
<reference>
<section name="3.4.6" title="JMSReplyTo" />
</reference>
</requirement>
<requirement requirementId="message.creation">
<description>
When a message is created, its message body and properties may be set.
</description>
<reference>
<section name="3.3" title="JMS Messages" />
</reference>
</requirement>
<requirement requirementId="properties.identifier">
<description>
An identifier is an unlimited-length character sequence that must begin
with a Java identifier start character; all following characters must be
Java identifier part characters. An identifier start character is any
character for which the method Character.isJavaIdentifierStart returns
true. An identifier part character is any character for which the
method Character.isJavaIdentifierPart returns true.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="properties.identifier.reserved">
<description>
Identifiers cannot be the words NULL, TRUE, FALSE, NOT, AND, OR, BETWEEN,
LIKE, IN, IS, or ESCAPE. These are case-insensitive reserved words.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="properties.identifier.case">
<description>
Identifiers are case sensitive.
</description>
<referenceId>section.3.8.1.1</referenceId>
</requirement>
<requirement requirementId="properties.types">
<description>
Property values can be boolean, byte, short, int, long, float, double,
and String.
</description>
<referenceId>section.3.5.2</referenceId>
</requirement>
<requirement requirementId="properties.objects">
<description>
The setObjectProperty method accepts values of Boolean, Byte, Short,
Integer, Long, Float, Double and String. An attempt to use any other
class must throw a JMS MessageFormatException.<br/>
The getObjectProperty method only returns values of null, Boolean, Byte,
Short, Integer, Long, Float, Double and String. A null value is returned
if a property by the specified name does not exist.
</description>
<referenceId>section.3.5.5</referenceId>
<referenceId>section.3.5.8</referenceId>
</requirement>
<requirement requirementId="properties.integrity">
<description>
User properties may not be modified by the provider
</description>
<referenceId>implied</referenceId>
</requirement>
<requirement requirementId="properties.conversion">
<description>
Properties support the following conversion table. The marked cases must
be supported. The unmarked cases must throw the JMS
MessageFormatException.<br/>
The String to numeric conversions must throw the
java.lang.NumberFormatException if the numeric's valueOf() method does
not accept the String value as a valid representation.
A value set as the row type can be read as the column type.<br/>
<table border="1">
<tr>
<th>&#160;</th><th>boolean</th><th>byte</th><th>short</th>
<th>int</th><th>long</th><th>float</th><th>double</th><th>String</th>
</tr>
<tr>
<th>boolean</th>
<td><b>X</b></td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td><b>X</b></td>
</tr>
<tr>
<th>byte</th><td>&#160;</td><td><b>X</b></td><td><b>X</b></td>
<td><b>X</b></td><td><b>X</b></td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td>
</tr>
<tr>
<th>short</th><td>&#160;</td><td>&#160;</td><td><b>X</b></td>
<td><b>X</b></td><td><b>X</b></td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td>
</tr>
<tr>
<th>int</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td><td><b>X</b></td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td>
</tr>
<tr>
<th>long</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td>
</tr>
<tr>
<th>float</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td><b>X</b></td><td><b>X</b></td>
<td><b>X</b></td>
</tr>
<tr>
<th>double</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td><b>X</b></td>
<td><b>X</b></td>
</tr>
<tr>
<th>String</th><td><b>X</b></td><td><b>X</b></td><td><b>X</b></td>
<td><b>X</b></td><td><b>X</b></td><td><b>X</b></td><td><b>X</b></td>
<td><b>X</b></td>
</tr>
</table>
</description>
<referenceId>section.3.5.4</referenceId>
<referenceId>table.3-2</referenceId>
</requirement>
<requirement requirementId="properties.conversion.null">
<description>
Attempting to read a null value as a Java primitive type must be treated
as calling the primitive's corresponding valueOf(String) conversion
method with a null value.
</description>
<referenceId>section.3.5.4</referenceId>
<referenceId>section.3.5.8</referenceId>
</requirement>
<requirement requirementId="properties.method.getPropertyNames">
<description>
The order of property values is not defined. To iterate through a
message's property values, use getPropertyNames to retrieve a property
name enumeration and then use the various property get methods to
retrieve their values.
The getPropertyNames method does not return the names of the JMS standard
header fields.
</description>
<referenceId>section.3.5.6</referenceId>
</requirement>
<requirement requirementId="message.send">
<description>
After sending a message, a client may retain and modify it without
affecting the message that has been sent. The same message object may be
sent multiple times.
</description>
<reference>
<section name="3.9" title="Access to sent messages" />
</reference>
</requirement>
<requirement requirementId="message.receive">
<description>
When a message is received its body is read only. If an attempt is made
to change them, a MessageNotWriteableException must be thrown.
If its properties or body are subsequently cleared, they are in the same
state as a newly created message.
TODO - need to test in transaction context
</description>
<reference>
<section name="3.5.3" title="Using Properties" />
</reference>
<reference>
<section name="3.10" title="Changing the Value of a Received Message" />
</reference>
<reference>
<section name="3.11.2" title="Read-Only Message Body" />
</reference>
</requirement>
<requirement requirementId="message.method.clearBody">
<description>
The clearBody method of Message resets the value of the message body to
the empty initial message value as set by the message type's create method
provided by Session. Clearing a message's body does not clear its property
entries. When a message is cleared, its message body and properties may
be set.
</description>
<reference>
<section name="3.11.1" title="Clearing a message body" />
</reference>
</requirement>
<requirement requirementId="message.method.clearProperties">
<description>
Clearing a message's properties leaves the message with an empty set of
properties. New property entries can then be both created and read.
Clearing a message's property entries does not clear the value of its
body.
</description>
<reference>
<section name="3.5.7" title="Clearing a Message's Property Values" />
</reference>
</requirement>
<requirement requirementId="message.bytes.creation">
<description>
When the message is first created, the body of the message is in
write-only mode. If a client attempts to read a message in write-only
mode, a MessageNotReadableException is thrown.
</description>
<referenceId>url.message.bytes</referenceId>
</requirement>
<requirement requirementId="message.bytes.eof">
<description>
MessageEOFException must be thrown when an unexpected end of stream has
been reached when a message is being read.
</description>
<referenceId>section.7.3</referenceId>
</requirement>
<requirement requirementId="message.object.method.setObject">
<description>
The setObject method places a copy of the input in the message.
</description>
<reference>
<section name="11.2.21" title="JMS Source JavaDoc Clarifications"/>
</reference>
</requirement>
<requirement requirementId="message.stream.creation">
<description>
When the message is first created, the body of the message is in
write-only mode. If a client attempts to read a message in write-only
mode, a MessageNotReadableException is thrown.
</description>
<referenceId>url.message.stream</referenceId>
</requirement>
<requirement requirementId="message.stream.eof">
<description>
MessageEOFException must be thrown when an unexpected end of stream has
been reached when a message is being read.
</description>
<referenceId>section.7.3</referenceId>
</requirement>
<requirement requirementId="message.bytes.read">
<description>
If a read method of a BytesMessage throws a MessageFormatException or
NumberFormatException, the current position of the read pointer must not
be incremented. A subsequent read must be capable of recovering from the
exception by re-reading the data as a different type.<br/>
NOTE: With the exception of the readUTF() method, it is difficult to
conceive test cases for read methods.
<ul>
<li>
A provider that implements BytesMessage using a DataInputStream
or equivalent, is likely to only throw MessageFormatException for
the readUTF() method.<br/>
The other likely exceptions are MessageEOFException for stream
overruns, and JMSException for any other error.
</li>
<li>
As BytesMessage does not support conversion, NumberFormatException
is unlikely to be thrown.
</li>
</ul>
</description>
<referenceId>section.3.11.3</referenceId>
</requirement>
<requirement requirementId="message.stream.read">
<description>
If a read method of a StreamMessage throws a MessageFormatException or
NumberFormatException, the current position of the read pointer must not
be incremented. A subsequent read must be capable of recovering from the
exception by re-reading the data as a different type.
</description>
<referenceId>section.3.11.3</referenceId>
<referenceId>table.3-7</referenceId>
</requirement>
<requirement requirementId="message.map">
<description>
A MapMessage is a message whose body contains a set of name-value pairs
where names are Strings and values are Java primitive types. The entries
can be accessed sequentially by enumerator or randomly by name. The
order of the entries is undefined.
</description>
<referenceId>section.3.11</referenceId>
</requirement>
<requirement requirementId="message.map.conversion">
<description>
MapMessage supports the following conversion table.
The marked cases must be supported. The unmarked cases must throw a JMS
MessageFormatException. The String to numeric conversions must throw a
java.lang.NumberFormatException if the numeric's valueOf() method does
not accept the String value as a valid representation.
MapMessage must implement the String to boolean conversion as
specified by the valueOf(String) method of Boolean as defined by the
Java language.<br/>
A value written as the row type can be read as the column type.<br/>
<table border="1">
<tr>
<th>&#160;</th><th>boolean</th><th>byte</th><th>short</th>
<th>char</th><th>int</th><th>long</th><th>float</th><th>double</th>
<th>String</th><th>byte[]</th>
</tr>
<tr>
<th>boolean</th>
<td><b>X</b></td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>byte</th><td>&#160;</td><td><b>X</b></td><td><b>X</b></td>
<td>&#160;</td><td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>short</th><td>&#160;</td><td>&#160;</td><td><b>X</b></td>
<td>&#160;</td><td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>char</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>int</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>long</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td><b>X</b></td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>float</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td><b>X</b></td>
<td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>double</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>String</th><td><b>X</b></td><td><b>X</b></td><td><b>X</b></td>
<td>&#160;</td><td><b>X</b></td><td><b>X</b></td><td><b>X</b></td>
<td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>byte[]</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td><b>X</b></td>
</tr>
</table>
</description>
<referenceId>section.3.11.3</referenceId>
<referenceId>table.3-7</referenceId>
</requirement>
<requirement requirementId="message.map.null">
<description>
For MapMessage, attempting to read a null value as a Java primitive
type must be treated as calling the primitive's corresponding
valueOf(String) conversion method with a null value. Since char does not
support a String conversion, attempting to read a null value as a char
must throw NullPointerException.
</description>
<referenceId>section.3.11.3</referenceId>
</requirement>
<requirement requirementId="message.map.unset">
<description>
Getting a MapMessage field for a field name that has not been set is
handled as if the field exists with a null value.
</description>
<referenceId>section.3.11.3</referenceId>
</requirement>
<requirement requirementId="message.stream.conversion">
<description>
StreamMessage supports the following conversion table.
The marked cases must be supported. The unmarked cases must throw a JMS
MessageFormatException. The String to numeric conversions must throw a
java.lang.NumberFormatException if the numeric's valueOf() method does
not accept the String value as a valid representation.
StreamMessage must implement the String to boolean conversion as
specified by the valueOf(String) method of Boolean as defined by the
Java language.<br/>
A value written as the row type can be read as the column type.<br/>
<table border="1">
<tr>
<th>&#160;</th><th>boolean</th><th>byte</th><th>short</th>
<th>char</th><th>int</th><th>long</th><th>float</th><th>double</th>
<th>String</th><th>byte[]</th>
</tr>
<tr>
<th>boolean</th>
<td><b>X</b></td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>byte</th><td>&#160;</td><td><b>X</b></td><td><b>X</b></td>
<td>&#160;</td><td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>short</th><td>&#160;</td><td>&#160;</td><td><b>X</b></td>
<td>&#160;</td><td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>char</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>int</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>long</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td><b>X</b></td><td>&#160;</td>
<td>&#160;</td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>float</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td><b>X</b></td>
<td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>double</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>String</th><td><b>X</b></td><td><b>X</b></td><td><b>X</b></td>
<td>&#160;</td><td><b>X</b></td><td><b>X</b></td><td><b>X</b></td>
<td><b>X</b></td><td><b>X</b></td><td>&#160;</td>
</tr>
<tr>
<th>byte[]</th><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td>&#160;</td><td>&#160;</td>
<td>&#160;</td><td>&#160;</td><td><b>X</b></td>
</tr>
</table>
</description>
<referenceId>section.3.11.3</referenceId>
<referenceId>table.3-7</referenceId>
</requirement>
<requirement requirementId="message.map.case">
<description>
MapMessage field names are case sensitive.<br/>
NOTE: the specification does not explicitly mention this requirement,
but it is in keeping with property name requirements.
</description>
<referenceId>implied</referenceId>
</requirement>
<requirement requirementId="message.stream.null">
<description>
For StreamMessage, attempting to read a null value as a Java primitive
type must be treated as calling the primitive's corresponding
valueOf(String) conversion method with a null value. Since char does not
support a String conversion, attempting to read a null value as a char
must throw NullPointerException.<br/>
NOTE: the specification is not explicit on the behaviour of invoking
writeBytes() or writeString() with a null value, but an acceptable policy
is to throw a NullPointerException. This is in keeping with the behaviour
of DataOutputStream.
</description>
<referenceId>section.3.11.3</referenceId>
</requirement>
<requirement requirementId="message.foreign">
<description>
A provider must be prepared to accept, from a client, a
message whose implementation is not one of its own.
A message with a 'foreign' implementation may not be handled as
efficiently as a provider's own implementation; however, it must be
handled.<br/>
Note that if the foreign message implementation contains a
<em>JMSReplyTo</em> header field that is set to a foreign destination
implementation, the provider is not required to handle or preserve the
value of this field.
</description>
<referenceId>section.3.12</referenceId>
</requirement>
<requirement requirementId="message.copy">
<description>
The JMS message interfaces provide read/get methods for accessing
objects in a message body. All of these methods must be implemented to
return a copy of the accessed objects.
</description>
<referenceId>section.3.12</referenceId>
</requirement>
<requirement requirementId="properties.copy">
<description>
The JMS message interfaces provide read/get methods for accessing
message object properties. All of these methods must be implemented to
return a copy of the accessed objects.
</description>
<referenceId>section.3.12</referenceId>
</requirement>
<requirement requirementId="message.bytes.method.clearBody">
<description>
When clearBody is called on a BytesMessage, the body of the message is in
write-only mode.<br/>
If clearBody is called on a message in read-only mode, the message body
is cleared and the message is in write-only mode.
</description>
<referenceId>url.message.bytes</referenceId>
</requirement>
<requirement requirementId="message.bytes.method.readBytes(1)">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/BytesMessage.html#readBytes(byte[])</url>
</reference>
</requirement>
<requirement requirementId="message.bytes.method.readBytes(2)">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/BytesMessage.html#readBytes(byte[], int)</url>
</reference>
</requirement>
<requirement requirementId="message.bytes.method.writeObject">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/BytesMessage.html#writeObject()</url>
</reference>
</requirement>
<requirement requirementId="message.map.method.setObject">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/MapMessage.html#setObject()</url>
</reference>
</requirement>
<requirement requirementId="message.map.method.itemExists">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/MapMessage.html#itemExists()</url>
</reference>
</requirement>
<requirement requirementId="message.map.method.getMapNames">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/MapMessage.html#getMapNames()</url>
</reference>
</requirement>
<requirement requirementId="message.stream.method.clearBody">
<description>
When clearBody is called on a StreamMessage, the body of the message is
in write-only mode.<br/>
If clearBody is called on a message in read-only mode, the message body
is cleared and the message is in write-only mode.
</description>
<referenceId>url.message.stream</referenceId>
</requirement>
<requirement requirementId="message.stream.method.writeObject">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/StreamMessage.html#writeObject()</url>
</reference>
</requirement>
<requirement requirementId="message.stream.method.writeBytes(1)">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/StreamMessage.html#writeBytes(byte[])</url>
</reference>
</requirement>
<requirement requirementId="message.stream.method.writeBytes(2)">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/StreamMessage.html#writeBytes(byte[], int, int)</url>
</reference>
</requirement>
<requirement requirementId="message.stream.method.readBytes">
<description>
Refer to javadoc
</description>
<reference>
<url>http://java.sun.com/products/jms/javadoc-102a/javax/jms/StreamMessage.html#readBytes</url>
</reference>
</requirement>
<requirement requirementId="properties.group">
<description>
JMSXGroupID and JMSXGroupSeq are standard properties clients should use
if they want to group messages. All providers must support them.
JMSXGroupID is a string property. JMSXGroupSeq is an int property,
starting at 1. @todo - need to verify if the range is applicable
</description>
<referenceId>section.3.5.9</referenceId>
<referenceId>table.3-3</referenceId>
</requirement>
<requirement requirementId="properties.provider">
<description>
JMS reserves the 'JMSX' property name prefix for JMS defined properties.
Unless noted otherwise, support for these properties is optional. The
Enumeration ConnectionMetaData.getJMSXPropertyNames() method returns the
names of the JMSX properties supported by a connection.
Properties that may only be set by the provider include JMSXUserID,
JMSXAppID, JMSXDeliveryCount, JMSXProducerTXID, JMSXConsumerTXID,
JMSXRcvTimestamp and JMSXState.
</description>
<referenceId>section.3.5.9</referenceId>
<referenceId>table.3-3</referenceId>
</requirement>
<requirement requirementId="connection.metadata.properties">
<description>
ConnectionMetaData provides a list of the JMS defined property names
supported by the connection. This must include JMSXGroupID and
JMSXGroupSeq
</description>
<referenceId>section.3.5.9</referenceId>
</requirement>
<requirement requirementId="subscriber.nolocal">
<description>
In some cases, a connection may both publish and subscribe to a topic.
The subscriber NoLocal attribute allows a subscriber to inhibit the
delivery of messages published by its own connection.
</description>
<referenceId>section.6.11</referenceId>
</requirement>
<requirement requirementId="subscriber.durable">
<description>
If a client needs to receive all the messages published on a topic,
including the ones published while the subscriber is inactive, it uses a
durable TopicSubscriber. JMS retains a record of this durable
subscription and insures that all messages from the topic's publishers
are retained until either they are acknowledged by this durable
subscriber or they have expired.
</description>
<referenceId>section.6.11.1</referenceId>
<referenceId>section.6.3</referenceId>
</requirement>
<requirement requirementId="subscriber.durable.clientId">
<description>
Sessions with durable subscribers must always provide the same client
identifier. In addition, each client must specify a name that uniquely
identifies (within client identifier) each durable subscription it
creates.
</description>
<referenceId>section.6.11.1</referenceId>
</requirement>
<requirement requirementId="subscriber.durable.unique">
<description>
Only one session at a time can have a TopicSubscriber for a
particular durable subscription.
</description>
<referenceId>section.6.11.1</referenceId>
<referenceId>section.4.3.2</referenceId>
</requirement>
<requirement requirementId="subscriber.durable.changing">
<description>
A client can change an existing durable subscription by creating a
durable TopicSubscriber with the same name and a new topic and/or
message selector. Changing a durable subscription is equivalent to
deleting and recreating it.
</description>
<referenceId>section.6.11.1</referenceId>
</requirement>
<requirement requirementId="subscriber.durable.unsubscribe">
<description>
TopicSessions provide the unsubscribe method for deleting a durable
subscription created by their client. This deletes the state being
maintained on behalf of the subscriber by its provider.
It is erroneous for a client to delete a durable subscription while it
has an active TopicSubscriber for it or while a message received by it
is part of a current transaction or has not been acknowledged in the
session.
(Note: this last sentence suggests that a provider doesn't need to check
that a client can remove a subscription)
</description>
<referenceId>section.6.11.1</referenceId>
</requirement>
<requirement requirementId="asf.connectionconsumer">
<description>
For application servers, connections provide a special facility for
creating a ConnectionConsumer. The messages it is to consume are
specified by a destination and a message selector. In addition, a
ConnectionConsumer must be given a ServerSessionPool to use for
processing its messages. A maxMessages value is specified to limit the
number of messages a ConnectionConsumer may load at one time into a
ServerSession's session.
</description>
<referenceId>section.8.2.4</referenceId>
</requirement>
<requirement requirementId="destination.remove">
<description>
If a destination is removed via the provider's administration interface,
and subsequently recreated, all messages to that destination must also
be removed.
</description>
<referenceId>implied</referenceId>
</requirement>
</document>