терминатор сегмента в BeanIO

Меня интересует свойство парсера recordTerminator BeanIO. Это относится и к сегментам, например к «segmentTerminator»? А именно, у меня есть поток формата фиксированной длины, содержащий одну запись с повторяющимися сегментами, и весь поток представляет собой одну строку. Следовательно, я установил recordTerminator="", но это все равно дает мне

==> 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

Он не жалуется на поля, которые предшествуют повторяемому сегменту, а жалобы на поля в повторяемом сегменте не соответствуют порядку, определенному в mapping.xml, который выглядит следующим образом:

    <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>

Реализации класса выглядят так:

    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...
    }       

Если я удалю все предыдущие поля в повторяющемся сегменте как из файла mapping.xml, так и из входной строки, оставшаяся строка будет должным образом деупорядочена и впоследствии маршалирована в json, я даже не изменил реализацию классов Java, поэтому предыдущие поля остаются неинициализированными, поскольку ожидается, но правильно распечатывается после сортировки. Где я неправ?

ОК, мой верблюжий код в spring xml выглядит так:

    <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>

Итак, в основном, когда я раскомментирую ввод из файла, в котором сохранен ответ, и помещаю в комментарий mq к конечной точке, демаршаллинг в порядке, но если я помещаю запрос в очередь и получаю ответ, то я надеюсь исправить проблему преобразованием, которое просто добавляет символ EOF, потому что без него это дает мне ошибку, о которой я сообщил в первую очередь. И преобразование не помогает, потому что я не знаю, как написать EOF (ascii 26), но даже если я это выясню, я не уверен, что это поможет.


person hdjur_jcv    schedule 16.02.2018    source источник
comment
На самом деле, если я верну все предыдущие поля обратно во входной поток и mapping.xml, но я прочитаю поток из файла, а не из очереди, все в порядке, неупорядочивание фиксированной длины в POJO, а затем маршалирование в json с помощью jackson. Таким образом, разница должна заключаться в обработке EOF для потока.   -  person hdjur_jcv    schedule 16.02.2018
comment
Таким образом, теперь возникает вопрос, как объединить символ EOF с ${body} в маршруте Apache Camel перед десортировкой.   -  person hdjur_jcv    schedule 16.02.2018
comment
Я вообще не знаю Camel, но, возможно, это поможет - stackoverflow.com/a/41450736/2020886   -  person nicoschl    schedule 16.02.2018
comment
Кроме того, если сейчас речь идет больше о Camel, то я предлагаю вам также предоставить соответствующий код Camel.   -  person nicoschl    schedule 16.02.2018
comment
Я пробовал использовать ‹transform›‹simple›${in.body}\0‹/simple›‹/transform› и ‹transform›‹simple›${in.body}\n‹/simple›‹/transform› , но это не сработало.   -  person hdjur_jcv    schedule 16.02.2018


Ответы (2)


Я собираюсь попробовать это как ответ, к сожалению, я не могу это проверить, у меня нет никаких настроек для использования с Camel. Во-первых, я бы не стал менять значение по умолчанию recordTerminator для BeanIO и оставить его для использования значения по умолчанию, которое является любым из CR, LF или CRLF.

Затем при преобразовании сообщения я добавлю новую строку (\n) вместо \0. Я не совсем понимаю, почему вы хотите использовать символ EOF, если у вас есть контроль над ним. Вместо:

<transform>
  <simple>${body}\0</simple>
</transform>

Я бы пошел на:

<transform>
  <simple>${body}\n</simple>
</transform>

См. раздел "Использование новых строк или вкладок в XML DSL" в нижней части страница:

Использование новых строк или вкладок в XML DSL

Доступно в Camel 2.9.3

Из Camel 2.9.3: стало проще указывать новые строки или вкладки в XML DSL, так как теперь вы можете экранировать значение xml

