Friday, October 17, 2008

Asynchronous Request Dispatching, Part 1

This is my first blog so I should say a little about myself before I get into things. My name is Maxim, or Max for short, and I’ve been working on the WebContainer since 2003 in various capacities. In Version 7 of WebSphere Application Server (WAS), I acted as the WebContainer architect and the Servlet Expert Group (EG) member representing IBM.

If you have been following the latest in Servlet technology, you would know that the expert group has finally decided to try to standardize asynchronous servlet support for Servlet 3.0. This came as somewhat of a surprise because I had already been working with my colleague Erinn Koonce on a related feature for WAS version 7 called the Asynchronous Request Dispatcher (ARD). Naturally, as options are discussed in the Servlet EG, I compare them to ARD and think about why you’d want to adopt one over the other.

ARD came about as a result of another feature we put in WAS Version 6.1 called the Remote Request Dispatcher (RRD). RRD was a requirement from WebSphere Portal to help them support Web Services for Remote Portlets (WSRP). The problem that WSRP tries to solve is that in some Portal environments one problem web module can bring down the entire application server and its applications. The natural response is to just add more resources to the deployment. However, this may be overkill for the web modules that are well behaved. Since many applications consist of multiple web modules that interact with one another through request dispatcher includes, each web module had to reside on the same server.

RRD provided the mechanism to separate up these applications into other servers or clusters without having to rewrite the interaction logic between web modules. However, there was a major drawback resulting from the cost of packaging and sending of the metadata across the network that each remote request dispatch required. To help alleviate this, Portal wanted a mechanism to execute these remote request dispatches asynchronously. Thus, ARD was born.

The Asynchronous Request Dispatcher does the following:

  • Allows request dispatch includes to execute asynchronously and concurrently
  • Maintains proper ordering of response output
  • Propagates request and thread context
  • Allows decoupling of the dispatching of the request with the position where the content should be inserted
  • Allows for client side aggregation of results

In my next blog, I will discuss the differences between the two proposals.

19 comments:

Sebastien said...

it is possible to have a little sample that show the Asynchronous Request Dispatcher in action ?

Andrew Spyker said...

@survivant

I deleted your other similar comment on another thread assuming that was a mistake. I'll see if I can get you an answer here.

Sebastien said...

thanks. Any example that use async API will be great. If you have something that suspend/resume a request using a servlet.. will be perfect. I try to find asynchronous doc for WAS, but on google there nothing.

Maxim Moldenhauer said...

This is a quick guide to get started with the IBM Asynchronous Request Dispatcher (ARD)

Configure the server to support ARD.

Go to Servers->Server Types->WebSphere Application Servers->yourServer->Web Container Settings->Web Container-> Asynchronous Request Dispatching.

Click check box for Allow Asynchronous Request Dispatcher.

Click OK and save.

Code up your asynchronous include:
((IBMServletContext)getServletContext().getContext("/YourContext")).getAsyncRequestDispatcher("/YourServlet").include(request,response);

You can also retrieve an include and insert it later in the page as such:
AsyncRequestDispatcher dispatcher1 = ((IBMServletContext)getServletContext().getContext("/YourContext")).getAsyncRequestDispatcher("/YourServlet");
FragmentResponse response1 = dispatcher1.getFragmentResponse(request,response);
...
response1.insertFragmentBlocking(request,response);


Install your ear as detailed below:

Select server side or client side under "Asynchronous Request Dispatch Type" in Step 1 of the app install panels

Server side will aggregate the includes in memory.

Client side will aggregate on client side using javascript.

I suggest using client side so you can verify its working more easily.

To verify, just hit your servlet and click on the page and view source and you should see the javascript added to retrieve the include.

You can contact me on linkedin for more information.

Maxim Moldenhauer said...

I'm going to post this quick start guide to my personal blog as well:
http://maximmoldenhauer.blogspot.com/

Sebastien said...

I'm trying to do a sample for ARD, but your sample doesn't compile.

