1

I'm trying to develop some rest services with Jersey to upload and download files (something like a file manager). If my services produce/consume only File class as "application/octet-stream", like in the code below, they work.

@GET
@Produces("application/octet-stream")
public File getFile(String id) {
    try {
        File file = new File(System.getProperty("user.home"), id);
        return file;
    } catch (FileNotFoundException ex) {
        Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

But if I try to transfer a custom object that contains a File field and some other data (FileEnvelope in the sample) I obtain an error.

@GET
@Produces("application/octet-stream")
public FileEnvelope getXml(String id) {
    try {
        File file = new File(System.getProperty("user.home"), id);
        FileEnvelope fileEnvelope = new FileEnvelope(file, "text");
        return fileEnvelope;
    } catch (FileNotFoundException ex) {
        Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

The error is

Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class com.mycompany.restdemo.FileEnvelope, and Java type class com.mycompany.restdemo.FileEnvelope, and MIME media type application/octet-stream was not found

Where I'm wrong? Is this the right way to manage this case? My client could not be a "Jersey client".

Dosty
  • 11
  • 1
  • 2
  • 1
    The problem here is that Jersey knows how to marshal standard types, e.g. `java.lang.File`. But as exception clearly states, you need to write and register in Jersay custom marshaller for `FileEnvelope`. See [A message body writer for Java type](http://stackoverflow.com/a/8187190/267197). – dma_k Mar 15 '12 at 22:51

2 Answers2

1

Jersey has no idea how to serialize your domain object into an octet-stream unless you tell it how. In this case if you want to include extra information beyond the file data you should consider how the client should be expected to read it. You could:

  1. Embed the information directly in the octet stream by creating your own MessageBodyWriter. The client would need to know where to look for this information in the resulting file.

  2. Include the information as part of the HTTP response header using ResponseBuilder. The client would just need to know which response headers to check for the information.

condit
  • 10,852
  • 2
  • 41
  • 60
  • Thanks for your answer. So I can't send my FileEnvelope object as xml for data and octetstream for File? – Dosty Mar 15 '12 at 09:34
  • You can - as @Martin suggests you can use a multipart response to achieve this. I think you'll need to include the jersey-multipart.jar (also in Maven central) to get this functionality... – condit Mar 15 '12 at 17:15
0

You can send different types of data in one message using multipart/* media types. For example this article shows how: http://aruld.info/handling-multiparts-in-restful-applications-using-jersey/

Martin Matula
  • 7,969
  • 1
  • 31
  • 35
  • Ok, I saw that tutorial...my doubt is if with this solution my services can be called from any kind of client (browser, java web app, mobile app....) – Dosty Mar 15 '12 at 22:13