[
https://issues.apache.org/jira/browse/CXF-4356?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Gonçalo Rodrigues updated CXF-4356:
-----------------------------------
Attachment: cxf-4356-reproducer.zip
I’ve attached a maven project that reproduces the described problem.
This project is composed of two web services:
* {{UploadService}} which has two operations ({{uploadFile}} and
{{uploadFileWsCall}}) that do the same thing, they read an incoming file stream
and return its size. The only difference between both operations is that the
second one calls the {{call}} operation of other web service ({{DummyService}})
before reading the stream.
* {{DummyService}} which does nothing, it was made to be called from the
{{uploadFileWsCall}} operation of {{UploadService}}.
The project has also two unit tests (integration tests in fact), to test both
operations of the {{UploadService}}. The test consist on sending 10,000 times
(1,000 times for the {{UploadFileAfterWsCallTest}}) the same file to the
{{UploadService}} operation and check that the returning size match the real
file size (130,700 bytes).
As we experienced, the {{UploadFileAfterWsCallTest}} fail after a few
iterations. The returning file size is 0 (as the {{DataHandler}} gives an empty
{{LoadingByteArrayOutputStream}} as {{InputStream}} implementation instead of
the overrided {{FileInputStream}} from {{CachedOutputStream}}).
The {{UploadFileTest}} doesn't fail often but when it fails, it has the same
symptoms as above.
This problem only occurs when MTOM is enabled.
To run the tests you only have to call "{{mvn clean test}}" – (make sure port
8080 is free as the tests start jetty on this port).
> Temp file deleted before returning the stream in CachedOutputStream
> -------------------------------------------------------------------
>
> Key: CXF-4356
> URL: https://issues.apache.org/jira/browse/CXF-4356
> Project: CXF
> Issue Type: Bug
> Affects Versions: 2.5, 2.6
> Reporter: Gonçalo Rodrigues
> Attachments: cxf-4356-reproducer.zip
>
>
> I’m implementing a web service to upload files (from 120 Kb to 1 Mb). Most of
> the time everything works fine, but sometimes (randomly) the uploaded file is
> empty (size == 0) in the target platform.
> After some debugging I found that the problem comes from the temp file
> created by the {{CachedOutputStream}} that is deleted during the process of
> getting the cached stream. In fact, {{maybeDeleteTempFile}} is called before
> {{getInputStream}} which returns an empty {{LoadingByteArrayOutputStream}}.
> The {{finalize}} method of {{FileInputStream}} calls its {{close}} method
> which is overridden in {{CachedOutputStream#getInputStream}} to delete the
> temp file.
> I tried to synchronize all the methods dealing with {{tempFile}} but it
> didn’t resolve my problem.
> The stack:
> {code}
> Daemon System Thread [Finalizer] (Suspended (breakpoint at line 490 in
> CachedOutputStream))
> CachedOutputStream.maybeDeleteTempFile(Object) line: 490
> CachedOutputStream.access$000(CachedOutputStream, Object) line: 43
> CachedOutputStream$1.close() line: 469
> CachedOutputStream$1(FileInputStream).finalize() line: 381
> Finalizer.invokeFinalizeMethod(Object) line: not available [native
> method]
> Finalizer.runFinalizer() line: 83
> Finalizer.access$100(Finalizer) line: 14
> Finalizer$FinalizerThread.run() line: 160
> {code}
> The {{getInputStream}} method:
> {code:java}
> public InputStream getInputStream() throws IOException {
> flush();
> if (inmem) {
> if (currentStream instanceof LoadingByteArrayOutputStream) {
> return ((LoadingByteArrayOutputStream)
> currentStream).createInputStream();
> } else if (currentStream instanceof ByteArrayOutputStream) {
> return new
> ByteArrayInputStream(((ByteArrayOutputStream) currentStream).toByteArray());
> } else if (currentStream instanceof PipedOutputStream) {
> return new PipedInputStream((PipedOutputStream)
> currentStream);
> } else {
> return null;
> }
> } else {
> try {
> FileInputStream fileInputStream = new
> FileInputStream(tempFile) {
> public void close() throws IOException {
> super.close();
> maybeDeleteTempFile(this);
> }
> };
> streamList.add(fileInputStream);
> return fileInputStream;
> } catch (FileNotFoundException e) {
> throw new IOException("Cached file was deleted, " +
> e.toString());
> }
> }
> }
> {code}
> The {{maybeDeleteTempFile}} method:
> {code:java}
> private void maybeDeleteTempFile(Object stream) {
> streamList.remove(stream);
> if (!inmem && tempFile != null && streamList.isEmpty() &&
> allowDeleteOfFile) {
> if (currentStream != null) {
> try {
> currentStream.close();
> postClose();
> } catch (Exception e) {
> //ignore
> }
> }
> tempFile.delete();
> tempFile = null;
> currentStream = new LoadingByteArrayOutputStream(1024);
> inmem = true;
> }
> }
> {code}
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators:
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira