barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

пятница, 12 декабря 2014 г.

Java: String.split() и пустые значения

Допустим, мы читаем некую строку, в которой значений разделены разделителями-табулциями:
a\tb\tc\t\te
На выходе 
"a\tb\tc\t\te".split("\t")
ожидаем массив из 5 значений, предпоследнее из которых будет пустым. Однако, размер выходного массива будет равен 4, а пустое значение в него не попадет. Выход - немного модифицировать вызов:
"a\tb\tc\t\te".split("\t", -1)

четверг, 20 ноября 2014 г.

ActiveMQ 5.7.0: настройка Dead Letter Queue и числа попыток повторной доставки для отдельной очереди

Задача

Есть некая очередь MyQueue. Для нее нужно настроить (независимо от общих настроек JMS-сервера):

  • Отдельную очередь, куда будут складываться недоставленные сообщения из этой очереди (Dead Letter Queue, или сокращённо DLQ), т.к. по-умолчанию в качестве DQL для всех очередей используется очередь с именем ActiveMQ.DLQ
  • Число попыток повторной доставки, по истечению которого сообщение будет помещаться в эту самую DLQ
Решение

Настройки выполняются в conf/activemq.xml. Первый шаг - отдельная DQL, настраивается она с помощью блока policyEntry со вложенным deadLetterStrategy:
<destinationPolicy>
<policyMap>
 <policyEntries>
<!-- -->
<policyEntry queue="MyQueue">
 <deadLetterStrategy>
<individualDeadLetterStrategy
 queuePrefix="DLQ." useQueueForQueueMessages="true" />
 </deadLetterStrategy>
</policyEntry>
 </policyEntries>
</policyMap>
</destinationPolicy>
Данная конфигурация указывает использовать в качестве DQL очередь с именем DQL.MyQueue. Помимо префикса, можно также задать постфикс (http://activemq.apache.org/maven/apidocs/org/apache/activemq/broker/region/policy/IndividualDeadLetterStrategy.html). Задать целиком имя очереди, насколько я понял, нельзя. Впрочем, меня устроил и вариант с префиксом.
Теперь про число повторных доставок. Настраиваться она может различными способами (https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_A-MQ/6.0/html/Client_Connectivity_Guide/files/AMQClientConnectRedelivery.html), но server-side способ один - с помощью redeliveryPlugin. Выполняется такая настройка помещением в тот же activemq.xml внутрь блока <broker>:
<plugins>
<redeliveryPlugin>
 <redeliveryPolicyMap>
<redeliveryPolicyMap>
 <redeliveryPolicyEntries>
<!-- a destination specific policy -->
<redeliveryPolicy queue="MyQueue"
 maximumRedeliveries="1" />
 </redeliveryPolicyEntries>
 <!-- the fallback policy for all other destinations -->
 <defaultEntry>
<redeliveryPolicy maximumRedeliveries="10" />
 </defaultEntry>
</redeliveryPolicyMap>
 </redeliveryPolicyMap>
</redeliveryPlugin>
  </plugins>
Особенность заключается в том, что для того, чтобы такая настройка отрабатывала как ожидается, клиент должен при подключении к брокеру указывать jms.redeliveryPolicy.maximumRedeliveries=0.

Apache PdfBox: WARN (XrefTrailerResolver.java:199) Did not found XRef object at specified startxref position 18252

Проблема

При обработке pdf-файла с помощью Apache PdfBox в лог попадает warning:
WARN (XrefTrailerResolver.java:199) Did not found XRef object at specified startxref position 18252

Причина

Если открыть pdf-ку в текстовом редакторе, можно увидеть, что в ней есть блок:
startxref
18252
представляющий из себя ссылку на таблицу перекрестных ссылок ("cross-reference table"). 
Посмотрев в hex-редакторе на адрес 18252 (в шестнадцатеричной системе счисления - это 0x474c) я увидел, что по нему, вместо начала таблицы (ключевого слова "xref") идет окончание ключевого слова endobj, а искомое "xref" идет на 4 байта дальше:

Если поправить ссылку в startxref на корректную (в моем случае - 18256), то warning уходит.


суббота, 11 октября 2014 г.

IE8: аналог getElementsByTagNameNS для объекта Microsoft.XMLDOM

Задача

В Internet Explorer 8 есть объект Microsoft.XMLDOM (передаваемый dojo-вским xjrPost в обработчик success), нужно из него вытащить элемент по имени тега, причем элемент имеет пространство имен.

Решение

Немного замысловато (здесь xml - объект Microsoft.XMLDOM):

xml.setProperty("SelectionNamespaces", "xmlns:myns='http://myns.com/ns'");
xml.setProperty("SelectionLanguage", "XPath");
alert(xml.documentElement.selectNodes("//myns:MyElement").length);

четверг, 2 октября 2014 г.

WSO2 ESB 4.5.1: реализация Splitter-паттерна с JMS-endpoint'ами и транзакицонностью

Задача

Реализовать прокси-сервис, который:

  • принимает по http входящее сообщение, являющееся "пакетным", т.е. состоящим из составных частей, которые должны обрабатываться отдельно друг от друга (Splitter EIP)
  • разбивает "пакет" на отдельные сообщения, складывает их по одному в JMS-очедерь
  • если все сообщения положились успешно, отвечает на входящий запрос успехом
  • если при помещении в JMS хотя бы одного из сообщений возникла ошибка, вся jms-транзакция должны быть откачена и в ответ на входящий запрос должен быть отправлен soapFault
Проблема

Вроде бы, реализация очевидна: iterate-медиатор для итерации по отдельным частям "пакета" и отправка этих "частей" на jms-endpoint посредством send-медиатора. Но проблема заключается в том, что JMSSender (входит в axis2-transport-jms) не умеет работать с jms-транзакциями. Т.е., если посмотреть в исходники, видим:
session = ((QueueConnection) connection).
            createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
, где false говорит об отсутствии поддержки транзакций. Т.е. не то что распределенные транзакции, а даже локальные транзакции не поддерживаются при записи в jms с помощью send-медиатора.
Другой вариант - использовать store-медиатор и JMSMessageStore. Однако, открыв исходники JMSMessageStore, видимо практически тоже самое:
return connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
Т.о., для реализации указанных требований придется что-то пилить руками, используя напрямую JMS-API.

четверг, 25 сентября 2014 г.

GUI-браузер для JKS-файлов

http://www.clearfield.com/key_store_browser/key_store_browser.html - вполне рабочая вещь, единственное что - импорт сертификатов все равно пришлось делать через keytool, т.к. эта утилита выдавала какую-то невнятную ошибку.