Some reader favorites:
EJB fundamentals and session beans
Create a scrollable virtual desktop in Swing
Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API
December 7, 2002
![]()
This week, I answer two questions concerning data compression in Java.
Question 1:
How can I zip something that isn't in a file?
Question 2:
I read with enthusiasm Todd Sundsted's "Zip Your Data and Improve the Performance of Your Network-Based Applications," (JavaWorld, November 1998) but I was a little disappointed.
When I read the title of the article, I was ecstatic. I thought I had finally found the solution for our problem.
At my company, we have been trying to improve the performance of an RMI (Remote Method Invocation) application that organizes data. The server does most of the process. We've made performance improvements in the past year and a half, but the bottleneck now is the data transfer. At any point in the day, we might be transferring thousands of records between the client and the server. As one possible solution, I proposed we compress the data before returning it to the client, a process I thought Todd's article would address. However, the example given in his article compresses files, not data, as we need.
On the RMI implementation, we get the results from the database, put them in a list, and return the list to the client, which in turn puts the results in a JTable. I would like to compress that list before sending it back to the client, decompress it at the client, then insert the data in the JTable.
Can this be done?
I've received several questions about Todd's article. Many readers seem confused because the article's examples were file
centric.
Note: You can download this article's source code from Resources.
In regards to question 1, nothing forces you to use files when you use ZipInputStream and ZipOutputStream. The only stipulation is that you convert your data to byte arrays.
Question 2, however, proves more involved because it requires a change in the way RMI communicates over the wire. In order to make RMI compress its data before sending it over the wire, you must create a new socket type that compresses the data. Then, once you have created the socket, you must tell RMI to use it.
"Creating a Custom RMI Socket Factory," a tutorial from Sun Microsystems, enumerates the steps necessary to create a new socket and get RMI to use it.
Briefly, to change RMI's socket type:
ServerSocket.
RMIClientSocketFactory.
RMIServerSocketFactory.
UnicastRemoteObject use the new factories.
Following the scenario outlined in question 2 above, let's go through each step for zip compression.
In the case of zip compression, create the following socket:
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import java.net.Socket;
public class ZipSocket extends Socket {
private InputStream in;
private OutputStream out;
public ZipSocket() { super(); }
public ZipSocket(String host, int port)
throws IOException {
super(host, port);
}
public InputStream getInputStream()
throws IOException {
if (in == null) {
in = new ZipInputStream(super.getInputStream());
}
return in;
}
public OutputStream getOutputStream()
throws IOException {
if (out == null) {
out = new ZipOutputStream(super.getOutputStream());
}
return out;
}
public synchronized void close() throws IOException {
OutputStream o = getOutputStream();
o.flush();
super.close();
}
}
Create the following server socket:
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
public class ZipServerSocket extends ServerSocket
{
public ZipServerSocket(int port) throws IOException {
super(port);
}
public Socket accept() throws IOException {
Socket socket = new ZipSocket();
implAccept(socket);
return socket;
}
}
The client factory will need to take the following form:
import java.io.IOException;
import java.io.Serializable;
import java.net.Socket;
import java.rmi.server.RMIClientSocketFactory;
public class ZipClientSocketFactory
implements RMIClientSocketFactory, Serializable {
public Socket createSocket(String host, int port)
throws IOException {
ZipSocket socket = new ZipSocket(host, port);
return socket;
}
}
Here's the server factory code:
import java.io.IOException;
import java.io.Serializable;
import java.net.ServerSocket;
import java.rmi.server.RMIServerSocketFactory;
public class ZipServerSocketFactory
implements RMIServerSocketFactory, Serializable {
public ServerSocket createServerSocket(int port)
throws IOException {
ZipServerSocket server = new ZipServerSocket(port);
return server;
}
}
Here's the code:
public class YourRMIObject extends UnicastRemoteObject {
public YourRemoteObject( int port ) {
super( port, new ZipClientSocketFactory(), new ZipServerSocketFactory() );
}
// the rest of your implementation
}
Now your communication will be compressed.
Free Download - 5 Minute Product Review. When slow equals Off: Manage the complexity of Web applications - Symphoniq
![]()
Free Download - 5 Minute Product Review. Realize the benefits of real user monitoring in less than an hour. - Symphoniq