users@jersey.java.net

Re: [Jersey] Input and Output binary streams using JERSEY?

From: Tauren Mills <tauren_at_groovee.com>
Date: Mon, 16 Aug 2010 23:24:36 -0700

Tatu,

> Yes, and that's where registering typed handled (MessageBodyWriter)
> would make things easier.
> Otherwise you will have to manually handle mapping of requested type
> into appropriate converter, which can add lots of code for larger
> systems.

If I create a MessageBodyWriter<ByteArrayOutputStream> with
@Produces("application/pdf"), then any Resource method that returns
ByteArrayOutputStream with the PDF mimetype will use the writer,
correct? Is this what you mean by "registering a converter"? It looks
like the entity-provider sample does this.

But what do I do if I don't want to return a ByteArrayOutputStream and
instead want to return a Response? For instance, getJSON() below
returns plain JSON with a Response object. I assume the method
getPDF() should use my custom MessageBodyWriter since it returns a
ByteArrayOutputStream. If I do something like the third method
getTest(), will that still use my custom MBW? And note that I want to
add some custom headers as well.

        @Inject
        private DataService dataService;

        @GET
        @Path("json/{id}")
        @Produces("application/json")
        public Response getJSON(@PathParam("id") String id) {
                // Get JSON representation of data
                ObjectNode data = dataService.getData(id);
                // Return JSON data
                return Response.ok().entity(data).build();
        }

        @GET
        @Path("pdf/{id}")
        @Produces("application/pdf")
        public ByteArrayOutputStream getPDF(@PathParam("id") String id) {
                // Return PDF representation of data
                return dataService.exportPdf(id):
       }

        @GET
        @Path("test/{id}")
        @Produces("application/pdf")
        public Response getTest(@PathParam("id") String id) {
                Date now = new Date();
                String name = "export-"+now.getTime()+".pdf";
                ByteArrayOutputStream pdf = dataService.exportPdf(id);
                return Response.ok().entity(pdf).header("Content-Disposition",
"attachment; filename="+name).build();
       }

So, still a bit confused as you can see... How do I combine getData
and getPDF into a single method? I don't want to return JSON with a
ByteArrayOutputStream. Note that I make different calls to my service
layer to get different types of data, so how do I know which one to
call in a single method? Is there a way to know in advance which
@Produces is going to be used?

Am I on the right track with something like this?

        @GET
        @Path("combined/{id}")
        @Produces("application/json","application/pdf")
        public Response getCombined(@PathParam("id") String id) {

                // how do I test for output type???
                if (testForOutputType.equals("application/pdf") {
                    Date now = new Date();
                    String name = "export-"+now.getTime()+".pdf";
                    ByteArrayOutputStream pdf = dataService.exportPdf(id);
                    return Response.ok().entity(pdf).header("Content-Disposition",
"attachment; filename="+name).build();
                }
                ObjectNode data = dataService.getData(id);
                return Response.ok().entity(data).build();
       }

Thanks again,
Tauren