Search code examples
utf-8apache-camelunmarshallingbean-iofixed-length-record

segment terminator in BeanIO


I'm interested in the recordTerminator parser property of BeanIO. Does it apply to segments too, like "segmentTerminator"? Namely, I have a stream of fixedlength format, containing of a single record with repeatable segments, and all stream is a single line. Hence, I have set recordTerminator="", but it still gives me

==> Invalid 'state':  Expected minimum 1 occurrences
==> Invalid 'city':  Expected minimum 1 occurrences
==> Invalid 'street':  Invalid field length, expected 35 characters
==> Invalid 'zip':  Expected minimum 1 occurrences

It doesn't complain about fields that precede to repeatable segment, and complaints about the fields in a repeatable segment are out of order defined in mapping.xml, that looks like this:

    <beanio  xmlns="http://www.beanio.org/2012/03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">
      <stream name="employeeFile" format="fixedlength">
        <parser>
            <property name="recordTerminator" value="" />
        </parser>  
        <record name="employee" class="example.Employee">
          <field name="firstName" length="35" />
          <field name="lastName" length="35" />
          <field name="title" length="35" />
          <field name="salary" length="35" />
          <segment name="addressList" collection="list" minOccurs="1" maxOccurs="unbounded" class="example.Address">
            <field name="street" length="35" />
            <field name="city" length="35" />
            <field name="state" length="35" />      
            <field name="zip" length="10" />
          </segment>
        </record> 
      </stream>
    </beanio>

Class implementations is like this:

    package example;        
    public class Employee {
        String firstName;
        String lastName;
        String title;
        String salary;
        List<Address> addressList;

        // getters and setters not shown...
    }       

    package example;
    public class Address {
        private String street;
        private String city;
        private String state;
        private String zip;

        // getters and setters not shown...
    }       

If I remove all preceding fields to repetitive segment both from mapping.xml and the input string, remaining string is properly unmarshalled, and marshalled to json afterwards, I even didn't change implementation of java classes, so the preceding fields stay uninitialized, as expected, but properly printed out after marshalling. Where did I go wrong?

OK, my camel code is in spring xml, looks like this:

    <route id="simple-route">
        <!-- from id="request-file" uri="file://C:/mqdocuments/?fileName=response464.txt"/-->
        <from id="request-file" uri="file://C:/mqdocuments/?fileName=request464.txt"/>
        <log id="route-log-request" message="request: ${body}"/>
        <setHeader headerName="CamelJmsDestinationName" id="_setHeader1">
            <constant>queue://QM_TEST/INPUTQ?targetClient=1</constant>
        </setHeader>
        <to id="_to1" pattern="InOut" uri="websphere:queue:SYSTEM.DEFAULT.LOCAL.QUEUE?useMessageIDAsCorrelationID=true&amp;replyTo=REPLYQ"/>
        <log id="route-log-response" message="response: ${body}"/>
                    <transform>
                        <simple>${body}\0</simple>
                </transform>
        <unmarshal ref="parseTransactions464"/>
        <marshal ref="jack"/>
        <log id="route-log-json" message="jackson: ${body}"/>
</route>

So basically, when I uncomment input from file, in which the reponse is saved, and place in comment mq to endpoint, unmarshalling is OK, but if I put a request to a queue, and get response, then I hope to rectify the problem by a transform that simply adds EOF character, because without it, it gives me error that I reported in the first place. And transform doesn't help, because I don't know how to write EOF (ascii 26), but even if I figure that out, I'm not sure it will help.


Solution

  • I was floating around trying to identify the problem, but in the end, I realized I should have set the charset with the encoding attribute of beanio dataFormat, which I couldn't do because of this defect:

    http://camel.465427.n5.nabble.com/Re-Exhausted-after-delivery-attempt-1-caught-java-lang-NullPointerException-charset-tc5817807.html

    http://camel.465427.n5.nabble.com/Exhausted-after-delivery-attempt-1-caught-java-lang-NullPointerException-charset-tc5817815.html

    https://issues.apache.org/jira/browse/CAMEL-12284

    Finally, I was instructed by Claus Ibsen to use such workaround:

        <bean class="org.apache.camel.dataformat.beanio.BeanIODataFormat" 
              id="some_bean_id"> 
            <property name="encoding" value="UTF-8"/> 
            <property name="mapping" value="mapping.xml"/> 
            <property name="streamName" value="some_stream_name"/> 
        </bean>