barbitoff programmer`s blog

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

вторник, 16 декабря 2014 г.

XPath 1.0: тернарный оператор

Как такового, тернарного оператора в XPath 1.0 нет. Можно реализовать аналогичное поведение, правда, немного замысловатым образом. Следующее выражение даст $stringA, если $cond = true, и $stringB - в противном случае:
concat(substring($stringA, 1 div $cond), substring($stringB, 1 div not($cond)))

WSO2 ESB 4.5.1: использование пространства имен http://ws.apache.org/ns/synapse в XPath-выражениях

Проблема

Есть прокси-сервис, в нем есть property-медиатор, у которого в xpath-выражении в атрибуте expression используется пространство имен "http://ws.apache.org/ns/synapse" с помощью некоторого префикса, который объявлен в этом же property-теге:
<property name="XXXProp" expression="//syn:abc/text()" xmlns:syn="http://ws.apache.org/ns/synapse"/>
Если прокси-сервис отредактировать через веб-консоль шины, объявление префикса пропадает, после чего property-медиатор, естественно, начинает выдавать ошибки из-за неизвестного префикса пространства имен. Если объявление префикса перенести из медиатора выше (хотя даже в сам корневой тег прокси-сервиса), ситуация не меняется.

Решение

Похоже на баг, и вызван он скорее всего тем, что сам конфигурационный xml прокси-сервиса имеет пространство имен по-умолчанию "http://ws.apache.org/ns/synapse". Копаться в исходниках времени не было, поэтому пришлось воспользоваться workaround'ом:
<property name="XXXProp" expression="//*[local-name()='abc']/text()" />

пятница, 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, т.к. эта утилита выдавала какую-то невнятную ошибку.

пятница, 29 августа 2014 г.

Дамп HTTP-запросов tcpdump-ом

Возникла необходимость посмотреть http-заголовки запросов, приходящих на weblogic. Т.к. вывести произвольный заголовок в access-log без написания кода невозможно (http://technotoddle.blogspot.ru/2010/07/logging-more-information-in-http-logs.html), я решил особо не заморачиваться и посмотреть траффик сниффером. На Win обычно использую для подобных целей Wireshark, но здесь я был на linux-сервере без иксов, поэтому первый раз в жизни воспользовался tcpdump-ом. Делается это так:
tcpdump -A -s 0 'tcp dst port 8080 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
(здесь сниффятся входящие запросы на порт 8080, если убрать dst, то получим в дампе и запросы, и ответы)
На выходе получил то, что хотел:
17:17:25.769127 IP xxx >yyy: . 297430808:297432068(1260) ack 1587021758 win 16695
E.....@.....
..I
..5.d....o.^...P.A7....GET /da/component/main?__dmfClientId=1409209083173&__dmfRequestId=__client1~~2&__dmfJumpType=jump&__dmfTzoff=-240 HTTP/1.1
Accept: */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727)
Accept-Encoding: gzip, deflate
Host: 10.2.5.53:8080
Connection: Keep-Alive
Cookie: appname=da;  ...
Спасибо https://sites.google.com/site/jimmyxu101/testing/use-tcpdump-to-monitor-http-traffic

пятница, 22 августа 2014 г.

WSO2 ESB: передача параметра из synapse-окружения в xslt

Задача

Есть некий xslt, выполняемый посредством xslt-медиатора. Есть некое свойство в default synapse-scope, хочется им воспользоваться внутри xslt.

Решение

Просто вызвать xpath-функцию syn:get-property изнутри xstl не получится - получим ругань на то, что функция отсутствует. Но есть другой вариант - через xslt-параметры. В xslt объявляем параметр:
<xsl:stylesheet ...>
<xsl:param name="MyParam" />
<!-- ... -->
</xsl:stylesheet>
А при вызове xslt-медиатора передать нужно значение в этот параметр:
<xslt key="...">
<property name="MyParam" expression="get-property('xxx')"/>
</xslt>

Ошибка java.lang.NullPointerException в классе ClassFinderMetaDataEnumaration при старте веб-приложения на weblogic

Проблема

При старте веб-приложения на weblogic 10.3.5 падает ошибка:
weblogic.application.ModuleException: Failed to load webapp: 'xxx'
at weblogic.servlet.internal.WebAppModule.prepare(WebAppModule.java:393)
at weblogic.application.internal.flow.ScopedModuleDriver.prepare(ScopedModuleDriver.java:176)
at weblogic.application.internal.flow.ModuleListenerInvoker.prepare(ModuleListenerInvoker.java:199)
at weblogic.application.internal.flow.DeploymentCallbackFlow$1.next(DeploymentCallbackFlow.java:517)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:52)
Truncated. see log file for complete stacktrace
Caused By: java.lang.NullPointerException at weblogic.application.utils.ClassFinderMetaDataEnumaration.hasMoreElements(ClassFinderMetaDataEnumaration.java:32)
at weblogic.servlet.internal.WebAnnotationProcessorImpl.getAnnotatedClasses(WebAnnotationProcessorImpl.java:139)
at weblogic.servlet.internal.War.getAnnotatedClasses(War.java:1038)
at weblogic.servlet.internal.WebAppServletContext$ServletContextWebAppHelper.getAnnotatedClasses(WebAppServletContext.java:3833)
at weblogic.servlet.internal.WebAnnotationProcessorImpl.processAnnotations(WebAnnotationProcessorImpl.java:84)
Truncated. see log file for complete stacktrace
Причина

В приложении был класс класс Settings с вложенным статическим приватным классом Settings.PropertyNames. Не было времени разбираться, что именно мешало weblogic'у, имя класса PropertyNames или же приватный доступ вложенного статического класса, но после того, как я убрал этот класс, приложение начало стартовать.

среда, 30 июля 2014 г.

WSO2 ESB 4.5.1: создание Scheduled Message Forwarding Processor через веб-консоль и настройка числа попыток повторной доставки

При создании Scheduled Message Forwarding Processor через веб-консоль WSO2 ESB есть возможность настройки числа попыток повторной отправки сообщения:


Однако, задаваемое здесь значение не применяется к Message Processor'у, и вот почему. В xml-файл конфигурации прокси-сервиса прописывается следующее:
<parameter name="max.delivery.attempts">2</parameter>
Тогда как в документации (https://docs.wso2.com/display/ESB451/Message+Forwarding+Processor) указано имя параметра "max.deliver.attempts". Если поправить имя на указанное в документации, настройка применяется.

пятница, 11 июля 2014 г.

Documentum: дамп типа с помощью API Tester'а

Для получения дампа некоторого типа Documentum с именем xx_type с помощью API Tester'а нужно выполнить следующие команды:
1. Командой:
retrieve,c,dm_type where name = 'xx_type' 
получить r_object_id объекта типа
2. Командой:
dump,c,<r_object_id из результата выполнения предыдущей команды>
сделать собственно дамп 

среда, 30 апреля 2014 г.

Excel: заголовки столбцов цифрами

Проблема: в книге Excel столбцы именуются цифрами вместо букв.
Решение (Excel 2010, англ.): File -> Options -> Formulas -> снять галочку "R1C1 reference style".

понедельник, 21 апреля 2014 г.

ActiveMQ 5.7.0 и JMX

Самый простой способ: идем в bin/activemq.bat, комментим:
if "%SUNJMX%" == "" set SUNJMX=-Dcom.sun.management.jmxremote
и раскомменчиваем:
set SUNJMX=-Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
Получаем JMX на порту 1099 без аутентификации.
Если нужна аутентификация, то настройка следующая:
if "%SUNJMX%" == "" set SUNJMX=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.access.file=%ACTIVEMQ_HOME%\conf\jmx.access -Dcom.sun.management.jmxremote.password.file=%ACTIVEMQ_HOME%\conf\jmx.password -Dcom.sun.management.jmxremote.ssl=false
Для файла %ACTIVEMQ_HOME%\conf\jmx.password нужно зайти в настройки безопасности и сделать так, чтобы единственным пользователем, имеющим доступ к этому файлу, был тот, из-под кого стартует ActiveMQ, иначе будет валится ошибка:
Password file read access must be restricted
(см. http://docs.oracle.com/javase/6/docs/technotes/guides/management/security-windows.html). 

пятница, 18 апреля 2014 г.

Spring Beans: свой bean вместо String

Проблема

В xml-конфиге спринговых бинов есть некий бин, принимающий аргументом конструктора строку:
<constructor-arg index="0">
<value>xxx</value>
</constructor-arg>
 Хочется эту строку формировать своим бином вместо хардкода ее в xml.

Решение

Первая идея - унаследоваться от String и заменить <value> на <bean class="my.super.Bean">. Но нет - java.lang.String объявлен как final. Следующая мысль - использовать конструктор класса String, принимающий StringBuilder, и опять таки переопределить SpringBuilder своим классом. Но снова неудача - java.lang.StringBuilder также является final. Но StringBuilder уже лучше String'а тем, что имеет конструктор, принимающий CharSequence. А это - уже интерфейс, и его можно свободно имплементировать, реализовав ту логику, которую нужно. В итоге получаем нечто подобное:
<constructor-arg index="0">
<bean class="java.lang.String">
<constructor-arg>
<bean class="java.lang.StringBuilder">
<constructor-arg>
<bean class="my.super.CharSequenceImpl">
<!-- ... -->
</bean>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</constructor-arg>

Raphael: Paper.print() и шрифты

В Paper.print() используется шрифт, получаемый с помощью Paper.getFon():
var txt = r.print(10, 50, "print", r.getFont("Tahoma"), 30).attr({fill: "#fff"});
Проблема в том, что по-умолчанию доступных шрифтов нет вообще. Чтобы  тот же самый Tahoma стал доступен, его нужно сначала зарегистрировать вызовом Raphael.registerFont(). Возникает вопрос: откуда взять сам шрифт для регистрации? Ответ - его нужно куфонизировать из обычного ttf-шрифта (или otf и пр.), т.е. выполнить преобразование глифов шрифта в svg-шные path-ы. Сделать это можно с помощью онлайн-приложения http://cufon.shoqolate.com/generate/. Получаемый на выходе js-файл нужно немного подправить, заменив в нем объект Cufon, в котором регистрируется шрифт, на Raphael. После подключения данной js-ки шрифт можно использовать в getFont().

среда, 9 апреля 2014 г.

Wavemaker 6.5.3: аутентификация по Active Directory с использованием sAMAccountName

Проблема

Реализовать аутентификацию по Active Directory в приложении, построенном на Wavemaker 6.5.3, c использованием в качестве логина sAMAccountName.

Решение 

Через UI настройек безопасности поиск по sAMAccountName не организовать, т.к. там единственный вариант поиска пользователя - это userDnPattern:


Нам же нужно задать не шаблон для DN, а поиск по атрибуту sAMAccountName. Выход - идем Source -> Resources, в Folder Shortcuts выбираем "Project", там открываем файл WEB-INF/project-security.xml. В нем добавляем бин:
<bean id="userSearch"
       class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">
   <constructor-arg index="0">
     <value>OU=Users</value>
   </constructor-arg>
   <constructor-arg index="1">
     <value>(sAMAccountName={0})</value>
   </constructor-arg>
   <constructor-arg index="2">
     <ref local="initialDirContextFactory"/>
   </constructor-arg>
   <property name="searchSubtree">
     <value>true</value>
   </property>
 </bean>
Первый аргумент конструктора нужно поправить в соответствие с базовым узлом для поиска по sAMAccountName. Базовый узел указывается относительно указанного в URL-е LDAP (в моем случае - относительно DC=my,DC=domain).
Далее необходимо исправить первый аргумент конструктора бина ldapAuthProvider с:
<constructor-arg>
<bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg>
<ref local="initialDirContextFactory"/>
</constructor-arg>
<property name="userDnPatterns">
<list>
<value>cn={0},ou=Users</value>
</list>
</property>
</bean>
</constructor-arg>
на 
<constructor-arg>
<bean class="org.acegisecurity.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg>
<ref local="initialDirContextFactory"/>
</constructor-arg>
<property name="userSearch">
<ref bean="userSearch"/>
</property>
</bean>
</constructor-arg>
Все, можно заходить в приложение по  sAMAccountName и паролю из AD.

PS Спасибо http://dev.wavemaker.com/forums/?q=node/7096

воскресенье, 6 апреля 2014 г.

Microsoft Word: не сохраняются горячие клавиши

Проблема

В Win Word 2010 перестали работать Ctrl-комбинации (Ctrl+C, Ctrl+V и пр.). Если зайти в Options --> Customize Ribbon --> Keyboard Shortcuts: Customize, и настроить их заново (для Ctrl+C и Ctrl+V, например, соотв. комманды называются EditCopy и EditPaste), то комбинации клавиш начинают работать, но до следующего перезапуска Word.

Причина

Куда-то пропал Normal.dotm из C:\Users\<XXX>\AppData\Roaming\Microsoft\Templates. А ведь все комбинации клавиш сохраняются именно туда (это видно в окне настройки комбинаций, где помимо Normal.dotm можно также выбрать в качестве места для сохранения текущий документ):


Решение

Создать новый файл, в нем выполнить настройку горячих клавиш, сохраняя изменения не в Normal.dotm, а в текущем документе. Сохранить документ как Normal.dotm в папке C:\Users\<XXX>\AppData\Roaming\Microsoft\Templates. 


среда, 26 марта 2014 г.

AxisFault: The system cannot infer the transport information from the vfs:file: ...

Проблема

WSO2 ESB 4.5.1. При попытке отправить сообщение на Endpoint с URL вида "vfs:file://..." в лог валится ошибка:
ERROR - Axis2Sender Unexpected error during sending message out
org.apache.axis2.AxisFault: The system cannot infer the transport
information from the vfs:file://...

Причина

В %WSO2_HOME%/repository/conf/axis2/axis2.xml не включен vfs-transportSender.

Решение

Раскомментировать:
<transportSender name="vfs" class="org.apache.synapse.transport.vfs.VFSTransportSender"/>

axis2 1.6.2 на weblogic и "Weblogic's StAX implementation is unsupported and some Axiom features will not work as expected! Please use Woodstox instead"

Проблема

Приложение, публикующее веб-сервис, построенный на axis2 (версия 1.6.2) отлично работает на Tomcat, однако на Weblogic выдает некорректный xml в ответ на запросы, например:
<ns1:Response xmlns:ns1="http://my.ns/get">
     <ns1:http://my.ns/get extension="pdf">
          <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:1.339fa79a76e9c28c028457f6d5d2336291c1c2c768ddde02@apache.org"></xop:Include>
     </ns1:http://my.ns/get>
</ns1:Response>
Т.е. вместо наименования тега (это должен был быть тег "Content") почему-то идет URL пространства имен.
При этом при старте приложения в лог пишется настораживающее:
Weblogic's StAX implementation is unsupported and some Axiom features will not work as expected! Please use Woodstox instead.
Решение

В weblogic.xml указать:
<weblogic-web-app>
 <container-descriptor>
    <prefer-web-inf-classes>true</prefer-web-inf-classes>
  </container-descriptor>
</weblogic-web-app> 
Также нужно убедиться в наличии в библиотеках приложения xercesImp и xml-apis.

вторник, 25 марта 2014 г.

Weblogic: password-encrypted в конфиге jdbc-data-source и ошибка "Could not perform unpadding: invalid pad byte"

Проблема:

Есть некий EAR-ник, содержащий jdbc-data-source. В нем пароль задан с помощью password-encrypted:
<password-encrypted>{AES}q+rhp78+7777woah7777JW7777S+0p7777djmw7777c=</password-encrypted>
При старте приложения в лог валится ошибка:
####<Mar 19, 2014 4:44:21 PM MSK> <Error> <Console> <xxx> <AdminServer> <[ACTIVE] ExecuteThread: '21' for queue: 'weblogic.kernel.Default (self-tuning)'> <weblogic> <> <> <1395233061606> <BEA-240003> <Console encountered the following error weblogic.application.WrappedDeploymentException: Could not perform unpadding: invalid pad byte.
at com.rsa.jsafe.c.a(Unknown Source)
at com.rsa.jsafe.JSAFE_SymmetricCipher.decryptFinal(Unknown Source)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptBytes(JSafeEncryptionServiceImpl.java:124)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptString(JSafeEncryptionServiceImpl.java:184)
at weblogic.security.internal.encryption.ClearOrEncryptedService.decrypt(ClearOrEncryptedService.java:96)
at sun.reflect.GeneratedMethodAccessor378.invoke(Unknown Source)
... at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer$1.run(DeploymentReceiverCallbackDeliverer.java:46)
at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:528)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)
При этом само приложение не стартует.

Причина


Конфиг datasource'а был перевезен с другого инстанса weblogic (соответственно, и сам зашифрованный пароль был создан именно для того инстанса). Как оказалось, шифрование пароля привязано к домену сервера Weblogic (о чем, кстати, и сказано в документации: http://docs.oracle.com/cd/E11035_01/wls100/admin_ref/utils.html#encrypt). Так что при копировании конфигурации в другой домен Weblogic требуется повторить процедуру шифрования пароля (как это делается, я писал тут: http://barbitoff.blogspot.ru/2013/11/weblogic-datasource.html).

суббота, 1 марта 2014 г.

jQuery: как в обработчике события отличить "реальное" событие от программно симулированного

Задача

В обработчике события (например, change) отличить "реальное" событие (вызванное пользовательским вводом) от программно симулированного (в случае с change-событием - вызовом метода change() для элемента).

Решение
$("input").change(function(ev) {
     if(ev.hasOwnProperty("originalEvent")) {
          // "реальное" событие
     }
     else {
          // симулированное
     }

JavaScript: расчет контрольной цифры штрихкода EAN-8

Стандарт EAN-8 предусматривает 7 значащих цифр и 8ую цифру, являющуюся контрольной суммой первых 7. Задача - рассчитать для имеющихся 7 цифр 8ую (а также - сгенерировать 100 последовательных штрихкодов):
function ean8(eanCode) {
even = Number(eanCode.charAt(1)) +
      Number(eanCode.charAt(3)) +
      Number(eanCode.charAt(5));
odd = Number(eanCode.charAt(0)) +
     Number(eanCode.charAt(2)) +
     Number(eanCode.charAt(4)) +
     Number(eanCode.charAt(6)) ;
total = 3 * odd + even;
total = total % 10;
total = 10 - total;
total = total % 10;
return eanCode+total;
}
for(var i = 1000000; i<1000100; i++) {
console.debug(ean8(String(i)));
}

четверг, 27 февраля 2014 г.

Google Drive и Git: ошибка "fatal: Reference has invalid format: 'refs/heads/master (Конфликт 1)'"

Проблема

Использую Google Drive для хранения git-репозитория. При очередной попытке сделать из него Fetch получаю ошибку:
fatal: Reference has invalid format: 'refs/heads/master (Конфликт 1)'
Решение

Почему именно при синхронизации с гуглодиском возник конфликт, не знаю, но решение простое - удалить из refs/heads/master репозитория на Google Drive файл, на который ругается git.

вторник, 25 февраля 2014 г.

jQuery: очередь ajax-запросов

Задача:

Ajax-запросы, выполняемые с помощью jQuery, выполнять по одному и в строгой последовательности.

Решение:

Помнится, когда-то давно, когда стояла аналогичная задача с использованием YUI2, я писал очередь сам. Теперь же мне стало лень, и я, после недолгих поисков, нашел готовое решение: https://github.com/Foliotek/ajaxq. Просто, элегантно. Мне правда не хватило 2 вещей: ограничения на максимальную длину очереди и возможности вызвать hook непосредственно перед отправкой очередного запроса (для актуализации его полезной нагрузки), но это оказалось несложно допилить руками. Будет время - форкну проект на гитхабе и выложу свои доработки в общий доступ.

воскресенье, 23 февраля 2014 г.

Javascript: обработка клика на disabled-кноках

Обрабатывать клики на кнопках, сделанных недоступными посредством атрибута "disabled" нельзя. Единственный выход из ситуации - делать кнопки недоступными посредством некоторого собственного css-класса, выполнив эмуляцию (с помощью стилей и javascript-обработчиков) работы атрибута "disabled".

среда, 12 февраля 2014 г.

cmd: найти в подпапке и скопировать файл по фрагменту имени

Задача

Найти файл, лежащий в одной из подпапок текущей папки, и скопировать его в заданную папку.

Решение
for /f "tokens=*" %%a in ('Dir /b/s/a-d *<search>*') Do copy "%%a" C:\Temp
, где <search> - искомый фрагмент имени файла. Целевой папкой копирования здесь является C:\Temp.

Excel: поиск значения ячейки в некотором столбце

Задача

Есть некий массив значений, размещенный в столбце "А" листа "1". Есть другой массив значений, размещенный в столбце "D" листа "2". Необходимо на листе "1" в столбце "B" проставить флаг, есть ли соотв. значение из столбца "А" листа "1" в столбце "D" листа "2".

Решение

Формула для ячейки"B1" листа "1" будет следующая:
=IF(IFERROR(MATCH(А1;'2'!D:D;0);0)=0;0;1)
В ячейке будет стоять "0", если значение из ячейки А1 отсутствует в столбце D листа "2" и "1" в противном случае.

среда, 5 февраля 2014 г.

Ошибка "com.documentum.web.form.control.TagPoolingEnabledException: JSP tag pooling is not supported..." при старте webtop-based приложения на Tomcat 7

Проблема
При старте на Tomcat 7 приложения, построенного на базе webtop, валится ошибка:
com.documentum.web.form.control.TagPoolingEnabledException: JSP tag pooling is not supported. Please refer to the product deployment guide for instructions on turning off tag pooling for the application server
Решение
В conf/web.xml томката добавить следующие строки (выделены жирным):
<servlet>
   <servlet-name>jsp</servlet-name>
   <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
   <init-param>
      <param-name>fork</param-name>
      <param-value>false</param-value>
   </init-param>
   <init-param>
      <param-name>xpoweredBy</param-name>
      <param-value>false</param-value>
   </init-param>
   <init-param>
      <param-name>mappedfile</param-name>
      <param-value>true</param-value>
   </init-param>
   <init-param>
      <param-name>enablePooling</param-name>
      <param-value>false</param-value>
   </init-param>
   <load-on-startup>3</load-on-startup>
</servlet>
Также, возможно, потребуется очистить каталог /work/Catalina/localhost томката.

JavaMail: кодировка по-умолчанию, используемая в заголовках писем

Вообще, не-ascii заголовки в почтовых сообщениях кодируются в соответствии с RFC 2047 (http://www.faqs.org/rfcs/rfc2047/). При отправке почты с помощью Javamail столкнулся со следующей проблемой: формируется заголовок письма, имеющий вид:
=?UTF8?B?0J3QsNC/0YDQsNCy0LvQtdC9INC00L7QutGD0LzQtdC9?= =?UTF8?B?0YI6INC+0YjQuNCx0LrQuCDQsiBlbWFpbA==?=
Не совсем корректным здесь является имя используемой кодировки - "UTF8", в то время как IANA предписывает использовать имя "UTF-8", т.е. с дефисом (http://www.iana.org/assignments/character-sets/character-sets.xhtml). Такие заголовки "съедаются" Outlook'ом, веб-клиентами mail.ru и gmail.com, однако, например, SquirrelMail выводит такой заголовок "как есть", не выполняя декодирование. 
Для установки заголовка мой код (вернее не мой, а код open-source проекта, но не суть) испольует javax.​mail.​internet.​MimeMessage.setSubject(java.lang.String subject). В документации сказано, что данный метод использует "platform's default charset" (http://docs.oracle.com/javaee/6/api/javax/mail/internet/MimeMessage.html#setSubject(java.lang.String)), по факту - системное свойство file.encoding.
Посмотрев в стартовые скрипты приложения, я обнаружил, что там действительно указана опция jvm "-Dfile.encoding=UTF8". Поменяв ее на "-Dfile.encoding=UTF-8" я решил проблему с некорректным именем кодировки в заголовках отправляемых почтовых сообщений.

воскресенье, 26 января 2014 г.

Pentaho: подключение к БД Oracle по Service Name

При создании "Database connection" в Pentaho при выборе СУБД Oracle нет возможности выбрать, как подключаться к БД - по SID или по Service Name. Есть только единственное поле - "Database". При этом, если ввести в него просто значение Service Name, на некоторых серверах подключение проходит успешно, тогда как на других приводит к ошибке:
2014/01/25 20:06:27 - ERROR (version 4.4.0-stable, build 17588 from 2012-11-21 16.02.21 by buildguy) : Error connecting to database: (using class oracle.jdbc.driver.OracleDriver)
2014/01/25 20:06:27 - ERROR (version 4.4.0-stable, build 17588 from 2012-11-21 16.02.21 by buildguy) : Listener refused the connection with the following error:ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
Из текста ошибки видно, что СУБД считает, что подключение ведется по SID, а не по Service Name. Почему ошибка возникает лишь на некоторых серверах - не знаю, видимо это зависит от каких-то настроек на стороне сервера.
Почему СУБД считает, что подключение ведется именно по SID, понятно: форматы JDBC-URL'а при подключении по SID и по Service Name различаются. Для SID URL выглядит так (используется thin-драйвер):
jdbc:oracle:thin:@server:1521:mysid
, а для Service Name - так:
jdbc:oracle:thin:@server:1521/myservicename
Pentaho использует первый формат, что и ведет к ошибке. Однако, не все так плохо: если указать в начале значения поля "Database" прямой слеш (перед значением Service Name) подключение проходит успешно. Спасибо http://forums.pentaho.com/archive/index.php/t-87866.html?s=57295456a6292b611f3e46e3fa0ea7d6.

суббота, 25 января 2014 г.

Как я сдавал 1Z0-897 "Oracle Certified Expert, Java EE 6 Web Services Developer"

Сразу оговорюсь, сдал я не особо - 68% при проходном 64%. Сказалась, как обычно, нехватка времени на подготовку, да еще и отсутствие в свободном доступе внятной информации о том, что конкретно будет на экзамене, а также более ли менее близких к составу экзаменационных вопросов книг и mock-экзаменов.
Собственно на подготовку ушла ровно неделя, точнее целиком я готовился только 2 выходных дня, а в остальные 5 дней в среднем по 3-4 часа. Опыт в разработке SOAP веб-сервисов у меня около 2 лет, но на момент начала подготовки я не мог похвастаться особо глубокими знаниями JAX-WS, т.к. разрабатываемые мной веб-сервисы в основном были достаточно тривиальными, и я довольствовался "обязательным минимумом" знаний. Что такое XML Schema и WSDL я знал, но в последнем также не был большим знатоком. REST же для меня был вообще практически новым словом, что это такое, я конечно представлял, но на практике никогда применять не приходилось. Собственно это все и стало предпосылкой к сдаче экзамена, т.к. экзамен - отличный повод "прибраться" в своих знаниях, систематизировать их, а также узнать что-то новое, что потом можно использовать на практике.
При подготовке я в основном ориентировался на содержимое вот этой странички на код-ранче: http://www.coderanch.com/how-to/java/ScdjwsLinks, поэтому первое, с чего я начал подготовку - прочитал книжку "Java Web Services: Up and Running" под авторством Martin Kalin (2009). Книжка по объему достаточно скромная - всего 318 страниц (+ некоторые разделы, например про историю веб-сервисов, можно смело пропускать), поэтому осилить ее можно достаточно быстро. По ходу чтения делал заметки, чтобы перед экзаменом была возможность быстро освежить в памяти полученные из нее знания. Из книги узнал для себя много нового, многие вещи, казавшиеся раньше загадочными, теперь стали очевидными. Не могу сказать, что книга дает исчерпывающие значения по теме, но она определенно показывает, в какую сторону копать при наличии той или иной задачи. Сказать, что этой книги достаточно для успешной сдачи экзамена, тоже с полной уверенностью нельзя. Но об этом немного позже.
После прочтения книги у меня закрались сомнения в том, что полученных знаний хватит для получения сертификата, и я начал судорожно искать, где бы еще что-нибудь почитать по теме. Для начала просмотрел вот этот гайд: http://java.boot.by/ocewsd6-guide/, - там многое пересекается с книгой (даже возникает впечатление, что оно оттуда и скопировано), но в тоже время есть и новая информация, в частности, по REST и JAX-RS. Чтобы окончательно удостовериться в том, что полученные мной знания по REST и JAX-RS достаточно полны, я также прочитал статью на сайте IBM: http://www.ibm.com/developerworks/ru/library/wa-jaxrs/.
В довершение, уже вечером перед экзамен, я пробежался по тестам тут:  http://www.examclouds.com/ (в разделе "WS Quiz"). Тесты меня несколько испугали, т.к. ответы на многие вопросы я не знал. Но как оказалось, это и не нужно - на экзамене ничего подобного не было.
Собственно вот и вся подготовка. Выспаться перед экзаменом не получилось, но свежесваренный кофе сделал свое дело =)
Сдавал я в Unix Education Center, там же, где 10 месяцами ранее я экзаменовался на OCJP. На экзамен дается 1.5 часа, вопросов в тесте - 60. В общем-то, расслабляться нельзя, времени не много. Я успел ответить на все вопросы за 1:15, потом просмотрел еще раз те вопросы, по которым были сомнения. Была пара вопросов, отображавшихся некорректно из-за того видимо, что xml, входящий в текст вопроса, забыли экранировать, и он попросту не показывался. Написал жалобу в pearsonvue, через которых заказывал экзамен, обещали разобраться.
Теперь про вопросы на экзамене. Их уровень не запредельный, обойтись одной только книжкой "Java Web Services: Up and Running" было бы сложно, но в целом, запомни я все прочитанное получше, сдать можно было бы на более высокий балл. Единственная тема, к которой я был совершенно не готов (а на которую, однако, было не менее 4-5 вопросов) - это WS-I.

четверг, 9 января 2014 г.

Wavemaker 6.5.3: отображение колонок из связанных объектов в DojoGrid

Чтобы колонки из связанных объектов были доступны для отображения в DojoGrid, необходимо отметить галочкой поле, соответствующее связи, в настройках соответствующего LiveVariable:



При создании grid-а путем перетаскивания на страницу соответствующего объекта из "Database Widgets" галочки рядом с полями-связями по-умолчанию сняты!

Wavemaker: возврат кнопки к "ненажатому" состоянию

Задача

В обработчике клика по кнопке сделать, чтобы кнопка перестала быть "нажатой" (что выражается в затемнении ее фона):


Решение

Для этого нужно убрать с кнопки фокус вызовом:
this.myButton.domNode.blur();

WaveMaker 6.5.3: загрузка страницы из JavaScript

app.loadPage("myPageName");