Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning huge file from a remote EJB call

I have an EJB client that needs to retrieve a large file from an EJB server (JBoss).

The evident way to implement this is the server to offer a EJB facade with a method like this one:

public byte[] getFile(String fileName);

That means, loading the whole file in memory, in a byte array, and then sending this byte array on the wire.

The problem is that this approach loads the whole file in memory, and since the file is huge, it would overflow it.

Is there any option to overcome this problem?

like image 847
Mr.Eddart Avatar asked May 24 '12 08:05

Mr.Eddart


Video Answer


2 Answers

HTTP would be a better choice, but that said, try this serialization trick:

import java.io.*;

public class FileContent implements Serializable {

    private transient File file;

    public FileContent() {
    }

    public FileContent(File file) {
        this.file = file;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        // 1. write the file name
        out.writeUTF(file.getAbsolutePath());

        // 2. write the length
        out.writeLong(file.length());

        // 3. write the content
        final InputStream in = new BufferedInputStream(new FileInputStream(file));
        final byte[] buffer = new byte[1024];

        int length;
        while ((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length);
        }
        out.flush();
        in.close();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        // 1. read the file name
        final String path = in.readUTF();

        // 2. read the length
        long remaining = in.readLong();

        // 3. read the content
        file = new File(path);
        final OutputStream out = new BufferedOutputStream(new FileOutputStream(file));

        final byte[] buffer = new byte[1024];

        while (true) {
            int length = in.read(buffer, 0, (int) Math.min(remaining, buffer.length));
            if (length == -1) break;

            out.write(buffer, 0, length);

            remaining -= length;
            if (remaining <= 0) break;
        }
        out.flush();
        out.close();
    }
}
like image 183
David Blevins Avatar answered Nov 22 '22 09:11

David Blevins


The RMIIO library was built for exactly this situation. It even includes an implementation of @DavidBlevins solution, the DirectRemoteInputStream.

like image 44
jtahlborn Avatar answered Nov 22 '22 11:11

jtahlborn