((IBMServletContext)getServletContext()

should be
((IBMServletContext)request.getServletContext()

?

and I don't find the class IBMServletContext.


What I'm trying to do, is to replace my CountDownLatch for suspending a request.

my code works, but it lock a thread abd it's not want I'm looking for.
Can you send me a little sample that I can deploy and play it ? (The quotestreamer doesn't suspend a request :( )

thanks

Maxim Moldenhauer said...
This comment has been removed by the author.
Maxim Moldenhauer said...

It looks like you should add your WAS_HOME/dev/was_public.jar to your classpath and use com.ibm.websphere.servlet.context.ExtendedServletContext instead. That is the publicly available API. Or you can point to WAS_HOME/plugins/com.ibm.ws.webcontainer.jar, but was_public.jar is the recommended approach. The was_public.jar doesn't include the FragmentResponse class in case you were looking to use that. That is an oversight and should be fixed.

I think our example was using a servlet that extended GenericServlet which provides a convenience method to directly call getServletContext. However, your method will work as well.

Is it possible for you to upload your code somewhere so I can see what you are trying to do? It may be that using Async Servlets is a better fit than using the Async Request Dispatcher. However, Async Servlets are currently only available in the WebSphere V8 Alpha.

Sebastien said...

thanks for your time.

I'm working to add async support to Atmosphere for Websphere.

Atmosphere auto-deploy which container is used to trygin to instanciate Class proper to each container.

For my tests, I was trying to do it by creating a isntance of Publisher. and after that it will used to right container handler.

the auto-detect is done in this class : http://github.com/jfarcand/atmosphere/blob/master/modules/cpr/src/main/java/org/atmosphere/cpr/DefaultCometSupportResolver.java

After that I wanted to create a WebsphereCometHandler.

For now, because we don't have a proper Websphere handler, it will load the BlockingIOHandler.

http://github.com/jfarcand/atmosphere/tree/master/modules/cpr/src/main/java/org/atmosphere/container/

I used to webapp Flickr from atmosphere to test it.

http://github.com/jfarcand/atmosphere/tree/master/samples/flickr-comet/

this webapp when you launch the index.html it will make 2 connections. The first one, do a suspend, and the second resume the connection.

In the BlockingIOCometHandler, it will block the thread, and it's not what we want.

Sebastien said...

can you contact me by email at

sebastien.dionne at gmail. com


any help will be appreciated. The goal is to use the API from Websphere without changes to the sample (.war).

Maxim Moldenhauer said...

The Async Request Dispatcher doesn't support the comet paradigm. I will ping you via email to figure out if there is something else we can do.

Ajax Developer said...

I have a Comet application that runs on Weblogic.

It implements the AbstractAsyncServlet interface to delink the service the request. The AbstractAsyncServlet API lets me keep the client/server connection alive after the current request has completed. That way, I can stream future updates on this connection to my browser client.

Can I implement this functionality in ARD?

Ajax Developer said...

fyi, this is how my app is coded on Weblogic:

import weblogic.servlet.http.AbstractAsyncServlet;
import weblogic.servlet.http.RequestResponseKey;

public class AsyncServlet
extends AbstractAsyncServlet
{
public void init( ServletConfig oServletConfig )
throws ServletException
{
super.init( oServletConfig );

// never time out
setTimeout( -1 );
}
public boolean doRequest( RequestResponseKey oRequestResponseKey )
{
boolean bFutureResponse = false;
HttpServletRequest oRequest = oRequestResponseKey.getRequest();

....

/* keep connection alive */
return true;
}

}

Maxim Moldenhauer said...

Sorry, ARD is not designed to do what you are describing. What you are describing is more close to what is in Servlet 3.0's Async Servlet feature. You'll want to download the latest WAS V8 beta here. https://www14.software.ibm.com/iwm/web/cc/earlyprograms/websphere/wsasoa/download.shtml

Ajax Developer said...

Thanks for the quick feedback.

Unfortunately, I have to port my app on WAS 7.0.

What options do I have? I've heard that WAS 7.0 supports the "Bayeux protocol". Is this true?

Do you have specific code samples that I can install and play with that show how ARD or Bayeux protocolworks?

Maxim Moldenhauer said...

We've already had someone try something like this to no avail.

See:
http://atmosphere-users-mailling-list.2493822.n2.nabble.com/Atmosphere-Websphere-support-td4910078.html

Key point:
"
Unfortunately you can not do something like this with our comet support in the web 2.0 feature pack. (nothing exposed to plugin to). Not much new development going on with Comet in Web 2.0 FP - our team has gotten quite small - so servlet 3.0 will be next big thing Comet wise for websphere customers.
"

ARD does not allow for threadless suspending of the request. Which is I believe what you need to scale.

I can check around internally to see if there is anything else we can do.

Can you contact me at mmoldenh@yahoo.com with your private contact info?

Sebastien said...

It's my answer in the forum :)

With WAS 7. You can use Atmosphere, but it will be with BLocking IO. Depend on your volume, but could still works fine.

Ajax Developer said...

What is BlockingIOCometSupport and what is "atmosphere framework"?

My J2EE app already runs on Weblogic and now I'm porting it to WAS.

Assuming that I can live with blocked threads, how can I code my app using BlockingIOCometSupport?

Do you have some sample code and/or WAS docs you can share or point me to?

Maxim Moldenhauer said...

Atmosphere is not IBM product, but they ran into similar problems. I don't really know anything about Atmosphere. The point I was getting at by linking to that other page is that we don't have any official support for "keeping connection alive" after the completion of your doPost or doGet method.