ServletContext#getResourceAsStream() returns null - servlets

Can anybody answer this?Don't know why i'm getting NullPointerException when trying to execute the below programme.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("image/jpeg");
ServletContext ctx = getServletContext();
InputStream is = ctx.getResourceAsStream("C:/Users/Public/Pictures/Sample Pictures/Desert.jpg"); --> The picture exists at this location
OutputStream os = response.getOutputStream();
int read = 0;
byte[] bytes = new byte[1024];
System.out.println("bytes :" + bytes);
while((read = is.read(bytes)) != -1) -- Error at this line
{
System.out.println("read :" +read);
os.write(bytes, 0, read);
}
os.flush();
os.close();
}
When running this in tomcat-Apache Getting the below error.
bytes :[B#158f9d3
Sep 19, 2013 7:23:04 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet Newest threw exception
java.lang.NullPointerException
at com.examples.Newest.doPost(Newest.java:69)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:873)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Thread.java:662)

This
InputStream is = ctx.getResourceAsStream("C:/Users/Public/Pictures/Sample Pictures/Desert.jpg"); --> The picture exists at this location
is not how you access a file on the file system. With that method call you are trying to get the resource from the context root. And, because you obviously don't have a resource called C:/Users/Public/Pictures/Sample Pictures/Desert.jpg relative to the context root, it returns null.
Use Java 7's NIO
Path path = Paths.get("C:/Users/Public/Pictures/Sample Pictures/Desert.jpg");
InputStream is = Files.newInputStream(path);

Related

InputStream closed unexpectedly while using Jersey MultiPart file upload & Server-Sent Events (SSE)

I'm using Jersey Multipart for uploading file to the server via Rest API. In the resource method, I accessed the file content via InputStream. I want to return the uploaded file size to the client with EventOutput using SSE so the client easily get the uploaded file size directly from upload resource method.
I'm using Jersey as JAX-RS implementation in java with Grizzly Http server. Here is my code:
#POST
#Path("upload")
#Produces(SseFeature.SERVER_SENT_EVENTS)
#Consumes("multipart/form-data;charset=utf-8")
public EventOutput upload(#FormDataParam("file") InputStream file,
#FormDataParam("file") FormDataContentDisposition fileDisposition) {
final EventOutput eventOutput = new EventOutput();
try {
new Thread(new Runnable() {
#Override
public void run() {
try {
int read = -1;
byte[] buffer = new byte[1024];
OutboundEvent.Builder eventBuilder
= new OutboundEvent.Builder();
OutboundEvent event = null;
long totalRead = 0, lastReadMB = 0;
while ((read = file.read(buffer)) != -1) {
totalRead += read;
if (lastReadMB != (totalRead / (1024 * 1024))) {
lastReadMB = totalRead / (1024 * 1024);
event = eventBuilder.name("uploaded").data(Long.class, totalRead).build();
eventOutput.write(event);
}
}
event = eventBuilder.name("uploaded").data(Long.class, totalRead).build();
eventOutput.write(event);
} catch (Exception e) {
throw new RuntimeException(
"Error when writing the event.", e);
} finally {
try {
eventOutput.close();
} catch (Exception ioClose) {
throw new RuntimeException(
"Error when closing the event output.", ioClose);
}
}
}
}).start();
return eventOutput;
} catch (Exception e) {
logger.error(e.toString(), e);
}
throw new WebApplicationException(Response.status(Response.Status.INTERNAL_SERVER_ERROR).
entity("something happened").build());
}
​
The problem is when my resource method return EventOutput as a response and request processing thread back to the I/O container, the InputStream closed and the processing thread can't access to the uploaded file. Here is the exception:
Exception in thread "Thread-1" java.lang.RuntimeException: Error when writing the event.
at com.WebService.ContentService$1.run(ContentService.java:192)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.jvnet.mimepull.MIMEParsingException: java.io.IOException: Stream Closed
at org.jvnet.mimepull.WeakDataFile.read(WeakDataFile.java:115)
at org.jvnet.mimepull.DataFile.read(DataFile.java:77)
at org.jvnet.mimepull.FileData.read(FileData.java:69)
at org.jvnet.mimepull.DataHead$ReadMultiStream.fetch(DataHead.java:265)
at org.jvnet.mimepull.DataHead$ReadMultiStream.read(DataHead.java:219)
at java.io.InputStream.read(InputStream.java:101)
at com.WebService.ContentService$1.run(ContentService.java:181)
... 1 more
Caused by: java.io.IOException: Stream Closed
at java.io.RandomAccessFile.seek0(Native Method)
at java.io.RandomAccessFile.seek(RandomAccessFile.java:557)
at org.jvnet.mimepull.WeakDataFile.read(WeakDataFile.java:112)
... 7 more
​
1- What's the problem in the code? Why InputStream is closed in the middle of the file transfer?
2- Is there any alternative way to return the uploaded file size to the client in server side? (REQUIREMENT: the upload resource method must handle upload file asynchronously in different thread)

