shashank created CAMEL-26452:
--------------------------------

             Summary: camel-beanio - BeanIOSplitter drops the record after each 
invalid record that the error handler replaces with a result
                 Key: CAMEL-26452
                 URL: https://issues.apache.org/jira/browse/CAMEL-26452
             Project: Camel
          Issue Type: Bug
          Components: camel-beanio
            Reporter: shashank
            Assignee: shashank


A custom {{BeanIOErrorHandler}} can turn an invalid record into a result with 
{{handleErrorAndAddAsResult(Object)}} (the {{MyErrorHandler}} of the component 
tests does it). The {{beanio}} data format adds that result to its list; 
{{BeanIOSplitter}} gives it to its {{BeanIOIterator}} with {{setNext(result)}}.

The error handler is called from inside {{BeanReader.read()}}. After the 
handler returns, BeanIO goes on reading and {{read()}} returns the next valid 
record. {{BeanIOIterator.next()}} then does:

{code:java}
next = reader.read();        // the valid record after the invalid one
if (forceNext != null) {
    next = forceNext;        // ... is replaced by the result of the error 
handler
    forceNext = null;
}
{code}

So the valid record that follows a handled invalid record is lost, and of two 
invalid records in a row only the last result is kept (the single {{forceNext}} 
field is overwritten). Nothing is logged. Only a single invalid record at the 
end of the data (where {{read()}} returns null) works, which is what 
{{BeanIOSplitterCustomBeanReaderErrorHandlerTest.testSplitFail}} covers.

Reproducer (the employee mapping of the component tests, 
{{split(splitter).streaming()}} with 
{{setBeanReaderErrorHandlerType(MyErrorHandler.class)}}):

||Records||split on main (4ab42b192b26)||unmarshal with the data format||
|Joe, Jane (invalid salary), Jon|Joe, ErrorDto|Joe, ErrorDto, Jon|
|Joe, Jane (invalid), Jim (invalid), Jon, Jack|Joe, ErrorDto, Jack|Joe, 
ErrorDto, ErrorDto, Jon, Jack|

A route that splits data with such an error handler silently drops a valid 
record after each invalid one, with any BeanIO stream format. The same code is 
on the 4.14.x, 4.18.x and 4.22.x branches.

*Proposal*
* {{BeanIOIterator}} keeps the results that the error handler adds during a 
read in a queue, and returns them in their order before the record that the 
read returned (the same order as the data format's list). {{setNext}} adds to 
the queue.
* Tests: an invalid record in the middle, two invalid records in a row followed 
by valid ones (with their order), an invalid first record, and an error handler 
type that cannot be created.

Next to it: the first record is read in the {{BeanIOIterator}} constructor, 
before {{BeanIOSplitter}} sets the error handler on the reader, so an invalid 
first record fails the split even with {{ignoreInvalidRecords=true}} or a 
custom error handler; and when the error handler cannot be created (a wrong 
{{beanReaderErrorHandlerType}}), the reader of the body is not closed. 
Proposal: set the error handler before the first read, inside the block that 
closes the reader on a failure.

_Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to