rray
rray

Reputation: 480

OpenCSV not mapping JavaBeans with annotations

I am using version 3.8 of OpenCSV library. I am using annotation to map the bean fields to the columns in the CSV file. I have it working to a point. It is failing when a date field is blank.

java.lang.RuntimeException: Error parsing CSV line: 1 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

 **Caused by: com.opencsv.exceptions.CsvDataTypeMismatchException**
at com.opencsv.bean.BeanFieldDate.convertLocaleInspecific(BeanFieldDate.java:216)
at com.opencsv.bean.BeanFieldDate.convert(BeanFieldDate.java:242)
at com.opencsv.bean.AbstractBeanField.setFieldValue(AbstractBeanField.java:70)
at com.opencsv.bean.CsvToBean.processField(CsvToBean.java:245)
at com.opencsv.bean.CsvToBean.processLine(CsvToBean.java:220)
at com.opencsv.bean.CsvToBean.processLine(CsvToBean.java:189)
at com.opencsv.bean.CsvToBean.parse(CsvToBean.java:166)
... 26 more
**Caused by: org.apache.commons.beanutils.ConversionException: No value specified for 'Date'
at** org.apache.commons.beanutils.converters.AbstractConverter.handleMissing(AbstractConverter.java:327)
at org.apache.commons.beanutils.converters.DateTimeConverter.convertToType(DateTimeConverter.java:327)
at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:169)
at com.opencsv.bean.BeanFieldDate.convertLocaleInspecific(BeanFieldDate.java:214)
... 32 more

The annotation for the specific bean field as "required=false" but it still does not work. Here is the JavaBean annotation where I am using the Java.Util.Date class:

@CsvBindByName(column="Sent On", required=true)
@CsvDate(value="MM/dd/yyyy HH:mm:ss a z")
private Date sentOn;

@CsvBindByName(column="Last Activity", required=false)
@CsvDate(value="MM/dd/yyyy HH:mm:ss a z")
private Date lastActivity;

@CsvBindByName(column="Completed On", required=false)
@CsvDate(value="MM/dd/yyyy HH:mm:ss a z")
private Date completedOn; 

This is how I have created the CSV reader and parser:

    final char QUOTE_CHARACTER = '"';
    ClassLoader classLoader = getClass().getClassLoader();
    File newFile = new File(classLoader.getResource(fileName).getFile());
    CSVReader reader2 = null;

    FileReader fileReader2 = null;

    List<My_Data> myList = null;

     try {

        HeaderColumnNameMappingStrategy<My_Data> strat = new HeaderColumnNameMappingStrategy<My_Data>();
        strat.setType(My_Data.class);

        CsvToBean<My_Data> csv = new CsvToBean<>();

        final CSVParser csvParser = new CSVParserBuilder().withSeparator(delimiter)
                                                          .withQuoteChar(QUOTE_CHARACTER)
                                                          .withStrictQuotes(true)
                                                          .build();

        fileReader2 = new FileReader(newFile);

        reader2 = new CSVReaderBuilder(fileReader2).withCSVParser(csvParser)
                                                   .withVerifyReader(true)
                                                   .withKeepCarriageReturn(false)
                                                   .build();


         myList = csv.parse(strat, reader2);

Here is CSV file data:

"Subject","Status","Sender Name","Recipient","Sent On","Last Activity","Completed On","Completion Time (DD:HH:MM)","Created Date","Declined Date","Document ID","Reason for Declining","Expiration Date","Date Signed"
"MyCompany: Plan RCP Endorsements Select Bundle","Sent","ENV_PROD","SANDRA BULLOCK","7/21/2016 10:49:38 AM EST","7/21/2016 10:49:38 AM EST","","","7/21/2016 10:49:37 AM EST","","e05e53d8-e8bd-469e-a774-c0dec98481b2","","9/4/2016 10:49:38 AM EST",""

How I discovered this fault is walking through the source code. I am hoping others have face a similar issue and can give me a suggestion on how to get around this issue. I like this mapping approach as it saves me time and effort. The process is working by just reading the file into a List. The problem with this approach is I would have to write the factory process for the JavaBeans.

Suggestions are welcomed.

Thanks,

Russ

Upvotes: 2

Views: 9548

Answers (1)

Scott Conway
Scott Conway

Reputation: 983

We identified the issue you are seeing as an issue in the opencsv code. A contributor is in the process of rewriting the date handling code the 3.9 release so we will make sure that the code fixes your issue.

We have not set a date for the 3.9 release so if you need something immediately and you have or can build the code yourself go to the BeanFieldDate class and in the convert method and replace:

    if (required && StringUtils.isEmpty(value)) {
        throw new CsvRequiredFieldEmptyException();
    }

with something like

    if (required && StringUtils.isEmpty(value)) {
        if (required) {
            throw new CsvRequiredFieldEmptyException();
        } else {
            return null;   // or maybe empty string
        }
    }

and see if that would help.

Upvotes: 0

Related Questions