Spring MVC file download controller returns garbled content

I'm trying to write a controller to return a file for download.
At first I was coding it this way:
#RequestMapping(value = RESTConstants.SLASH + "{id}" + RESTConstants.SLASH + RESTConstants.EXPORT, method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
#ResponseBody
public ResponseEntity<FileSystemResource> export(#PathVariable Long id, UriComponentsBuilder builder) throws IOException {
String filename = rolloutExportService.getDownloadFilename();
FileSystemResource fileSystemResource = rolloutExportService.export(id);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);
int read = 0;
byte[] bytes = new byte[1024];
OutputStream outputStream = null;
InputStream inputStream = null;
ResponseEntity<FileSystemResource> responseEntity = new ResponseEntity<FileSystemResource>(fileSystemResource, responseHeaders, HttpStatus.OK);
try {
responseHeaders.add(HttpHeaders.CONTENT_LENGTH, Long.toString(fileSystemResource.contentLength()));
outputStream = responseEntity.getBody().getOutputStream();
inputStream = fileSystemResource.getInputStream();
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} finally {
inputStream.close();
outputStream.flush();
outputStream.close();
}
return responseEntity;
}
But the response would be a 406 The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.
With the console log saying:
2014-11-05 01:18:39,403 DEBUG [DefaultHandlerExceptionResolver] Resolving exception from handler [public org.springframework.http.ResponseEntity<org.springframework.core.io.FileSystemResource> com.nsn.nitro.project.rest.controller.RolloutExportController.export(java.lang.Long,org.springframework.web.util.UriComponentsBuilder) throws java.io.IOException]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
2014-11-05 01:18:39,403 DEBUG [DispatcherServlet] Null ModelAndView returned to DispatcherServlet with name 'NITRo': assuming HandlerAdapter completed request handling
2014-11-05 01:18:39,403 DEBUG [DispatcherServlet] Successfully completed request
2014-11-05 01:18:39,405 DEBUG [ExceptionTranslationFilter] Chain processed normally
2014-11-05 01:18:39,405 DEBUG [SecurityContextPersistenceFilter] SecurityContextHolder now cleared, as request processing completed
And so I changed it not to return a response like:
#RequestMapping(value = RESTConstants.SLASH + "{id}" + RESTConstants.SLASH + RESTConstants.EXPORT, method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
#ResponseBody
public void export(#PathVariable Long id, HttpServletResponse response) throws IOException {
String filename = rolloutExportService.getDownloadFilename();
FileSystemResource fileSystemResource = rolloutExportService.export(id);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);
int read = 0;
byte[] bytes = new byte[1024];
OutputStream outputStream = null;
InputStream inputStream = null;
try {
responseHeaders.add(HttpHeaders.CONTENT_LENGTH, Long.toString(fileSystemResource.contentLength()));
outputStream = response.getOutputStream();
inputStream = fileSystemResource.getInputStream();
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
} finally {
inputStream.close();
outputStream.flush();
outputStream.close();
}
}
On both controllers, the request is the same, being typed in the Chromium browser:
http://localhost:8080/nitro-project-rest/rollouts/3/export
But the response would be garbled content displayed in the browser:
PK��îeE���������������/home/stephane/tmp/language.csv%É1
À ÐÝÃô™uìÐHˆßT‰±ØûC….oy2Èy€l
¨
V8EWc/Ïñܪµ÷>ú£¡.J‹]#uåtmáò×PKç}:H���O���PK��îeE���������������/home/stephane/tmp/country.csvKÎOIµÎKÌMµÎÉ,.ñ/JI-âJͳvÍKÏIÌK±6äJ+²v+JÌKN²PK*9»¶-���-���PK��îeE���������������/home/stephane/tmp/team.csvËKÌMµNI-N.Ê,(ÉÌϳN.JM1\KRK2sS¹BRs¬C2RJ
With the console saying:
20. select team0_.id as id1_15_0_, team0_.version as version2_15_0_, team0_.creation_datetime as
creation3_15_0_, team0_.description as descript4_15_0_, team0_.name as name5_15_0_ from team
team0_ where team0_.id=2
2014-11-05 01:31:29,983 DEBUG [JpaTransactionManager] Initiating transaction commit
2014-11-05 01:31:29,983 DEBUG [JpaTransactionManager] Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl#6569cc]
2014-11-05 01:31:29,988 DEBUG [JpaTransactionManager] Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl#6569cc] after transaction
2014-11-05 01:31:29,988 DEBUG [EntityManagerFactoryUtils] Closing JPA EntityManager
2014-11-05 01:31:30,013 DEBUG [DispatcherServlet] Null ModelAndView returned to DispatcherServlet with name 'NITRo': assuming HandlerAdapter completed request handling
2014-11-05 01:31:30,013 DEBUG [DispatcherServlet] Successfully completed request
2014-11-05 01:31:30,021 DEBUG [ExceptionTranslationFilter] Chain processed normally
2014-11-05 01:31:30,021 DEBUG [SecurityContextPersistenceFilter] SecurityContextHolder now cleared, as request processing completed
My last attempt was this one:
#RequestMapping(value = RESTConstants.SLASH + "{id}" + RESTConstants.SLASH + RESTConstants.EXPORT, method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
#ResponseBody
public FileSystemResource export(#PathVariable Long id) throws IOException {
String filename = rolloutExportService.getDownloadFilename();
FileSystemResource fileSystemResource = rolloutExportService.export(id);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);
responseHeaders.add(HttpHeaders.CONTENT_LENGTH, Long.toString(fileSystemResource.contentLength()));
responseHeaders.add(HttpHeaders.CONTENT_TYPE, "application/zip");
return fileSystemResource;
}
But it also gave me a 406 response.
From the last attempt above, I removed the attribute: produces =
MediaType.APPLICATION_OCTET_STREAM_VALUE
And the same request sent by the browser (seen in the console) looked like:
Request URL:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAuCAQAAAD9sOO8AAAASUlEQVR4Xu3SMQoAIAzFUO/o/c+iY4fSSfgQyesgOESHrs9I0j7TEOL9pk5i/OmB/s9IvAYQH6DjxmtTWPEWBcS52zJPIJ4lSRfUZeB1c/cgSwAAAABJRU5ErkJggg==
Request Headers CAUTION: Provisional headers are shown.
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/34.0.1847.116 Chrome/34.0.1847.116 Safari/537.36
With the server console log saying:
2014-11-05 12:08:35,938 DEBUG [ExceptionsHandler] org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.core.io.InputStreamResource["inputStream"]->java.io.FileInputStream["fd"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.core.io.InputStreamResource["inputStream"]->java.io.FileInputStream["fd"])
You need to set the correct MIME type of the file in your controller.
If your file is a pdf:
response.setContentType("application/pdf");
If your file is a gif image:
response.setContentType("image/gif");
If your file is a zip file:
response.setContentType("application/zip");
You may find the correct MIME type here.
you should set the content Type of the HttpResponse like the following :
response.setContentType("application/zip");
or set the ContentType using the HttpHeaders , and set the CONTENT_ENCODING to UTF-8 like the following :
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set(HttpHeaders.CONTENT_TYPE, "application/zip");
responseHeaders.add(HttpHeaders.CONTENT_ENCODING, "UTF-8");
so the browser will know what kind of files he is expecting, please refer to this tutorial here that explains the Http Headers .
Hope that Helps .
I could make it work with this controller:
#RequestMapping(value = RESTConstants.SLASH + "{id}" + RESTConstants.SLASH + RESTConstants.EXPORT, method = RequestMethod.GET)
public void doDownload(#PathVariable Long id, HttpServletRequest request, HttpServletResponse response) throws IOException {
String filename = rolloutExportService.export(id);
ServletContext context = request.getServletContext();
File downloadFile = new File(filename);
FileInputStream inputStream = new FileInputStream(downloadFile);
String mimeType = context.getMimeType(filename);
if (mimeType == null) {
mimeType = MediaType.APPLICATION_OCTET_STREAM.getType();
}
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
String headerValue = String.format("attachment; filename=\"%s\"", downloadFile.getName());
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, headerValue);
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inputStream.close();
outStream.close();
}
Sending the request
http://localhost:8080/nitro-project-rest/rollouts/3/expor
in the browser pops up a download window.
Remove
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
as will push out generic binary content. If you want the content sent from the filename extension then in your spring XML file put
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
and
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean" />

