----- Original Message -----
Sent: Thursday, February 26, 2004
7:05 PM
Subject: [ebxml-iic] edits for
GetMessage() op
Mike:
Some proposed additions in the section below
(in bold). Please update if not correct.
Should the Filter of a GetMessage() op produce a "Result" element
containing the resulting node-set?
Jacques
Semantics of the GetMessage operation
A fundamental aspect of the GetMessage
operation is its behavior and
effect over the Message Store.
The Message Store is an XML document
object that contains an XML representation of all synchronous and
asynchronously received ebXML messages for a Test Case. The received
messages for a particular Test Case MUST persist in the Message
Store for the life of the Test Case. Messages in the Message Store
MAY contain all MIME, SOAP and ebXML or other types of message content,
represented as an XML document. The particular XML representation of
a message in the Message Store is based upon an a "best practice"
schema for representing a particular message type. If the messages
being stored are ebXML messages using HTTP transport and a SOAP envelope,
the XML format of the Message Store document MUST validate against the
ebXMLMessageStore.xsd schema in appendix D.
The GetMessage Filter sub-operation queries the
Message Store document object, and retrieves (by default) the XML content
that satisfies the XPath expression specified in its Filter child
element. As the MessageStore is
updated every time a new message comes in, a GetMessage() operation will
automatically execute as often as needed, until either (1) its Filter
selects and returns a non-empty node-set, or (2) the timeout
(stepDuration) expires.
[MIKE] - suggest
adding:
A
TestPreCondition and/orTestAssertion sub-operation ( which also contain a
single XPath query) query the resulting document object constructed
from the node-list generated by a GetMessage Filter operation. That
document object to be examined by a TestPreCondition of TestAssertion
action MUST have a root element with a name of test:Result ( as
defined in the Result schema in Appendix XX). If the Test
Driver is unable to create a Result document object because the
resulting node-list contains any XML content other than elements ( such as
an attribute list), then the Test Driver MUST generate an exception, and
terminate the Test Case with a result of "undetermined". (i.e. if
the XPath query does not return XML content that can be built
into a document object, then it cannot be further examined with XPath in
the TestPreCondition or TestAssertion operations)
[Jacques Durand] sounds good. I think
we can even be more specific: the Filter is supposed to apply to Message
elements always, and return such a
set.
NOTES:
All the message items available for querying, are children of the
MessageStore element. The Xpath expression in the Filter will typically
select all the /MessageStore/Message elements that satisfy the filter,
and these will be consolidated as children of a Result element,
available for further querying, e.g. by the TestAssertion
operation.
The messages that have been selected by
a GetMessage() operation are (suggest remove the
word 'normally'.. sounds ambiguous)
[Jacques
Durand] fine.
"invisible" to future
Getmessage() operations in the same test case, unless the "mask"
attribute is set to "false" (default is "true"). A GetMessage()
operation will execute over all messages in the message store for this
test case, except those messages that have been masked by a previous
GetMessage() operation. [MIKE] - My interpretation
of what you are saying here ( and what will be necessary to
implement) is that there will have to be 2 MessageStores ( this
would seem the only efficient way to make this transparent to the test
writer ). If I do a <GetMessage mask="true"> ( the default )
then any messages that contain a node in the returned nodelist are
"moved" to the "masked" MessageStore after the <GetMessage>
operation.
[Jacques Durand] The way I see it, we
don't need two message stores: we still always work with the original
message store. Only, I make the following implementation assumptions:
(1) in the message store, each message is numbered when added (e.g.
M001, M002, M003 etc.) i.e. we add an identifier just for the sake of
the message store (there is already an Id in the schema, but we are
talking here of something different than the Id in the message header,
probably would need to add that to the store schema?). (2)
When a Getmessage() is masking a message, it just adds its store
identifier in a list of "masked messages" for this test case. (3)
When a GetMessage() executes, it selects messages that satisfy its
Filter AND the identifier of which are not in the masked list.
[MIKE2] - Here is perhaps where the problem
is. XPath processors only perform what is stated in the
query. In order to "add" this to a test writer's XPath query
(which can be expressed in a virtually infiniate number of ways) and
still make it "transparent" to the test writer... the Test Driver must
either:
a)Automatically modify the query to include
checking the <Message> element's "masked" attribute for value of
true/false.. (scary since the same XPath query can be expressed in a
virtually infinite number of ways.. and parsing and substituting
query text would be very difficult)
b) Have the test writer explicitly write their
XPath query (like below) to include a
@masked="true/false" since there is only one MessageStore,
containing both masked and unmasked messages, and the XPath processor
must be able to differentiate the two
types
/MessageStore[Message
@masked="true"//eb:MessageHeader/eb:MessageData[eb:ConversationId='123']]
c) Have the default be that all incoming
messages that match a particular <Filter> operation are actually
"removed" from the MessageStore ( that is the only way to transparently
"mask" them for a test writer...and an XPath
processor) This makes it transparent to the test writer, and
if they want to "save" messages that they've <Filter>ed, the must
specifically do a <GetMessage mask="false"/> to save them for
subsequent queries..
The one thing that a test writer would have to
be aware of ( if they wish to examine message content in a
subsequent <TestStep> or <Thread> ) is that they need to
explicitly set mask="false"
This can be easily done using XSLT (XSLT
processors can take several input docs: the store, and the masked
list.)
[MIKE2] - I agree that an XSLT processor could
easily modify an incoming message to add a "masked" attribute.
It's the modification of the incoming XPath query that is very
problematic. I'd opt to "remove" masked messages from the
MessageStore.. and keep life simple for XPath query writers.. and the
Test Driver...
This is a bit tricky ( will
require the Test Driver to traverse "back up" the document tree to the
root <MessageStore> element, and copy the <Message>(s) that
contain the matching node-set node(s) and delete them from the
"unmasked" MessageStore. and add them to the "masked"
MessageStore. This will be a bit time-consuming for the Test
Driver ( unless the default is mask="false".. a more likely
scenario in testing I think ). Also.. there is the
issue of "side-effects". Since the MessageStore is a
"global" data resource, available to any concurrently running
Thread... "masking" (i.e. deleting) messages that may be needed by
a concurrently running GetMessage operation would introduce
problems unless the test writer is aware of them.
[Jacques
Durand] Well, masking / unmasking is the choice of the test writer.
But "side effect" is a relative concept: Thread A consuming a coming
message that was intended for itself, and leaving it in the store, will
be a serious side effect for Thread B which will see it...
[MIKE2] - Agreed. Then I would recommend a
"removal" type masking as the easiest way to keep scripting simple,
and make the default
Everything a thread does or does not do on the
store, will be a side effect to other concurrent threads anyway, since
the structure is shared.
[MIKE2] - Agreed
Lastly, I would hope that
"masking" would not require "unmasking". If so, then we need to
introduce another operation called <Unmask> to move the messages
back to the "unmasked" MessageStore.
[Jacques
Durand] Right, masking a message will not require "unmasking": it
really means it was intended to be consumed once, like so far it is the
case in all test cases I have seen for ebMS. The case where you want to
have the same message consumed twice e.g. by two successive GetMessage()
ops, is most unusual (which would be why "mask" is
default...)
Do implementers see this (masking)
as a necessary function? I think that we may be able to satisfy
the need to mask by simply assigning parameter values (e.g.
messageCount="5").. and if a subsequent GetMessage operation returns 10
messages, then a <TestAssertion>//Message[count() =5] would
fail... without the need to "mask"messages so that our count is set to
"0". Comments from implementers?
NOTES:
Examples of use:
If one wants to verify that within 300
seconds, exactly 5 messages with MessageId="123" have been received,
then the test case should first wait 300 sec before executing
GetMessage(). This is done with a "Sleep" operation. The
Sleep operation (not
step) must be followed by a GetMessage() operation (not step) with a Filter selecting any
message with MessageId="123", and a stepDuration of a few seconds at
most . The TestAssertion Xpath expression will finally verify that
the resulting node-set contains 5 message elements.
[Jacques
Durand] OK.
If one wants to verify that within 300 seconds, at least one
messages with DocumentType="PurchaseOrder" has been received, then it is
sufficient to use a GetMessage() test step with a stepDuration of 300
sec, and a Filter selecting DocumentType=" PurchaseOrder". This would
succeed as soon as a PurchaseOrder message is
received.