barbitoff programmer`s blog

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

пятница, 28 августа 2015 г.

КриптоПРО JCP 1.0.54 и JDK 1.7.0_71: java.util.MissingResourceException: Can't find ru.CryptoPro.JCP.tools.resources.logger bundle

Проблема

Пытаюсь установить КриптоПРО JCP 1.0.54 на JDK 1.7.0_71, получаю ошибку:
...
Executing commands:
java.lang.ExceptionInInitializerError
        at ru.CryptoPro.JCP.Digest.GostDigest.reset(Unknown Source)
        at ru.CryptoPro.JCP.Digest.GostDigest.a(Unknown Source)
        at ru.CryptoPro.JCP.Digest.GostDigest.<init>(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.a(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.a(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.b(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.c(Unknown Source)
        at ru.CryptoPro.JCP.tools.AbstractLicense.<init>(Unknown Source)
        at ru.CryptoPro.JCP.tools.License.<init>(Unknown Source)
        at ru.CryptoPro.JCP.Install.JCPInstaller.a(Unknown Source)
        at ru.CryptoPro.JCP.Install.JCPInstaller.parseArgs(Unknown Source)
        at ru.CryptoPro.Install.f.a(Unknown Source)
        at ru.CryptoPro.Install.ShellInstaller.h(Unknown Source)
        at ru.CryptoPro.Install.ShellInstaller.makeAction(Unknown Source)
        at ru.CryptoPro.Install.ShellInstaller.makeActionNoEx(Unknown Source)
        at ru.CryptoPro.Install.VariantTwo.main(Unknown Source)
Caused by: java.util.MissingResourceException: Can't find ru.CryptoPro.JCP.tools.resources.logger bundle
        at java.util.logging.Logger.setupResourceInfo(Logger.java:1537)
        at java.util.logging.Logger.<init>(Logger.java:267)
        at java.util.logging.Logger.<init>(Logger.java:261)
        at ru.CryptoPro.JCP.tools.JCPLogger.<init>(Unknown Source)
        at ru.CryptoPro.JCP.tools.JCPLogger.<clinit>(Unknown Source)
        ... 16 more
Install failed
---- Script ERROR
Решение

Установка сертифицированных версий JCP (последняя на данный момент - 1.0.54) возможна на версии JDK до 1.7.0_25, о чем и сказано на странице продукта в разделе "Системные требования". Причем, судя по всему, не включительно, т.к. на 25-ой наблюдается та же проблема. Установить удалось только на 1.7.0_21.
Т.е. либо даунгрэйдим JDK, либо отказываемся от сертифицированной версии в пользу несертифицированной.

среда, 26 августа 2015 г.

WSO2 ESB: установка Correlation ID сообщения при отправке в JMS

Задача

При помещении сообщения в JMS из прокси-сервиса (медиатором <send/>) необходимо установить JMS-свойство "Correlation ID".

Решение

<property name="JMS_COORELATION_ID" value="****" scope="axis2" />

Да, именно так, через два "O" и одно "R" (http://axis.apache.org/axis2/java/core/api/org/apache/axis2/Constants.html).

четверг, 13 августа 2015 г.

пятница, 7 августа 2015 г.

WSO2 ESB: установка таймаута ответа при двухстороннем взаимодействии через JMS

Сценарий

Есть двухсторонний HTTP-to-JMS прокси-сервис, т.е. сервис, который:

  1. Принимает запрос по HTTP
  2. Помещает его в JMS-очередь queue1
  3. Ожидает ответа в JMS-очереди queue2
  4. Отправляет принятый ответ в виде HTTP-ответа
Логично, что между шагами 2 и 3 может пройти сколь угодно большой период времени. Необходимо задать величину таймаута, после которого проски-сервис будет сваливаться в faultSequence.

Решение

Обычный таймауты endpoint-ов тут не работают: WSO2 ESB их игнорирует и использует значение таймаута сокета из глобальных настроек. Однако, есть специальное свойство JMS_WAIT_REPLY:
<endpoint>
<address statistics="disable" trace="disable" uri="jms:/...">
<timeout>
<duration>0</duration>
<responseAction>fault</responseAction>
</timeout>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
<retryDelay>0</retryDelay>
</markForSuspension>
<suspendOnFailure>
<initialDuration>0</initialDuration>
<maximumDuration>0</maximumDuration>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
</address>
<property name="JMS_WAIT_REPLY" value="5000" scope="axis2"/>
</endpoint>
В примере выше таймаут ожидания ответа установлен в 5 секунд.

среда, 5 августа 2015 г.

WSO2 ESB и IBM WebSphere MQ: "Имя свойства 'Content-Type' не является верным идентификатором Java(tm)"

Сделал простейший прокси-сервис HTTP-> JMS (в качестве JMS-провайдера используется IBM WebSphere MQ 7.5), при его вызове получаю ошибку в логах:
TID: [0] [ESB] [2015-08-05 13:10:28,219] ERROR {org.apache.axis2.transport.jms.JMSSender} -  Error creating a JMS message from the message context {org.apache.axis2.transport.jms.JMSSender}
com.ibm.msg.client.jms.DetailedMessageFormatException: JMSCC0049: Имя свойства 'Content-Type' не является верным идентификатором Java(tm).
Указанное имя свойства не соответствует разрешенному формату, описанному в спецификации JMS.
Причина в том, что с точки зрения спецификации JMS имя свойства не может содержать символов "-". WSO2 же пытается пробросить в качестве свойства JMS-сообщения пришедший во входящем вызове HTTP-заголовок. Решение:
<property action="remove" name="TRANSPORT_HEADERS" scope="axis2"/>
<property action="set" name="transport.jms.ContentTypeProperty" value="CONTENT_TYPE" scope="axis2"/>
В данном случае тип контента будет записан в JMS-свойство "CONTENT_TYPE".

вторник, 4 августа 2015 г.

JDK 1.6: баг при передаче unicode-символов с использованием Runtime.exec()

В JDK 6 имеется баг, поправленный только в 7ой версии, связанный с передачей unicode-символов при вызове Runtime.exec(). Например, т.н. "правые двойные кавычки" при таком вызове превращаются в обычные прямые двойные кавычки (хотя бывают и более неприятные кейсы, когда вызов вообще падает с Exception-ом).
Благо, для проблемы есть workaround, основанный на замене Runtime.exec() на использование ProcessBuilder. Ниже приведен пример вызова, взятый со stackoverflow:
String[] cmd = new String[]{"yourcmd.exe", "some argument with unicode characters"};      
Map<String, String> newEnv = new HashMap<String, String>();
newEnv.putAll(System.getenv());
String[] i18n = new String[cmd.length + 2];
i18n[0] = "cmd";
i18n[1] = "/C";
i18n[2] = cmd[0];
for (int counter = 1; counter < cmd.length; counter++)
{
    String envName = "JENV_" + counter;
    i18n[counter + 2] = "%" + envName + "%";
    newEnv.put(envName, cmd[counter]);
}
cmd = i18n;
ProcessBuilder pb = new ProcessBuilder(cmd);
Map<String, String> env = pb.environment();
env.putAll(newEnv);
final Process p = pb.start();

WSO2 ESB 4.8.1 + IBM WebSphere MQ 7.5: "Unable to continue server startup as it seems the JMS Provider is not yetstarted. Please start the JMS provider now"

Проблема

Настроил взаимодействие WSO2 ESB 4.8.1 и IBM WebSphere MQ 7.5, следуя примеру https://docs.wso2.com/display/ESB481/Configure+with+IBM+WebSphere+MQ. Пришлось немного отступить в части библиотек, т.к. состав библиотек, поставляемых с MQ 7.5 несколько отличается от приведенного в примере. В моем случае я поместил в %WSO2_HOME%/repository/components/lib следующие библиотеки, взяв их из /java/lib директории установки MQ:
  • fscontext.jar
  • providerutil.jar
  • com.ibm.mqjms.jar
  • com.ibm.mq.jmqi.jar
После этого шина стала успешно стартовать, инициализируя JMSSender и JMSReceiver. Однако, при попытке задеплоить прокси-сервис, слушающий JMS-очередь, я получал в логе:

[2015-08-04 12:27:55,477] ERROR - JMSListener Unable to continue server startup as it seems the JMS Provider is not yetstarted. Please start the JMS provider now.
[2015-08-04 12:27:55,480] ERROR - JMSListener Connection attempt : 1 for JMS Provider failed. Next retry in 20 seconds
[2015-08-04 12:28:15,505] ERROR - JMSListener Unable to continue server startup as it seems the JMS Provider is not yet
started. Please start the JMS provider now.
[2015-08-04 12:28:15,508] ERROR - JMSListener Connection attempt : 2 for JMS Provider failed. Next retry in 40 seconds
[2015-08-04 12:28:55,538] ERROR - JMSListener Unable to continue server startup as it seems the JMS Provider is not yet
started. Please start the JMS provider now.
[2015-08-04 12:28:55,543] ERROR - JMSListener Connection attempt : 3 for JMS Provider failed. Next retry in 80 seconds
...
Решение

Удалить библиотеки com.ibm.mqjms.jar и com.ibm.mq,jmqi.jar из components/lib (а также из components/dropins, куда их скопировала шина при установке). Далее я скопировал все содержимое папки /java/lib с машины MQ в папку %WSO2_HOME%/mq, после чего добавил в стартовый скрипт wso2 (wso2server.bat для Win) следующие строки:
rem --- FOR IBM MQ
set CARBON_CLASSPATH=.\mq\com.ibm.mq.jar;.\mq\com.ibm.mqjms.jar;.\mq\com.ibm.mq.jmqi.jar;%CARBON_CLASSPATH%

после строчки set CARBON_CLASSPATH=.\lib;%CARBON_CLASSPATH%. 
Прокси-сервис, слушающий JMS-очередь, заработал.