<definitions>
<proxy name="BuyAllProxy" transports="https http" startOnLoad="true" trace="disable">
<target>
<!-- Iterate over all items in the request and call addItem() on the ShoppingCart EJB for each item. -->
<inSequence>
<property name="SESSION_ID" expression="get-property('MessageID')"/>
<iterate xmlns:m0="http://services.samples" preservePayload="false"
expression="//m0:buyItems/m0:items/m0:item">
<target>
<sequence>
<ejb class="samples.ejb.ShoppingCart" beanstalk="demo" method="addItem" sessionId="{get-property('SESSION_ID')}" jndiName="ShoppingCartBean/remote">
<args>
<arg value="{//m:item//m:id}" xmlns:m="http://services.samples"/>
<arg value="{//m:item//m:quantity}" xmlns:m="http://services.samples"/>
</args>
</ejb>
<sequence key="collector"/>
</sequence>
</target>
</iterate>
</inSequence>
</target>
</proxy>
<!-- Prepare the response once all addItem() calls are finished. -->
<sequence name="collector">
<aggregate>
<onComplete>
<ejb class="samples.ejb.ShoppingCart" beanstalk="demo" method="getItemCount" sessionId="{get-property('SESSION_ID')}" target="ITEM_COUNT"/>
<ejb class="samples.ejb.ShoppingCart" beanstalk="demo" method="getTotal" sessionId="{get-property('SESSION_ID')}" target="TOTAL" remove="true"/>
<payloadFactory>
<format>
<buyAllResponse xmlns="">
<itemCount>$1</itemCount>
<total>$2</total>
</buyAllResponse>
</format>
<args>
<arg expression="get-property('ITEM_COUNT')"/>
<arg expression="get-property('TOTAL')"/>
</args>
</payloadFactory>
<respond/>
</onComplete>
</aggregate>
</sequence>
</definitions>
Executing the Client
Send the following request to http://localhost:8280/services/BuyAllProxy
using a tool such at TCPMon or curl.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<buyItems xmlns="http://services.samples">
<items>
<item>
<id>2150</id>
<quantity>1</quantity>
</item>
<item>
<id>1189</id>
<quantity>2</quantity>
</item>
<item>
<id>890</id>
<quantity>4</quantity>
</item>
</items>
</buyItems>
</soapenv:Body>
</soapenv:Envelope>
Each instance of the ShoppingCart stateful session bean hosted on the remote EJB container
maintains a state which keeps track of the number and the total price of the items
added via its addItem(String itemId, int count) method. The float getTotal() and
int getItemCount() methods are used to retrieve this state.
When the BuyAllProxy receives the above request, it iterates over all <item> elements
in the request and calls the addItem() method on the ShoppingCart bean,
once per each <item>, using the EJB mediator. Since the sessionId used for these
invocations is actually the message ID, each request works on a new ShoppingCart instance
which is created at the first EJB mediator invocation in that request's flow.
When all addItem() method calls are finished, getItemCount() and getTotal() methods
are invoked on the same ShoppingCart instance within the collector sequence and
results are stored in two message context properties named ITEM_COUNT and TOTAL.
The last EJB call on the shopping cart sets the EJB mediator attribute remove = "true"
instructing the current stateful bean stub to be removed from the beanstalk. This is because the
same stateful bean instance will not be used again (each request uses a new bean instance). If the
user does not explicitly remove the stub using this attribute, it will be removed automatically
upon timeout as specified by the beanstalk configuration.
Finally, the PayloadFactory mediator is used to build the response message which is sent back to the
client.
A sample response is shown below.
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<buyAllResponse>
<itemCount>7</itemCount>
<total>807.0</total>
</buyAllResponse>
</soapenv:Body>
</soapenv:Envelope>