user2869231
user2869231

Reputation: 1541

Give a Jersey response using a Stream of Supplier<InputStream> in Java

So I've got kind of an ugly situation right now. I have a class Revision that contains a method "getAllData". That method returns a Supplier of InputStream.

public class Revision {
    private String id;
    private Supplier<InputStream> allData;

    public Revision(String id, Supplier<InputStream> allData) {
        this.id = id;
        this.allData = allData;
    }

    public getAllData() {
        return allData;
    }
}

Let's say I have 2 revisions. They are declared like so:

Supplier<InputStream> revisionValue1 = () -> new ByteArrayInputStream(
            "{\"name\":\"George\", \"state\":\"Colorado\", \"Exp\":\"lots\"}".getBytes());
Revision revision1 = new Revision("Id1", revisionValue1);

Supplier<InputStream> revisionValue2 = () -> new ByteArrayInputStream(
            "{\"name\":\"Sean\", \"state\":\"New York\"}".getBytes());
Revision revision2 = new Revision("Id2", revisionValue2);

And they're put into a Map member:

Map<String, Revision> revisions = new HashMap<>();
revisions.put("Id1", revision1);
revisions.put("Id2", revision2);

A current method (which in itself is probably not very well written) returns a stream:

public Stream<Revision> getRevisions() {
    return revisions.values().stream();
}

Now in my Jersey code, I need to figure out how to return those values as a response in Json format. So the result should look something like:

[
{
    "name": "George",
    "state": "Colorado",
    "Exp": "lots"
},
{
    "name": "Sean",
    "state": "New York"
}
]

I'm trying to do this even as plain text, which isn't working. What I'm trying is:

@Produces(MediaType.TEXT_PLAIN)
public Response getRevisions(...) {

    Stream<Revision> revisionObjects = getRevisions();

    // each Revision option has a getAllData() method that needs called, which returns Supplier<InputStream>
    // each Supplier<InputStream> contains, essentially, a Json record

    // attempt at creating a StreamingOutput that can be sent as a response
    if (revisionObjects != null) {
        StreamingOutput stream = os -> {
            Writer writer = new OutputStreamWriter(os);
            Iterator<Revision> revisionIterator = revisionObjects.iterator();
            while (revisionIterator.hasNext()) {
                Revision next = revisionIterator.next();
                writer.write(next.getAllData().get().toString());
            }
            writer.flush();
        };
        return Response.ok(stream).build();
    }
    return Response.noContent().build();
}

This is returning results like:

[email protected]@ba0b09

Which I'm assuming is because there needs to be an extra step before the "toString()" method for the writer.

Sorry about how long this is, I just wanted to give the details. Does anyone know how to get this to work? Ideally, I'd like it to respond with JSON, but even plain text would be a huge amount of progress.

P.S. I'm still trying to wrap my head around InputStreams and OutputStreams, so chances are, I have something in there that is illogical.

Upvotes: 0

Views: 434

Answers (1)

Sanj
Sanj

Reputation: 4029

@Produces(MediaType.TEXT_PLAIN)
public Response getRevisions(...) {

    Stream<Revision> revisionObjects = getRevisions();

    // each Revision option has a getAllData() method that needs called, which returns Supplier<InputStream>
    // each Supplier<InputStream> contains, essentially, a Json record

    // attempt at creating a StreamingOutput that can be sent as a response
    if (revisionObjects != null) {
            Iterator<Revision> revisionIterator = revisionObjects.iterator();
            List<JSONObject> revisionsResponse = new ArrayList<JSONObject>();
            while (revisionIterator.hasNext()) {
                BufferedReader streamReader = new BufferedReader(new InputStreamReader(revisionIterator.next().getAllData().get(), "UTF-8")); 
                StringBuilder responseStrBuilder = new StringBuilder();

                String inputStr;
                while ((inputStr = streamReader.readLine()) != null)
                        responseStrBuilder.append(inputStr);
                revisionsResponse.add(new JSONObject(responseStrBuilder.toString());
            }

            return Response.ok(revisionsResponse).build();
    }
    return Response.noContent().build();
}

Upvotes: 1

Related Questions