<transform> <simple>The following text\nis on a new line</simple></transform>
person nicoschl    schedule 16.02.2018
comment
К сожалению, это не работает, я удалил параметр recordTerminator из mapping.xml и попробовал еще раз, добавив \n, но все по-прежнему. И, кстати, содержимое файла, с которым работает маршрут, если взять на вход, не имеет новой строки в конце, поэтому я попытался конкатенировать EOF в конце, а не \n. - person hdjur_jcv; 19.02.2018
comment
Хорошо, нет проблем. Это из-за моего отсутствия знаний о Camel - person nicoschl; 19.02.2018
comment
nicoschl, спасибо за помощь. Я понял, что верблюжий маршрут на самом деле прерывается, когда в ответном сообщении есть диакритические знаки. Таким образом, речь идет не о том, как завершается полная строка при получении из очереди или чтении из файла, а о том, что мне нужно что-то установить в BeanIO, чтобы он правильно анализировал и неупорядочивал диакритические знаки utf-8. - person hdjur_jcv; 19.02.2018
comment
Я нашел в Camel что-то вроде этого: ‹convertBodyTo type=java.lang.String charset=UTF-8 /›, возможно, мне стоит попробовать, прежде чем разбирать. - person hdjur_jcv; 19.02.2018
comment
Преобразование в UTF-8 имело какое-либо значение? - person nicoschl; 20.02.2018
comment
К сожалению, нет, я все еще пытаюсь решить проблему, но я уверен, что проблема в том, что фиксированные позиции перепутались, когда длины становятся переменными из-за кодировки utf-8, когда диакритические знаки представлены двумя символами, а затем фиксированная длина рассортировка не удается. - person hdjur_jcv; 20.02.2018
comment
Может быть, BeanIO не очень заботится о том, чтобы сообщить ему, что такое кодировка, если он считает только байты? В этом случае нет никакого способа распараллелить с ним строки фиксированной длины utf-8, если только я не конвертирую его в кодировку, которая раньше имела представление однобайтовой кодировки, а потом обратно в utf-8? - person hdjur_jcv; 20.02.2018
comment
BeanIO не считает байты AFAIK. Чтобы убедиться, что он использует правильную кодировку, используйте InputStreamReader и укажите правильную кодировку в конструкторе. Reader in = new InputStreamReader(new FileInputStream("input.txt"), StandardCharsets.UTF_8)); BeanReader beanReader = factory.createReader("streamName", in); - person nicoschl; 20.02.2018
comment
На самом деле, я думаю, что цель convertBodyTo не в том, чтобы сообщить какому-то классу, который должен выполнять десортировку, что фактическая строка, хотя и объявленная фиксированной длины, может быть переменной длины, а в том, чтобы выполнить фактическое преобразование. Но для этого нужно, чтобы я сначала сказал где-нибудь, что фактическим источником является utf-8, возможно, из конечной точки. - person hdjur_jcv; 20.02.2018
comment
Хорошо, мой пост был только через 40 секунд, я рассмотрю ваше предложение, спасибо. - person hdjur_jcv; 20.02.2018
comment
Заметив здесь camel.apache.org/schema/spring/camel-spring.xsd что beanioDataFormat имеет кодировку атрибута, которая позволяет определить используемую кодировку, я добавил ее, но это также не помогает. - person hdjur_jcv; 20.02.2018
comment
‹beanio id=parseTransactions464 mapping=mapping.xml streamName=Transactions464 encoding=UTF-8/› - person hdjur_jcv; 20.02.2018
comment
Я получаю: Exhausted после попытки доставки: 1 поймал: java.lang.NullPointerException: charset - person hdjur_jcv; 20.02.2018
comment
Давайте продолжим обсуждение в чате. - person nicoschl; 20.02.2018
comment
nicoschl, я присоединюсь к вам, как только вернусь домой, к сожалению, наша корпоративная политика безопасности запрещает использование этого чата по какой-то необоснованной причине, но все ребята, которые смогли устранить это препятствие, уже покинули офис. С нетерпением жду возможности поговорить с вами. - person hdjur_jcv; 20.02.2018

Я плавал вокруг, пытаясь определить проблему, но в конце концов я понял, что должен был установить кодировку с атрибутом кодирования beanio dataFormat, чего я не мог сделать из-за этого дефекта:

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

Наконец, Клаус Ибсен поручил мне использовать такой обходной путь:

    <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> 
person hdjur_jcv    schedule 21.02.2018