Friday, August 10, 2012

Issues and solutions when testing and developing asynchronous BPEL processes

Webservices, when developed, need testing. Some difficulties with testing webservices are the following;


- asynchronous services are not easily tested outside Fusion Middleware Control if there is no service available handling the correlation
- often it is not visible directly what the raw HTTP message is which is transmitted. HTTP headers are often hidden from the monitoring tooling. Also in case for example the Oracle HTTP binding adapter is used to do a JSON call, the adapter proxies the message. This causes only the adapter call to be visible in the audit trail in the Enterprise Manager.
- metrics for load tests are often needed. the start situation needs to be reproduced for subsequent tests and thus these metrics need to allow resetting

In this post I will describe solutions to these issues. A collegue Marcel Bellinga has provided suggestions on resetting of the metrics, usage of the JDeveloper HTTP Analyzer and has solved the issue when calling an asynchronous proces using a synchronous one in JDeveloper 11.1.1.6.

Setup

I've created a synchronous HelloWorldAsync service. This service is wrapped by a synchronous HelloWorldAsyncCaller service. I want to know exactly (including HTTP headers) which message is send to the HelloWorldAsync service by the HelloWorldAsyncCaller service. In addition to this I want to be able to test the HelloWorldAsync service from SOAP-UI and collect metrics on the requests on the application server (SOAP UI can provide load tests but those are influenced by network latency and I'm not interested to take that also into account since it is time and customer dependant).

One first thing to mind in this setup is the following; when calling an asynchronous service from a synchronous one with a project created in JDeveloper 11.1.1.6, you will encounter the following error;

[2012-08-10T01:09:32.472-07:00] [AdminServer] [ERROR] [] [oracle.soa.bpel.engine.delivery] [tid: [ACTIVE].ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] [userId: <anonymous>] [ecid: 11d1def534ea1be0:7c9113cc:1390f864b2c:-8000-0000000000000579,0:9] [WEBSERVICE_PORT.name: HelloWorldAsyncCaller_pt] [APP: soa-infra] [composite_name: HelloWorldAsyncCaller] [J2EE_MODULE.name: fabric] [WEBSERVICE.name: helloworldasynccaller_client_ep] [J2EE_APP.name: soa-infra] No response found for the reply for conversation id urn:99E85AE0E2C211E1BF3487E7CAA738F8

And then

[2012-08-10T01:09:32.836-07:00] [AdminServer] [ERROR] [OWS-04086] [oracle.webservices.service] [tid: [ACTIVE].ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] [userId: <anonymous>] [ecid: 11d1def534ea1be0:7c9113cc:1390f864b2c:-8000-0000000000000579,0:9] [APP: soa-infra] [composite_name: HelloWorldAsyncCaller] javax.xml.rpc.soap.SOAPFaultException: Waiting for response has timed out. The conversation id is null. Please check the process instance for detail.[[

This is caused by the following setting in the composite.xml file;

  <component name="HelloWorldAsyncCaller" version="2.0">
    <implementation.bpel src="HelloWorldAsyncCaller.bpel"/>
    <property name="bpel.config.transaction" type="xs:string" many="false">required</property>
  </component>

If this line is removed or changed to

    <property name="bpel.config.transaction" type="xs:string" many="false">requiresNew</property>

This error will not occur.

This property (Transaction in the below screenshot) is created when creating a synchronous BPEL process in JDeveloper 11.1.1.6. In previous versions (11.1.1.4 was checked), the property was not added by default.


Asynchronous correlation issues with parallel execution in foreach

In order to increase performance, parallel execution in the foreach construct in BPEL 2.0 can be used. In a synchronous process when calling asynchronous services inside a loop in which all branches are executed simultaneously, the 'Conflicting receive' error can occur. To avoid this, correlation sets can be used. Using correlation sets is however relatively complex and requires the response message to contain correlation information in the message content. In order to avoid having to use correlation sets to achieve this, it is of course possible to wrap the asynchronous service in a synchronous one as described above (if the asynchronous service doesn't take too long) and call the synchronous process from the loop in the calling synchronous process (Synchronous process with loop -> synchronous process wrapper -> asynchronous process). It is however a better solution to define the partnerlink on the level of the scope which is executed in parallel. If you define the same partnerlink in global BPEL scope and in the scope which is executed in parallel, you can assign values to the request/response messages more easily. If a partnerlink is defined locally only, this is not always possible.

Monitoring

Monitoring service calls

JDeveloper has has an HTTP Analyzer and it is possible to specify the HTTP Analyzer as proxy in Fusion Middleware Control. This causes webservice requests to be proxied by the analyzer and allows the complete request to be monitored.

Start the HTTP Analyzer


Specify the IP of the machine running the HTTP Analyzer as HTTP proxy

 Test the webservice and look at the results
 

I was however surprised I couldn't see the HelloWorldAsyncCaller HTTP requests to the HelloWorldAsync process. I created a simple JAX-WS webservice instead to test this. Actually, this was correct; there were no HTTP requests to find here. If a BPEL process calls another BPEL process running in the same container, the transformation to HTTP is not done, which has of course benefits for performance. Load balancing however is something to think about as it requires more then just setting the load balancer as HTTP proxy in the services.

Testing asynchronous services with SOAP-UI

SOAP-UI (http://www.soapui.org/) is a tool which is often used for testing of webservices. Testing of asynchronous services is explained on; http://www.oracle.com/technetwork/articles/soa/bpel-amadei-1518001.html.

Key is creating a test suite with two steps; a request and a mock response. The request contains WS-Adressing headers and a ReplyTo indication so the response is send to the Mock Response listener in SOAP UI.


Things to mind in the previously mentioned post; the specified path in step 8 under 'Testing it' should correspond to the ReplyTo path specified in the WS-Adressing section of the request. Also the ReplyTo address should point to the machine running SOAP UI. If the development environment is not running locally, the IP address of your machine should be specified here.





Process metrics

A servlet is available to analyze process metrics. See section 6.4.1 of http://docs.oracle.com/cd/E25178_01/core.1111/e10108.pdf for more information on this DMS Spy servlet. It can be started by going to http://<host>:<port>/dms/Spy.

How these metrics can be reset, can be found on; https://blogs.oracle.com/soaproactive/entry/how_to_reset_a_soa

An example URL for resetting metrics; http://localhost:7001/dms/Spy?operation=reset&format=raw&cache=refreshall&name=/dev_soa_osb/AdminServer/soainfra/default/HelloWorldAsyncCaller&recurse=all

The sample projects can be downloaded here; https://dl.dropbox.com/u/6693935/blog/TestApp.zip