[ 
https://issues.apache.org/jira/browse/CAMEL-14085?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16955639#comment-16955639
 ] 

Robert Half commented on CAMEL-14085:
-------------------------------------

Here I created a reproducer test, which fails with the error below.

The problem with the fixed length records and variable encoding like UTF-8 is 
that the format as far as I'm concerned and which is the case for the format 
I'm processing, is based on records given in bytes - not characters. So if I 
know the first record is 10 bytes, I can only read it with bindy if every 
character takes 1 byte.

StacktraceStacktrace---------------------------------------------------------------------------------------------------------------------------------------java.lang.IllegalArgumentException:
 Size of the record: 9 is not equal to the value provided in the model: 10 at 
org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat.createModel(BindyFixedLengthDataFormat.java:295)
 at 
org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat.unmarshal(BindyFixedLengthDataFormat.java:242)2019-10-20T10:49:27.873
 | -1 | main | INFO  |  ---  ---  ---  | com.mypackage.CamelBindyReproducerTest 
| - 
{code:java}
import org.apache.camel.EndpointInject;
import org.apache.camel.Exchange;
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.dataformat.bindy.annotation.DataField;
import org.apache.camel.dataformat.bindy.annotation.FixedLengthRecord;
import org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat;
import org.apache.camel.spring.javaconfig.SingleRouteCamelConfiguration;
import org.apache.camel.test.spring.CamelSpringDelegatingTestContextLoader;
import org.apache.camel.test.spring.CamelSpringRunner;
import org.apache.camel.test.spring.CamelTestContextBootstrapper;
import org.apache.camel.test.spring.MockEndpoints;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.BootstrapWith;
import org.springframework.test.context.ContextConfiguration;

import java.nio.charset.StandardCharsets;

import static org.junit.Assert.assertThat;

@RunWith(CamelSpringRunner.class)
@BootstrapWith(CamelTestContextBootstrapper.class)
@ContextConfiguration(
 classes = CamelBindyReproducerTest.TestConfig.class,
 loader = CamelSpringDelegatingTestContextLoader.class)
@MockEndpoints
@DirtiesContext(
 classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class CamelBindyReproducerTest {

 @Produce(uri = "direct:in")
 private ProducerTemplate producer;

 @EndpointInject(uri = "mock:result")
 private MockEndpoint result;

 @Test
 /*
 Let's assume we want to read the content of a 10 bytes record from an UTF-8 
encoded file.
 test string takes 10 bytes with 9 characters (2 char = 3 bytes content + 
padding).
 I assume to be able to read 9 char string from this 10 bytes fixed length 
record with bindy.
 */
 public void reproduceBindyErrorTest() throws InterruptedException {
 String test = "aß ";
 byte[] testAsBytes = test.getBytes(StandardCharsets.UTF_8);
 Assert.assertEquals("aß takes 3 bytes, because ß takes 2", 10, 
testAsBytes.length);
 result.expectedMessagesMatches(exchange -> 
"aß".equals(exchange.getIn().getBody(TestRecord.class).field1));
 producer.sendBody(test);
 result.assertIsSatisfied();
 }

 @Configuration
 static class TestConfig extends SingleRouteCamelConfiguration {

 @Override
 public RouteBuilder route() {
 return new RouteBuilder() {
 @Override
 public void configure() throws Exception {
 from("direct:in")
 .setHeader(Exchange.CHARSET_NAME, constant(StandardCharsets.UTF_8.name()))
 .unmarshal(new BindyFixedLengthDataFormat(TestRecord.class))
 .to("mock:result");
 }
 };
 }
 }

 @FixedLengthRecord(length = 10, paddingChar = ' ')
 public static class TestRecord {
 public TestRecord() {

 }
 public String getField1() {
 return field1;
 }

 public void setField1(String field1) {
 this.field1 = field1;
 }

 @DataField(pos = 1, length = 10)
 private String field1;
 }
}{code}

> Camel Bindy @FixedLengthRecord cannot parse UTF-8 with multibyte characters
> ---------------------------------------------------------------------------
>
>                 Key: CAMEL-14085
>                 URL: https://issues.apache.org/jira/browse/CAMEL-14085
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-bindy
>    Affects Versions: 2.21.5
>            Reporter: Robert Half
>            Priority: Major
>             Fix For: 2.25.0, 3.x
>
>
> We are using Camel Bindy to parse fixed length data.
> I came across the issue, that it fails to read data containing characters 
> like ß, which takes 2 bytes. The character set is properly set on the 
> exchange to UTF-8, the record length is 1568 bytes, but since there are 2xß 
> characters, it throws the error:
> Size of the record: 1566 is not equal to the value provided in the model: 
> 1568, StackTrace: java.lang.IllegalArgumentException: Size of the record: 
> 1566 is not equal to the value provided in the model: 1568Size of the record: 
> 1566 is not equal to the value provided in the model: 1568, StackTrace: 
> java.lang.IllegalArgumentException: Size of the record: 1566 is not equal to 
> the value provided in the model: 1568 at 
> org.apache.camel.dataformat.bindy.fixed.BindyFixedLengthDataFormat.createModel(BindyFixedLengthDataFormat.java:295)
> here:
> BindyFixedLengthDataFormat#createModel
> {code:java}
> if ((myLine.length() < factory.recordLength()
>  && !factory.isIgnoreMissingChars()) || (myLine.length() > 
> factory.recordLength())) {
>  throw new java.lang.IllegalArgumentException("Size of the record: " + 
> myLine.length()
>  + " is not equal to the value provided in the model: " + 
> factory.recordLength());
> }{code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to