Sample 471: Introduction to the EJB Mediator II - Invoking Stateful Session Beans

<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>

Objective

Demonstrate the usage of the EJB mediator for invoking EJB Stateful Session Beans hosted on a remote EJB Container.

Pre-requisites

  • Follow steps 1 to 5 in Sample 470 to host the EJBs in an EJB Container of your choice and to configure the demo beanstalk.
  • If the JNDI names assigned to the EJBs by your EJB Container differ from the JNDI names specified in the sample 471 configuration file (repository/conf/sample/synapse_sample_471.xml), edit the jndiName attribute of all < ejb /> mediator invocations in the synapse_sample_471.xml accordingly.
  • Start Synapse using the configuration numbered 471 (repository/conf/sample/synapse_sample_471.xml):
    Unix/Linux: sh synapse.sh -sample 471
    Windows: synapse.bat -sample 471

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>

Back to Catalog