Menu

#12 CsvBeanReader fails with NullPointerException

2.0.0-beta-1
closed
None
5
2012-09-16
2008-10-31
No

Hello,

version 1.52 of SuperCSV exhibits a very similar error to the one described in bug number 2093734. When using an Optional cellprocessor with for example a ParseDate cellprocessor, CsvBeanReader will throw a NullPointerException during the execution of fillObject(...).

The error is in line 72, that reads:
cache.getSetMethod(resultBean, nameMapping[i], lineResult.get(i).getClass())//
.invoke(resultBean, lineResult.get(i));

lineResult.get(i) will be null if Optional found an empty string. The CsvBeanReader should not invoke a setter if the value to be set is null. Following code will fix that:

if (lineResult.get(i) != null) {
cache.getSetMethod(resultBean, nameMapping[i], lineResult.get(i).getClass())//
.invoke(resultBean, lineResult.get(i));
}

Thank you very much for putting so much effort into SuperCSV.

Cheers,

Nico

Discussion

  • Kasper B. Graversen

    Hi Nico

    thanks for the report. I'm looking at it now. I'm not 100% convinced about your solution, as it will prevent e.g. the "Optional" or the "ConvertNullTo" processors from ever executing on nulls... maybe those two processors should implement some empty interface that denotes the processor should be invoked even on empty input. this makes the cellprocessor architecture a bit more complicated, but i don't see it as a big deal. Then instead of checking if the input is != null, it must also check the first processor as it may be able to handle the null input and return something the setter method can set..e.g. a default date in your example.

    What do you (and others) think of such a solution?

    many thanks
    kasper

     
  • Nico Fritschi

    Nico Fritschi - 2008-10-31

    Hi Kasper,

    you are right. My initial fix is too narrowminded, because it will only resolve my problem at hand but break other things. I'm not too familiar with the SuperCSV architecture, but what you are saying seems to make sense. I don't know if your solution with an empty interface will result in a good solution, since I haven't looked at the SuperCSV code except the CsvBeanReader.

    Greetings,

    Nico

     
  • Bogdan Gusiev

    Bogdan Gusiev - 2008-12-01

    Try this one:
    cache.getSetMethod(resultBean, nameMapping[i],
    lineResult.get(i) == null ? null : lineResult.get(i).getClass())//
    .invoke(resultBean, lineResult.get(i));
    Fix ASAP.

     
  • Markus S

    Markus S - 2009-02-09

    I stumbled upon the same problem in the same (latest) version, when parsing empty CSV columns.
    My fix in method fillObject() below:

    Object lineVal = lineResult.get(i);
    Class<?> lineClazz = lineVal != null ? lineVal.getClass() : null;

     
  • James Bassett

    James Bassett - 2010-04-30

    I realize there hasn't been any discussion on this for 2 years - but it's still an issue.

    To fix this, I just modified CsvBeanReader class' fillObject method to ignore lineResults that are null (all the other solutions provided execute unnecessary lines of code, i.e. calling the methodCache).

    // don't call a set-method in the bean if there is no mapping or result to store
     if (nameMapping[i] == null || lineResult.get(i) == null) {
        continue;
     }
    

    The current comment regarding 'no result to store' is misleading, it should read 'no mapping'. 'No result to store' is actually when the lineResult is null (the last executing processor returned null).

    Kasper, I think you're making things complicated! This has no impact on the CellProcessors at all. The 'Optional' and 'ConvertNullTo' processors (and every other processor) execute before the fillObject method does. It just means that if the end result of the processor chain is null, then the setter for that column value will not be executed so the field will keep its default value (null for objects, primitive defaults for primitives).

     
  • Mike Colagrosso

    Mike Colagrosso - 2011-02-01

    This bug still exists, and it's a very easy fix. In one line:

    • if( nameMapping[i] == null ) {
    • if( nameMapping[i] == null || lineResult.get(i) == null) {

    Here's a link to the fix in patch format:

    https://gist.github.com/806933

    jamesbassett's assessment from 10 months ago is correct. Please commit the change.

     
  • Anonymous

    Anonymous - 2011-08-10

    The author already applied the bugfix to his svn. There you can create a SuperCSV 1.53

    1. Click in this sourceforge-page on "Code" > "SVN"
    2. Download the projekt via svn
    3. In the downloaded files you will find the the folder "trunk" the ant-script "build.xml"
    4. Run "distro" from the ant-script
    5. Afterwards it says "Building zip: E:.....\trunk\distro\SuperCSV-1.53-source.zip" Yeah! ;)
     

    Last edit: Anonymous 2014-09-08
  • James Bassett

    James Bassett - 2011-11-14

    This fix will be available in the upcoming release!

     

Log in to post a comment.