Using Open CSV to Send files from ServletOutputStream

I have parsed a JSON Object that was sent to my TOMCAT server using POST and turned it into a CSV file. I would like to send the CSV file back to the user. I am confused about how to send the file back because all the examples I have seen reference an actual file that is stored on the server - my file is built in memory and doesn't actually reference a file/file descriptor as far as I can tell.
//The doPost method has already generated the String[] - I then call generateCSV
protected void generateCSV(ArrayList<String[]> data, ServletOutputStream out,
HttpServletResponse response)
{
try{
BufferedWriter buff = new BufferedWriter(new OutputStreamWriter(out));
CSVWriter writer = new CSVWriter(buff);
writer.writeAll(data);
writer.close();
sendFile(response, out);
}catch(IOException | ServletException e){
e.printStackTrace();
}
}
protected void sendFile(HttpServletResponse response, ServletOutputStream outstream)throws ServletException, IOException
{
response.setContentType("application/octet-stream");
outstream.flush();
outstream.close();
}
What do you have to do to send a file to the user from a servlet?
Set the content-type.
Write out the bytes.
Seems to me you are doing this, but in the wrong order. Also, rather than using application/octet-stream you might want to actually tell the browser this is CSV. You might also want to give it a filename.
response.setContentType("text/csv");
response.setHeader("Content-Disposition","filename=whatever.csv");
BufferedWriter buff = new BufferedWriter(new OutputStreamWriter(out));
CSVWriter writer = new CSVWriter(buff);
writer.writeAll(data);
writer.close();

