BeanIO InvalidRecordGroupException给出错误的行号

问题描述:

我使用BeanIO来解析固定宽度的文本文件。例如,文件进入我的项目看起来像下面的固定宽度文本:BeanIO InvalidRecordGroupException给出错误的行号

CD DummyValue3 
EF DummyValue4 DummyValue5 DummyValue6 
AB DummyValue1 DummyValue2 
... 

在我的映射文件,我已经公布各的recordId一个record(即AB,CD,EF)

<record name="dummyRecord" template="AB" 
class="com.company.project.DummyRecordClass" minOccurs="0" 
maxOccurs="1" /> 

我然后让每个记录的template

<template name="AB"> 
    <field name="recordID" length="3" rid="true" literal="AB" 
      lenientPadding="true" minOccurs="0" /> 
    <field name="value1" length="12" lenientPadding="true" 
      minOccurs="1" required="true"/> 
    <field name="value2" length="12" lenientPadding="true" 
      minOccurs="1" required="true"/> 
</template> 

因为value1value2minOccurs = 1作为以及required="true"(是的,我知道这是多余的,但它已经在代码中,我们有成千上万的这些字段),如果我有一个AB段,它们必须存在。

所以,如果我下面的文件传递到我的程序:

CD DummyValue3 
EF DummyValue4 DummyValue5 DummyValue6 
AB DummyValue1 

我收到以下InvalidRecordGroupException:

org.beanio.InvalidRecordGroupException: Invalid 'ediMessage' record group at line 1

然而,由于缺少字段实际上是在第3行,当你有500-600行数据进入应用程序时,这可能是一个完全痛苦的调试。

有没有什么办法让beanIO输出正确的行号,或即使必填字段缺少templatefield价值?

我通过扩展org.beanio.BeanReaderErrorHandlerSupport创建LoggingErrorHandler使用org.beanio.BeanReaderErrorHandler定制的实行。

import org.beanio.BeanReaderErrorHandlerSupport; 
import org.beanio.BeanReaderException; 
import org.beanio.InvalidRecordException; 
import org.beanio.MalformedRecordException; 
import org.beanio.RecordContext; 
import org.beanio.UnexpectedRecordException; 
import org.beanio.UnidentifiedRecordException; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

/** 
* A BeanIO {@code BeanReaderErrorHandler} that logs the error messages. 
* 
* @author Nico Schlebusch 
*/ 
public class LoggingBeanReaderErrorHandler extends BeanReaderErrorHandlerSupport { 

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingBeanReaderErrorHandler.class); 

    /** 
    * Creates a new instance of {@code LoggingBeanReaderErrorHandler}. 
    */ 
    public LoggingBeanReaderErrorHandler() { 
    } 

    /** 
    * {@inheritDoc} 
    * 
    * @see org.beanio.BeanReaderErrorHandlerSupport#invalidRecord(org.beanio.InvalidRecordException) 
    */ 
    @Override 
    public void invalidRecord(final InvalidRecordException ex) throws BeanReaderException { 

    LOGGER.error("{}", createErrorMessage(ex)); 
    } 

    /** 
    * {@inheritDoc} 
    * 
    * @see org.beanio.BeanReaderErrorHandlerSupport#unexpectedRecord(org.beanio.UnexpectedRecordException) 
    */ 
    @Override 
    public void unexpectedRecord(final UnexpectedRecordException ex) throws BeanReaderException { 

    LOGGER.error("{}", createErrorMessage(ex)); 
    } 

    /** 
    * {@inheritDoc} 
    * 
    * @see org.beanio.BeanReaderErrorHandlerSupport#unidentifiedRecord(org.beanio.UnidentifiedRecordException) 
    */ 
    @Override 
    public void unidentifiedRecord(final UnidentifiedRecordException ex) throws BeanReaderException { 

    LOGGER.error("{}", createErrorMessage(ex)); 
    } 

    /** 
    * {@inheritDoc} 
    * 
    * @see org.beanio.BeanReaderErrorHandlerSupport#malformedRecord(org.beanio.MalformedRecordException) 
    */ 
    @Override 
    public void malformedRecord(final MalformedRecordException ex) throws BeanReaderException { 

    LOGGER.error("{}", createErrorMessage(ex)); 
    } 

    /** 
    * {@inheritDoc} 
    * 
    * @see org.beanio.BeanReaderErrorHandlerSupport#fatalError(org.beanio.BeanReaderException) 
    */ 
    @Override 
    public void fatalError(final BeanReaderException ex) throws BeanReaderException { 

    LOGGER.error("{}", createErrorMessage(ex)); 
    } 

    /** 
    * Creates an error message using the exception to get the RecordContext from which a meaningful error 
    * message can be constructed. 
    * 
    * @param ex the exception containing the error information. 
    * 
    * @return a string describing the error(s). 
    */ 
    protected String createErrorMessage(final BeanReaderException ex) { 

    final String message = ex.getMessage(); 
    final StringBuilder errorMessage = new StringBuilder(message.length() * 5); 

    // if a bean object is mapped to a record group, 
    // the exception may contain more than one record 
    for (int i = 0, j = ex.getRecordCount(); i < j; i++) { 
     final RecordContext recordContext = ex.getRecordContext(i); 
     final String recordName = recordContext.getRecordName(); 
     final String text = recordContext.getRecordText(); 
     errorMessage.append(String.format("%s: %s%n", message, text)); 

     if (recordContext.hasRecordErrors()) { 
     for (final String error : recordContext.getRecordErrors()) { 
      errorMessage.append(String.format("Record '%s' - %s%n", recordName, error)); 
     } 
     } 
     if (recordContext.hasFieldErrors()) { 
     for (final String field : recordContext.getFieldErrors().keySet()) { 
      for (final String error : recordContext.getFieldErrors(field)) { 
      errorMessage.append(String.format("Field '%s' - %s%n", field, error)); 
      } 
     } 
     } 
    } 

    return errorMessage.toString(); 
    } 

} 

您可以修改createErrorMessage()方法只保留你正在寻找的信息。

当然你可以用这些信息做很多其他的事情,比如写入文件,发邮件等等。请参阅文档的BeanReaderErrorHandler部分查找替代方法。

然后,你必须与你的BeanReader实例来注册错误处理程序:

BeanReader beanReader = .... 
beanReader.setErrorHandler(errorHandler); 

哪里错误位于这应该然后输出的更多信息。