AlikElzin-kilaka
AlikElzin-kilaka

Reputation: 36001

Restlet client-server streaming using interfaces

I'd like to do something similar to the example posted in restlet's site (first applicaiton) - with one difference:

I want to stream data - not use primitive types - using an interface.

I want to define some kind of an interface between the client and the server, stream data between them and let restlet handle transmit the data seamlessly.

Example of what I have in mind:

interface Streaming {
  InputStream startStream(String streamId);
}

When the client invokes a call, it starts reading from the inputstream. The server receives the call and starts providing the stream by creating an inputstream (for example, a video file, or just some raw data). Restlet should be reading from the inputstream on the server side and provide the data as an inputstream on the client side.

Any idea how can I achieve this? A code sample or link to one would be great. Thanks.

Upvotes: 1

Views: 915

Answers (2)

AlikElzin-kilaka
AlikElzin-kilaka

Reputation: 36001

Below's an example code of what I learned so far - an interface with streaming capavilities and a client-server streaming example.

I haven't yet added parameters to the interface and it's only download - no upload yet.

Interface:

public interface DownloadResource {
    public ReadableRepresentation download();
}

Interface with protocol: (separation between logic and technology):

public interface DownloadResourceProtocol extends DownloadResource {
    @Get
    @Override
    public ReadableRepresentation download();
}

Client:

ClientResource cr = new ClientResource("http://10.0.2.2:8888/download/");
cr.setRequestEntityBuffering(true);
DownloadResource downloadResource = cr.wrap(DownloadResourceProtocol.class);
// Remote invocation - seamless:
Representation representation = downloadResource.download();
// Using data:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
IOUtils.copy(representation.getStream(), byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
Log.i("Byte array: " + Arrays.toString(byteArray));

Server:

public class DownloadResourceImpl extends ServerResource implements DownloadResourceProtocol {
    @Override
    public ReadableRepresentation download() {
        InputStreamChannel inputStreamChannel;
        try {
            inputStreamChannel = new InputStreamChannel(new ByteArrayInputStream(new byte[]{1,2,3,4,5,6,7,8,9,10}));
            return new ReadableRepresentation(inputStreamChannel, MediaType.ALL);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

Configuration:

public class SampleApplication extends Application {
    @Override
    public Restlet createInboundRoot() {
        Router router = new Router(getContext());
        router.attach("/download/", DownloadResourceImpl.class);
        return router;
    }
}

Upvotes: 1

tom
tom

Reputation: 2712

Not sure this addresses your problem completely, but one approach is to create a thread that streams data back to the client using ReadableRepresentation and a Pipe.

Create a pipe:

Pipe pipe = Pipe.open();

Create a representation like this:

ReadableRepresentation r = new ReadableRepresentation(pipe.source(), mediatype);

Start a separate thread that writes batches of bytes to the pipe like this:

pipe.sink().write(ByteBuffer.wrap(someBytes));

return the representation to the client.

Upvotes: 0

Related Questions