Skip to main content

Resolving Excel Export I/O Stream Error/Fatal Error Issue

Problem:

    Fatal Application Error while exporting search results data into an excel sheet.

Root Cause for the Issue is:


  1. The Root Cause of the issue is Because of using the global (Instance) variables instead of using the method variables inside the class for writing the data to the excel file.

  1. In Struts 1.1/1.2 the Action class behaves like singleton. There will be only one instance of the action for all the incoming requests. So whenever we try to build our logic using the instance variables (The variables which we are defining at the top of the class outside the method area) instead of local variables (or method variables), we will face data inconsistency issues. If we are using this kind of variables for IO operations then we will be ending with Stream errors (like the one we faced in one of our application recently).


  1. In the case of our (XYZ) application, there was a call to flushRows(100) function on the global variable which variable was declared outside the method (at the beginning of the respective action class). So whenever two requests raised simultaneously, Out of two requests one request was taking less time to complete the job, during completion of this request the I/O stream was  closed after the call to flushRows() function or call to out.close(). So when another request starts processing on the same, that time it finds the I/O stream closed and it cannot proceed the request and was throwing "Stream Closed" exception. Because it was unable to read or write to the stream once it was closed. Since the same copy of instance variable has been used for both the request, one user request finds the modified variable by another request which is not correct behavior.
  

Solution:

       To avoid this problem there are three approaches which I proposed, out of three I felt the last one is the best approach:

  1. Moving all Excel export code to different function and using local variables to that function instead of global (instance) variables. Implementing this functionality in a separate method inside the action class. But this is not a good approach as action comes under view layer and excel export needs to be implemented in the business layer. And also here we are not separating the excel functionality to another class which is not a proper design. But as immediate fix we can go ahead with this approach if your implementation already in some action class and you don’t have much time.  

  1. Moving all excel related code to the different class and calling these methods from the current action class. Here the advantage is we are separating the excel related business logic from the action layer code. One good thing about this approach is that we are separating the Excel Export functionality code to different class, but the bad thing about this is, we are calling this class from action class i.e. from view layer which is not a correct design. This we can just keep as one immediate solution for our problem.


  1. The Best approach is to move all the Excel related functionalities to one utility class and call the respective method from Model Layer (Business layer, where business logic implemented). And avoid use of instance variables for Excel export implementation especially for multithreaded application. If at all using you have to take care of all the scenarios which is a very big headache. And also proper exception handling and proper cleaning of the I/O resources once after completing the job is very important to avoid errors.

Popular posts from this blog

Resolve OutOfMemoryError With ExcelExport : Export Excel Utility with Apache POI Stream API (SXSSF)

Whenever we try to export excel of huge data (for ex: around 200000-300000 records), most of the time we end up with OutOfMemoryError:JavaHeapSpace. And also consuming more time to process or export that much of data. Main reason to this kind of problem is that, the prior version of Apache POI (prior to 3.8) will not provide proper solution for this kind of situations and also we have other issues with the API designed with those versions. Even I had faced issues of not supporting more than 65000 rows of data during exporting excel with prior versions of POI. But with the version 3.8 and higher they come with solutions for all these problems. To resolve Memory issue and performance issue of Excel Export they have utilized stream API to design their API to support huge data export and performance issues. With stream API we can flush only few rows of data into the Memory and reamining we can flush to the hard memory (permanent Memory). In this example y…

Java Performance Checklist

Specify the required performance. Ensure performance objectives are clear.Specify target response times for as much of the system as possible.Specify all variations in benchmarks, including expected response ranges (e.g., 80% of responses for X must fall within 3 seconds).Include benchmarks for the full range of scaling expected (e.g., low to high numbers of users, data, files, file sizes, objects, etc.).Specify and use a benchmark suite based on real user behavior. This is particularly important for multi-user benchmarks.Agree on all target times with users, customers, managers, etc., before tuning.

Make your benchmarks long enough: over five seconds is a good target. Use elapsed time (wall-clock time) for the primary time measurements.Ensure the benchmark harness does not interfere with the performance of the application.Run benchmarks before starting tuning, and again after each tuning exercise.Take care that you are not measuring artificial situations, such as full caches contain…

Consider static factory methods instead of constructors

The normal way for a class to allow a client to obtain an instance of itself is to provide a public constructor. There is another technique that should be a part of every programmer’s toolkit. A class can provide a public static factory method, which is simply a static method that returns an instance of the class. Here’s a simple example from Boolean (the boxed primitive class for the primitive type boolean). This method translates a boolean primitive value into a Boolean object reference:

public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}

          Note that a static factory method is not the same as the Factory Method pattern from Design Patterns . The static factory method described in this item has no direct equivalent in Design Patterns. A class can provide its clients with static factory methods instead of, or in addition to, constructors. Providing a static factory method instead of a public constructor has both advantages and disadvant…