So recently I have been asked about async services on a SOA environment and the interesting about the questions is that most people are not really expecting me to simply show them how it is done, and I am going to show an example on this post, but rather how async service processing works at all, and I came up with a sort of “default” response to such inquiries that has been working so well that I decided to post it here so I can probably help more people around the net.
OK, so for you to understand why do you need async services at all I like to go deeper into the rabbit whole and explain what happens when the application server receives a request, what is an application server for in the first place and a very simple explanation about threads, the idea of this post is to give you a guide so you can look further details by yourself, so let´s do this thing!
What [the heck] are threads?
So, according to the wikipedia post, a thread of execution is the smallest unit of processing that can be scheduled by an operating system, as you may know everything that is resolved by a computer has to be submitted to processing by the CPU. Problem is one processor can actually process ONE task at a time! SO how does your computer is able to run your browser, your anti-virus, play your favorite music and all the other software it is running right now at the same time? It is not! So how is it happening?
You might want to take a look around for the history of processors, but what modern processors do is get every processing request and put them in a processing queue, then each process will receive a limited amount of time to use the processor unit, as soon as that time is finished that process returns to the end of the queue, it really depends on the process priority, and the next process will then be granted some processing time and that goes on for all the processes pending on the queue. We name this processing behaviour time-division multiplexing, and every place in this queue waiting for process we call a thread.
What are Application Servers then?
An Application Server(AS) is a system that serves applications, oh really? To understand this let’s say you want to access you bank account data right now, what do you do? You log in to your bank’s website and there it is for you. You do not have to call your bank manager and tell him you need to have the bank application running so you can access it, right? That happens because the application was already running on the bank’s application server. In addition to that you do not have to wait for some other bank clients to finish their transactions so you can access your data, that all happens at the same time.
The Application Server is really a software running on a machine that has embedded capabilities like hosting web-services, web-applications, accessing databases, securing your data and a lot more features so developers do not have to create those things from scratch every time they have to develop new software.
Application servers do a whole more than this, but again you will have to look further into this by yourself, I might even right something about this in the future however this is not our goal here.
So as you can see the application server serves one [or more] applications at the same time to various clients. It does that lending the processor’s thread capability! What happens is when you launch an application server it reserves a lot of places in that queue the processor has as I mentioned earlier by launching a bunch of threads and it organizes it in a group that we normally call a thread pool.
Everytime a client sends a processing request to any application running in the application server it retrieves a thread from the thread pool and assigns the task of processing that request, once the processing is finished the thread goes back to the thread pool waiting for new assignment.
Now what happens when all the threads are under assignment at the same time and a new request comes in? Well that depends a lot on the AS implementation and configuration but most of the time it either holds the client request for a few moments waiting for a thread to return to the pool, that time is usually configurable so after this time is reached we say that the request has timed-out and an error is returned, or it simply denies the request.
How does that lead me to Asynchronous services?
Well you have to understand now that having available threads at all times is a critical thing for applications servers since it relies on them to have received requests processed. Additionally there are certain requests you make to services that are not fulfilled in just a few seconds. Back to the bank example when you request a new credit card you do not want your browser to wait until you credit card is ready! This normally takes a few days! All you want to do is send the request, log off and go on with your life. This is a classic async service request.
When you use synchronous services for heavy processing you are overloading more than just AS threads, you are overloading network, while sync processes are running the connection to the client must be kept alive, processor, sync processes must happen immediately so if you have a great number of requests to those heavy services you will probably overload your server which may cause it to crash, when you design your system for async processing you can implement logic to balance that load.
There are various possible reasons you will choose async processing over sync but the most common reasons are those: long term services or heavy processing.
Show me how it is done!
This is a part that I think tutorial are not strong abou, examples, so what I am going to do here is quick example on how to implement a fully functional request/callback service using Oracle BPEL and Oracle Service Bus, the service client here will be regulkar SOAPUI 4.0.1 request, so we will be able to see all the little configurations you will have to do to make it work.
First of all let me give you and introduction on request/callback services, the SOA in practice website glossary states that request/callback services is “A message exchange pattern where a service consumer sends a request message but does not block and wait for a reply. Instead, it defines a callback function that is called later, when the response message sent by the service provider arrives.”. And that is exactly what whe are going to do, so let us open our JDevelopers and create a new application, mine is called vrsAsyncApp and it is a SOA Application.
Now create a project inside it, mine is called vrsAsyncProject and make sure you create an empty composite in it.
Create a Asynchronous BPEL process as make sure expose as webservice option is selected, just like you see on my wizard:
So for testing sake all I will do to this process is add an assign, that simply copies the input string to the output string and add a wait of 30 seconds, so we can see the process under execution without blocking the customers’ endpoint, it should look like the image below, once you have it, deploy it to your SOA environment.
Allright if you already deployed it, go to the test screen on your enterprise manager and copy the wsdl to your browser so you can see it similar to this:
<?xml version=”1.0″ encoding=”utf-16″?> <wsdl:definitions name=”asyncProcessService” targetNamespace=”http://xmlns.oracle.com/vrsAsyncApp/vrsAsyncProject/asyncProcessService” xmlns:plnk=”http://docs.oasis-open.org/wsbpel/2.0/plnktype” xmlns:client=”http://xmlns.oracle.com/vrsAsyncApp/vrsAsyncProject/asyncProcessService” xmlns:wsdl=”http://schemas.xmlsoap.org/wsdl/” xmlns:soap=”http://schemas.xmlsoap.org/wsdl/soap/”> <wsdl:documentation> <abstractWSDL>http://localhost:8001/soa-infra/services/async/vrsAsyncProject!1.0/asyncProcessService.wsdl</abstractWSDL> </wsdl:documentation> <plnk:partnerLinkType name=”asyncProcessService”> <plnk:role name=”asyncProcessServiceProvider” portType=”client:asyncProcessService” /> <plnk:role name=”asyncProcessServiceRequester” portType=”client:asyncProcessServiceCallback” /> </plnk:partnerLinkType> <wsp:Policy wsu:Id=”wsaddr_policy” xmlns:wsu=”http://docs.oasis-open.org/wss/2004/01/oasis -200401-wss-wssecurity-utility-1.0.xsd” xmlns:wsp=”http://schemas.xmlsoap.org/ws/2004/09/policy”> <wsaw:UsingAddressing xmlns:wsaw=”http://www.w3.org/2006/05/addressing/wsdl” /> </wsp:Policy> <wsdl:types> <schema xmlns=”http://www.w3.org/2001/XMLSchema”> <import namespace=”http://xmlns.oracle.com/vrsAsyncApp/vrsAsyncProject/asyncProcessService” schemaLocation=”http://localhost:8001/soa-infra/services/async/vrsAsyncProject/asyncprocessservice_client_ep?XSD=xsd/asyncProcessService.xsd” /> </schema> </wsdl:types> <wsdl:message name=”asyncProcessServiceResponseMessage”> <wsdl:part name=”payload” element=”client:processResponse” /> </wsdl:message> <wsdl:message name=”asyncProcessServiceRequestMessage”> <wsdl:part name=”payload” element=”client:process” /> </wsdl:message> <wsdl:portType name=”asyncProcessServiceCallback”> <wsdl:operation name=”processResponse”> <wsdl:input message=”client:asyncProcessServiceResponseMessage” /> </wsdl:operation> </wsdl:portType> <wsdl:portType name=”asyncProcessService”> <wsdl:operation name=”process”> <wsdl:input message=”client:asyncProcessServiceRequestMessage” /> </wsdl:operation> </wsdl:portType> <wsdl:binding name=”asyncProcessServiceBinding” type=”client:asyncProcessService”> <soap:binding transport=”http://schemas.xmlsoap.org/soap/http” /> <wsp:PolicyReference URI=”#wsaddr_policy” wsdl:required=”false” xmlns:wsp=”http://schemas.xmlsoap.org/ws/2004/09/policy” /> <wsdl:operation name=”process”> <soap:operation style=”document” soapAction=”process” /> <wsdl:input> <soap:body use=”literal” /> </wsdl:input> </wsdl:operation> </wsdl:binding> <wsdl:binding name=”asyncProcessServiceCallbackBinding” type=”client:asyncProcessServiceCallback”> <soap:binding transport=”http://schemas.xmlsoap.org/soap/http” /> <wsdl:operation name=”processResponse”> <soap:operation style=”document” soapAction=”processResponse” /> <wsdl:input> <soap:body use=”literal” namespace=”http://xmlns.oracle.com/vrsAsyncApp/vrsAsyncProject/asyncProcessService” /> </wsdl:input> </wsdl:operation> </wsdl:binding> <wsdl:service name=”asyncprocessservice_client_ep”> <wsdl:port name=”asyncProcessService_pt” binding=”client:asyncProcessServiceBinding”> <soap:address location=”http://localhost:8001/soa-infra/services/async/vrsAsyncProject/asyncprocessservice_client_ep” /> </wsdl:port> </wsdl:service> </wsdl:definitions>
The whole magic here is on the header. I added jus the basic header configuration here so callback works, you can do a lot further reading on this, but this one will do just fine for us, so let us understand it:
First property you will notice is the RelatesTo, this is and ID so your callback service will know what process the request is responding to, you should make it meaningful to your project, the BPEL service you return this to you.
Next is the ReplyTo.Address, this is where your call back service, here our OSB proxy endpoint is published at, so it knows whre to reply to.
Last is the Action, which is simply the operation you implemented as callback.
Now when you test it, remember we put a 30 seconds delay on our process so you can experience the client being released for processing while the BPEL process solves the problem.
All the source code can be accessed here.
Thank you for reading!