Can I force the browser to download the PDF file instead of opening it?

So this is the code I have:
public class PdfDownloaderServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws ServletException, IOException {
httpServletResponse.setContentType("application/pdf");
ServletContext servletContext = httpServletRequest.getServletContext();
InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/pdfs/x.pdf");
int read;
byte[] bytes = new byte[1024];
OutputStream os = httpServletResponse.getOutputStream();
while ((read = inputStream.read(bytes)) != -1) {
os.write(bytes, 0, read);
}
os.flush();
os.close();
}
}
and it works just fine.
However when I click the link that invokes this method, the browser will open the file, but I want the browser to directly download the file. How can I achieve this?
Thanks.
If you want the browser to download as attachment, you need to say so using the Content-Disposition header field. See http://greenbytes.de/tech/webdav/rfc6266.html#disposition.type, disposition type "attachment".

How to avoid java.io.IOException: Attempted read on closed stream

I'm trying to find a way to avoid the IOException related to the fact that I read on a closed stream.
I'm calling a webservice method that returns a Stream:
InputStream stream = callRestWebService();
try {
parkingState = objectMapper.readValue(stream, ParkingState.class);
} catch (IOException e) {
throw new ParkingMeasurementProviderException("Could not retrieve data.", e);
}
Then, I have my Web Service method where I close the get connection:
public InputStream callRestWebService() {
int parkingId = 2803;
String endpointURL = REST_ENDPOINT + URI_INFO_PATH + parkingId + "/parkingState";
InputStream inputStream = null;
// Create an instance of HttpClient.
HttpClient httpclient = new HttpClient();
// Create a method instance.
GetMethod getMethod = new GetMethod(endpointURL);
getMethod.addRequestHeader("accept", "application/json");
try {
// Execute the method.
int statusCode = httpclient.executeMethod(getMethod);
inputStream = getMethod.getResponseBodyAsStream();
} catch (IOException e) {
e.printStackTrace();
} finally {
// Release the connection.
getMethod.releaseConnection();
}
return inputStream;
}
Is there a way to avoid having this exception without removing the : getMethod.releaseConnection();
The stack trace:
Disconnected from the target VM, address: '127.0.0.1:62152', transport: 'socket'
at be.ixor.itg.server.service.parking.hermesWS.HermesWSParkingControllerMeasurementProvider.getHermesMechelenData(HermesWSParkingControllerMeasurementProvider.java:126)
at be.ixor.itg.server.service.parking.hermesWS.Main.main(Main.java:14)
Caused by: java.io.IOException: Attempted read on closed stream.
at org.apache.commons.httpclient.AutoCloseInputStream.isReadAllowed(AutoCloseInputStream.java:183)
at org.apache.commons.httpclient.AutoCloseInputStream.read(AutoCloseInputStream.java:86)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager$RewindableInputStream.read(XMLEntityManager.java:2977)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:702)
at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:186)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:772)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:232)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:284)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124)
at be.ixor.itg.server.service.parking.hermesWS.HermesWSParkingControllerMeasurementProvider.getHermesMechelenData(HermesWSParkingControllerMeasurementProvider.java:116)
... 1 more
Because you are calling releaseConnection() in your finally block, the input stream will no longer be available.
If you do not expect the content to be large, you could read the data from the input stream into a buffer and return the buffer instead of the input stream. Otherwise, you will need to change your code to allow the called to process the data from the input stream before releasing the connection.
BufferedReader br = new BufferedReader(new
InputStreamReader((response.getEntity().getContent())));
String response = br.readLine();
System.out.println("response" + response );
This code is working for me.

Resources