4

i'm trying to write a WebApplication which views some DICOM files. My idea was to convert the DICOM files to JPEG on the fly by calling my servlet. I use dcm4che 2.0.27 to convert the files.

The servlet is called like

<img src="pathToServlet/PathToDICOMFile">.

The Problem: When i have many tags (of course addressing different DICOM files) sometimes i get an exception of type java.util.ConcurrentModificationException

Here is the method, my servlet is calling:

void convertFile(String path, OutputStream to) throws IOException {
    File myDicomFile = new File(path);

    BufferedImage myJpegImage = null;
    ImageIO.scanForPlugins();
    Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName("DICOM");

    ImageReader reader = (ImageReader) iter.next();

    DicomImageReadParam param = (DicomImageReadParam) reader.getDefaultReadParam();

    ImageInputStream iis = ImageIO.createImageInputStream(myDicomFile);
    reader.setInput(iis, false);
    myJpegImage = reader.read(0, param);
    iis.close();
    ImageIO.write(myJpegImage, "JPEG", to);

    to.close();

}

"path" is the absolute path to the dicom file and "out" is just response.getOutputStream().

The exception can be thrown at 3 places:

  1. ImageIO.getImageReadersByFormatName("DICOM");
  2. myJpegImage = reader.read(0, param);
  3. ImageIO.write(myJpegImage, "JPEG", to);

Here is a stack trace where it was thrown when calling ImageIO.getImageReadersByFormatName("DICOM"):

java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
at java.util.HashMap$ValueIterator.next(HashMap.java:835)
at javax.imageio.spi.PartialOrderIterator.<init>(PartiallyOrderedSet.java:177)
at javax.imageio.spi.PartiallyOrderedSet.iterator(PartiallyOrderedSet.java:85)
at javax.imageio.spi.SubRegistry.getServiceProviders(ServiceRegistry.java:759)
at javax.imageio.spi.ServiceRegistry.getServiceProviders(ServiceRegistry.java:451)
at javax.imageio.spi.ServiceRegistry.getServiceProviders(ServiceRegistry.java:507)
at javax.imageio.ImageIO.getImageReadersByFormatName(ImageIO.java:708)
at example.project.dicomtest.myDicomConverter.ConvertHelper.convertFile(ConvertHelper.java:32)
at example.project.dicomtest.myDicomConverter.GetImage.doGet(GetImage.java:40)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:185)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:151)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEnginateValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:269)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)

Is it because ImageIO is not thread safe? What can i do to solve this issue? Thank you very much for any help and best regards!

mesx
  • 1,035
  • 2
  • 12
  • 26

2 Answers2

6

These two lines:

ImageIO.scanForPlugins();
Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName("DICOM");

Only need to be done once, when your application loads or your servlet is initialized. In particular, the first line ImageIO.scanForPlugins() does mutate shared data used by the ImageIO class internally. This is likely the cause of your concurrent modification exceptions. Consider moving those two lines to either a servlet filter, or to the init(ServletConfig) method of your servlet.

Perception
  • 79,279
  • 19
  • 185
  • 195
1

use synchronized methods to prevent concurrent modification can be of help. read this question

stackoverflow.com/questions/9884148/use-of-synchronized-method-in-affable-bean-shopping-cart

qualebs
  • 1,291
  • 2
  • 17
  • 34