users@glassfish.java.net

ACC improvement ideas

From: Florian Bruckner (3Kraft) <"Florian>
Date: Wed, 09 May 2007 16:00:18 +0200

Hello everybody,

as a result of discussions with Ken in another thread, I would like to
start a discussion about remote operations within the ACC.

Current situation
============
JEE application clients may suffer from the fact that the client/server
communication is opaque to them. When preparing a remote operation, the
client cannot influence how that operation is handled by the ORB and the
transport layer. When a remote operation has been called, the client has
no way to gather information about the state of the operation.

This can cause problems for clients that use remote operations from a
rich client application. In such applications giving the user feedback
about what is going on is essential. The application may, for example,
have to push BLOBs (like images) to the service layer. For this use
case, other than the fact that the operation has been handed to the ORB,
no further information is available to the client and therefore the
user. The operation also is not cancellable. The user might want to
cancel a large file upload (because he thinks that it is taking too
long), right now there is no way to achieve this.

Another issue with rich clients spread throughout the Internet is
transport reliability. Currently there is no clean way to detect a
network outage, leading to undeterminded behaviour and lack of feedback
to the user.

If have therefore written down these thoughts how to improve the current
situation by (hopefully) simple mechanisms.

What does it mean
============

Let me illustrate how rich java clients can work with a service layer.
Let us assume that we have a Swing GUI, and once a button has been
pressed, we want to upload lots of data to the server. This could look
like the following:

public uploadData(byte[] blobData)
{
     Future remoteOpFuture = AppController.getExecutorService().submit(
new Callable<ReturnValue>()
     {
          public ReturnValue call()
             throws Exception
          {
              return aServiceBean.upload(blobData);
          }
     }

    new JProgressDialog("Uploading data", remoteOpFuture).setVisible(true);

}

Lets us say, aServiceBean is a reference to a stateless session bean,
that has already been gathered earlier. Let us also assume that we have
some application scope controller that provides a reference to an
ExecutorService, where we can submit long running operations. Let us
also assume that we have a (modal) progress dialog, that takes a future
(besides a descriptive text). The progress dialog is shown
unconditionally and returns as soon as the Future has a value to return,
i.e. our remote operation is either finished or has failed.

Currently, the progress dialog can only show that the operation has been
submitted. There is no further information available about it. It cannot
even be cancelled here, because we do not have control over the remote
operation in any way. We could of course just forget about the future,
but this would lead to a possibly undefined behaviour, besides wasted
bandwidth.

 From a users point of view, what would I like to do do: Firstly, I
would like to get information about the state of my request. Then I
would like to be able to cancel the request. This leads to the following
things I may want to have as the programmer:


Configurability
===========

 From a programmers point of view: I would like to set increase timeout
values for this type of operation like the following:

  - The total time the operation may take (from method entry to method
exit) may be longer than usual, as we upload potentially huge data to
the server.
  - The time required for transmitting the operation may be longer than
usual, for the reasons given above.
  - Lets assume we do not do any processing on the server side, so we
expect the immediate begin of the response stream. Therefore we reduce
the time from the operation transmisstion until the first bits of the
answer drop in (i.e. limiting the processing time).
  - As we do not expect much data to come back, we reduce the time we
are willing to wait from the begin of the response transmission to the
end of the response transmission.
  - We are running on a sufficiently reliable link, therefore we want to
stop the processing if we do not get news from the transport layer for
15 seconds (i.e. no connection was established, no data was flowing out
or in when it was expected).

I may have, somewhere else in the application, a much more simple piece
of code that calls a fine grained remote operation. For this operation I
may want to have a completely different set of parameters:

  - The total time the operation may take is shorter than usual. Lets
assume we are on the AWT event dispatcher (I know, right now I
shouldn't), and if we do not get a response within 5 seconds, we are not
interested in the results, instead prefere a responsive UI.
  - For this case, we want to have a short transport timeout of 5
seconds as well.
  - Other configuration parameters may be like in the use case above.

Another use case - we have a small amount of input data, small amount of
output data, but expect some server side processing time. For this use
case I may want to have:
  - Short timeout for transmission to the server
  - A long timeout for the server to process the request (time from
finished operation request transmission to begin of response transmission)
  - A short timeout for transmissions from the server

I am sure, these use cases can be generalised and that most of the
parameters already exist in the Glassfish ORB. They are just not
documented and cannot be set for individual operations.


Monitorability
===========

To give the user an idead of what is happening, we need to get
information about the state of the operation. This could be
  - not yet started
  - transmitting request to server
  - transmission finished, server is (hopefully) processing
  - transmission of response to client
  - done

During transmissions, I would like to get an idea, where we are in the
transmission. In the beginning, or have we already transmitted 75% of
payload? I can imagine this could be tricky, because the size of the
request (in bytes) is most likely only known when the transmission is
finished. But maybe there is a way to get SOME indication. It may be
that we get a figure of the total number of parameters, which parameter
is currently transmitted and how many bytes already have been
transmitted for this parameter. In our first use case, I would know the
number of bytes to be transmitted to the server and could therefore
display a correct progress bar.

Cancellable
===========
This one should be easy: As long as the operation has not been fully
transmitted, the operation should easily be cancellable. Even if the
server is currently processing the response, we could choose to ignore
the result and rollback. In any case, if I instruct the operation to
stop (over whatever mechanism, if it is multithreaded the most feasible
mechanism could be thread interruption)

How could this be done
===========
In this case, I only can share my thoughts from the programmers point of
view. I do not have any insight in the ORB to even get an idea what this
would mean from that point of view.

Remember the simplified use case we have setup earlier. We encapsulate
our call into a Callable and submit it to an ExecutorService. I think
this method would be suitable to monitor the request state and/or also
control it. We could submit Callable objects to an extended
ExecutorService. ExecutorService returns a Future for each Callable, and
this already provides mechanisms for cancelling a request. The Future
would need to be extended to return the state of the request. The
Callable could be extended to set additional parameters for the ORB
(like transport timeouts, etc.).

Finally, something comletely different: Server NAT
===========
Another problem with clients rolled out to the Internet are firewalls.
It is common practise to put application servers behind some firewall or
even a load balancer, and usually this implies network address
translation (at least while IPv4 is used). In addition, the server might
also have internal clients, which use the internal, private IP-address
or server name. Because the ORB transmits the server name for remote
objects, this can only be done with headache (by using a server name,
that resolves to different IP addresses internally and externally) and
it is not possible to work around some use cases.

It should be considered to add functionaliy to the ORB to make NAT
scenarios possible. This could, for example, be done with an ORB
property that translates the remote object address received from the
server to a local address (e.g. the server transmits 192.168.1.10 for
the remote object, and in the client this is translated to
glassfish.example.com).


As I already said, this is written purely from a users point of view and
does not take into consideration what this might mean for the
implementation. It is thought as a starting point for a discussion how
to improve Glassfish features in this area.

best regards,

Florian

-- 
3Kraft Software | Applications | Development
Wasagasse 26/2
1090 Vienna
Austria
Phone: +43 (0)1 920 45 49
Fax: +43 (0)1 920 45 49
Mobile: +43 (699) 102 53 901
E-Mail: florian.bruckner_at_3kraft.com
Web: http://www.3kraft.com