On Apr 24, 2009, at 11:42 AM, James Allchin wrote:
> OK - I suspect it is something to do with a VOID method instead of  
> returning a type...
>
Doh! oh yes. Please ignore my email i sent about logging an issue.
@GET methods are expected to return something. It is sort of an  
"artificial" restriction to encourage best practices. I think another  
work around is to return Response.ok().build() if you want to keep  
using HttpServletResponse.
Paul.
> How do I overcome this if I wish to serve via HttpServletResponse?
>
>
> On Fri, Apr 24, 2009 at 10:09 AM, James Allchin <james_at_knowledgemill.com 
> > wrote:
> Hi All,
>
> Thanks to everyone who keeps answering my questions on the forum.  
> The support is excellent.
>
> My current question is how to serve binary content i.e. a file out  
> through my RESTful services.
>
> I have managed to accept a file through my REST implementation with  
> the following method (it uses apache.commons upload) which is a nice  
> combo in my view (particularly streaming capabilities).
>
>     @POST
>     @Path("user/{userId}/artifacts/{artifactId}/content")
>     @Consumes("multipart/form-data")
>     //_at_Consumes("multipart/mixed")
>     public void setArtifactBinaryContent(@PathParam("userId") long  
> userId
>                                        , @PathParam("artifactId")  
> long artifactId
>                                        , @javax.ws.rs.core.Context  
> HttpServletRequest request)
>        throws Exception {
>             // First write the file to disk
>             FileItemFactory factory = new DiskFileItemFactory();
>             ServletFileUpload upload = new ServletFileUpload(factory);
>             List items = null;
>             try {
>                 items = upload.parseRequest(request);
>                 Iterator iter = items.iterator();
>                 while (iter.hasNext()) {
>                     FileItem item = (FileItem)iter.next();
>                     if (!item.isFormField()) {
>                         File fileLocator = new File("/fileshare/ 
> filedata/" + artifactId + ".dat");
>                         item.write(fileLocator);
>                     }
>                 }
>                 // Assuming success we now update the link and set  
> to enabled
>                 dA.updateArtifactLink(0, userId, artifactId, "/ 
> fileshare/filedata/" + artifactId + ".dat");
>                 dA.updateArtifactEnabled(0, userId, artifactId, true);
>             }
>             catch (Exception e) {
>                 e.printStackTrace();
>             }
>
>     }
>
> This works a treat... The problem I am having is now serving the  
> file. I am trying the following:
>
>     @GET
>     @Path("user/{userId}/artifacts/{artifactId}/content")
>     @Produces("application/octet-stream")
>     public void getArtifactBinaryContent(@PathParam("userId") long  
> userId
>                                        , @PathParam("artifactId")  
> long artifactId
>                                        , @javax.ws.rs.core.Context  
> HttpServletResponse response)
>        throws Exception {
>             try {
>                 // Get an internal representation of an artifact
>                 InternalArtifact ia = dA.getInternalArtifact(0,  
> userId, artifactId);
>
>                 // Get the file from disk
>                 File                f        = new File(ia.getLink());
>                 int                 fLength   = (int)f.length();
>
>                 // Set the response header header
>                 response.setContentType("application/octet-stream");
>                 response.setContentLength(fLength);
>                 response.setHeader( "Content-Disposition",  
> "attachment; filename=\"" + artifactId + "\"" );
>                 ServletOutputStream sos      =  
> response.getOutputStream();
>
>                 // Output the file stream
>                 byte[] bbuf = new byte[100];
>                 DataInputStream in = new DataInputStream(new  
> FileInputStream(f));
>                 int length = 0;
>                 while ((in != null) && ((length = in.read(bbuf)) !=  
> -1))
>                 {
>                     sos.write(bbuf,0,length);
>                 }
>                 in.close();
>                 sos.flush();
>                 sos.close();
>             }
>             catch (Exception e) {
>                 e.printStackTrace();
>             }
>     }
>
> When deploying it moans with the following error:
>
> SEVERE: Servlet /ACMERest threw load() exception
> com.sun.jersey.api.container.ContainerException: Method, public void  
> com 
> .acme 
> .rest 
> .MainService 
> .getArtifactBinaryContent 
> (long,long,javax.servlet.http.HttpServletResponse) throws  
> java.lang.Exception, annotated with GET of resource, class  
> com.acme.rest.MainService, is not recognized as valid Java method  
> annotated with @HttpMethod.
>
> Does anyone know what the issue is here. Is it incorrect to be using  
> @Context to access the HttpServletResponse object?
>
> Is there another way to serve a file perhaps?
>
> Thanks,
>
> James
>
>
>