BeanIO InvalidRecordGroupException 给出错误的行号
BeanIO InvalidRecordGroupException giving wrong line number
我正在使用 BeanIO 来解析固定宽度的文本文件。例如,进入我的项目的文件看起来像以下固定宽度的文本:
CD DummyValue3
EF DummyValue4 DummyValue5 DummyValue6
AB DummyValue1 DummyValue2
...
在我的映射文件中,我为每个记录 ID(即 AB、CD、EF)声明了 record
<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>
因为 value1
和 value2
有一个 minOccurs = 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 输出正确的行号,甚至是缺少必填字段时的 template
和 field
值?
我通过扩展 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);
这应该会输出有关错误位置的更多信息。
我正在使用 BeanIO 来解析固定宽度的文本文件。例如,进入我的项目的文件看起来像以下固定宽度的文本:
CD DummyValue3
EF DummyValue4 DummyValue5 DummyValue6
AB DummyValue1 DummyValue2
...
在我的映射文件中,我为每个记录 ID(即 AB、CD、EF)声明了 record
<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>
因为 value1
和 value2
有一个 minOccurs = 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 输出正确的行号,甚至是缺少必填字段时的 template
和 field
值?
我通过扩展 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);
这应该会输出有关错误位置的更多信息。