[Fwd: Strange problem w/ RMI HTTP to CGI socket factory]

Peter Jones peter.jones at Sun.COM
Fri Oct 12 17:21:35 UTC 2007

On Fri, Oct 12, 2007 at 01:04:14PM +0100, Christopher Hegarty - Sun Microsystems Ireland wrote:
> Forwarding this mail to the core libs mailing list as they are most 
> probably in a better position to answer it as they own the sun.rmi package.
> -Chris.

Thanks for the forward, Chris:

> -------- Original Message --------
> Subject: Strange problem w/ RMI HTTP to CGI socket factory
> Date: Thu, 11 Oct 2007 15:57:48 -0400
> From: Sarel Botha <sarel at botha.us>
> To: net-dev at openjdk.java.net
> Hi All,
> This problem seems strange to me and I don't know where to look to
> resolve it.
> The RMIHttpToCGISocketFactory class is working well for me. I call
> RMISocketFactory.setSocketFactory(new RMIHttpToCGISocketFactory ()),
> then Naming.lookup() and all is well. However, I need to customize this
> class a little, so I got a copy of the source code for the package
> sun.rmi.transport.proxy, then renamed the package for these classes to
> sun.rmi.transport.proxy2 (also tried openjdk.sun.rmi.transport.proxy).
> If I try to use the same class in this package I get this error when it
> tries to establish the RMI connection:
> java.rmi.ConnectIOException: error during JRMP connection establishment;
> nested exception is:
>        java.io.IOException: attempt to write on HttpSendSocket after
> request has been sent
>        at
> sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:286)
> What's happening is that the underlying RMI code is calling
> HttpSendOutputStream.write() and passing only 7 bytes. This is
> immediately sent to the server which responds with only about 18 bytes.
> Then, it tries to call write() again, which should never happen, so it
> throws the exception you see above.
> When it works (using the socket factory that ships with JRE6) it first
> sends 58 bytes and the server responds with 217 bytes. You can also see
> the name of the RMI service in the request and the server response
> contains the name of the stub and the IP where the service is running.
> It seems like the underlying implementation is treating this socket
> factory totally differently from the one it ships with.
> Must the code be compiled with different switches maybe? Must the socket
> factory be registered somewhere? Any pointers would be appreciated.

First I should caution that the sun.rmi.transport.proxy package is a
relatively delicate old corner of the implementation (it has barely
been touched in 11 years)-- extending it is both somewhat risky and
not supported by public Java SE APIs (for better or for worse).

I suspect what your problem is:

The implementation of the HTTP tunnelling provided by this package is
presented (to the higher RMI/JRMP protocol implementation code) using
java.net.Socket as an abstraction for an HTTP request/response pair,
which is really not a very fitting abstraction, because with a Socket
one can normally assume a full-duplex connection.

The JRMP implementation code must understand what kind of "Socket" it
is using in order to know whether to use JRMP's StreamProtocol (for a
regular TCP connection or equivalent) or the SingleOpProtocol (for an
HTTP-tunnelled remote invocation).[1]  The implementation actually
makes this distinction based on whether the Socket is an instance of
the sun.rmi.transport.proxy.RMISocketInfo interface, and if it is,
what an invocation of its isReusable() method returns-- if it is an
instance of that interface and if isReusable returns false, HTTP
tunnelling is assumed and the SingleOpProtocol is used; otherwise, a
normal Socket is assumed and the StreamProtocol is used.

So, if you completely cloned the sun.rmi.transport.proxy package, then
your HttpSendSocket class presumably implements an incompatible
RMISocketInfo interface, and thus it will not be recognized as only
supporting request/response usage.  If you make the class implement
the original sun.rmi.transport.proxy.RMISocketInfo interface, that
should fix this problem, but all of the caveats of depending on sun.*
APIs would apply.[2]

Some previous discussion of a similar problem is here:

-- Peter

[1] These modes are described here:
[2] http://java.sun.com/products/jdk/faq/faq-sun-packages.html

More information about the core-libs-dev mailing list