barbitoff programmer`s blog

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

воскресенье, 27 декабря 2015 г.

SLES и birt: русские буквы в pdf

Проблема

Есть SLES, на нем установлен Tomcat, на котором крутится Birt Report Viewer. На последнем задеплоен отчет, используемый для генерации pdf-файлов, содержащих русский текст. Проблема заключается в том, что русские символы в отчете выгружаются моноширинным шрифтом, причем вне зависимости от того, какой шрифт указан в самом отчете (Calibri, Arial или просто sans-serif).

Решение

Устанавливаем пакет msttcorefonts (http://software.opensuse.org/download.html?project=home%3Acsa7fff%3Aadei&package=msttcorefonts), он распакует в /usr/share/fonts/msttcorefonts некоторый набор TrueType-шрифтов. 
Следующая задача - указать Birt'у на эту папку. Делается это путем правки файла WEB-INF/lib/org.eclipse.birt.runtime_4.5.0.jar/fontsConfig.xml. Этот файл содержит блок <font-paths> с перечнем путей, по которым birt ищет шрифты. Все имеющиеся там записи можно удалить, и добавить одну новую:
<path path="/usr/share/fonts/msttcorefonts" />
Вуаля, шрифты, которые есть в папке /usr/share/fonts/msttcorefonts, можно использовать в отчетах.
ЗЫ Вообще, в файлах fontsConfig.xml, fontsConfig_pdf.xml и fontsConfig_linux.xml есть и другие настройки, которые могут оказаться полезными: например, можно выбрать, какой шрифт будет использоваться при указании семейства "serif", указать fallback-шрифт, используемый, когда для символа невозможно найти глиф в указанном шрифте (<composite-font name="all-fonts"  ... />) и пр.

Birt Report Viewer: логирование

Чтобы получить максимальный уровень логирования для Birt Report Viewer'а, необходимо в его web.xml задать значение параметра BIRT_VIEWER_LOG_LEVEL равным FINEST:
<context-param>
<param-name>BIRT_VIEWER_LOG_LEVEL</param-name>
<param-value>FINEST</param-value>
</context-param>
Логи пишутся в папку log корня развертывания веб-приложения. 

пятница, 25 декабря 2015 г.

WSO2 ESB 4.9.0: пропадает контент бинарного узла при его создании с помощью ByteArrayInputStream + org.apache.axis2.builder.unknowncontent.InputStreamDataSource

Проблема

Некий кастомный Java-медиатор создает бинарный XML-узел, наполняя его из массива байт byte[], используя ByteArrayInputStream и org.apache.axis2.builder.unknowncontent.InputStreamDataSource:
ByteArrayInputStream stream = new ByteArrayInputStream(myBytes);
DataSource ds = new InputStreamDataSource(stream);
DataHandler dataHandler = new DataHandler(ds);
OMText binaryNode = factory.createOMText(dataHandler, true);
При этом созданный узел ведет себя крайне странно: если попробовать 2 раза подряд залогировать созданный XML, в первый раз он логируется корректно (бинарный узел логируется base64-кодированным), а при повторном логировании оказывается, что бинарный узел уже пуст.

Решение

Особо не разбирался, реализовал создание DataSource напрямую из массива байт:
DataSource ds = new org.apache.axiom.attachments.ByteArrayDataSource(myBytes);

четверг, 24 декабря 2015 г.

WSO2 ESB 4.9.0: при отправке запроса теряются WS-Addressing заголовки

Проблема

Прокси-сервис устанавливает WS-Addressing заголовки, но при отправке запроса на конечный веб-сервис они теряются, запрос на веб-сервис приходит уже без них.

Решение

Решается проблема установкой соответствующего свойства контекста:
<property name="PRESERVE_WS_ADDRESSING" value="true"/>

среда, 23 декабря 2015 г.

WSO2 ESB 4.9.0: ошибка "Name cannot contain any special characters other than hyphen (-) and underscore (_)" при создании Datasource

Проблема

Пытаюсь создать Datasource через веб-консоль WSO2 ESB 4.9.0, при попытке проверки соединения ("Test connection") получаю ошибку:
Name cannot contain any special characters other than hyphen (-) and underscore (_)
При этом имя датасорса не содержит никаких спецсимволов, только строчные латинские буквы.

Причина

Видимо, некорректный regexp для валидации поля "Name", до конца так и не понял, что именно ему не нравится, но знаю точно - если вместо строчных букв использовать заглавные - ошибка не возникает. Названия из строчных букв также иногда прокатывают, но не все (например, если в названии есть буква "s" - то ошибка гарантирована). Нашел похожую багу, заведенную на WSO2 Data Analytics Server: https://wso2.org/jira/browse/DAS-116, там, похоже, проблему поправили, а вот в ESB - нет. 

четверг, 3 декабря 2015 г.

Spring Tools Suite: ошибка "You need to run build with JDK or have tools.jar on the classpath..." при просмотре pom-ки

Проблема

При открытии в Spring Tools Suite pom-ки проекта вверху отображается ошибка:
You need to run build with JDK or have tools.jar on the classpath...
Причина

STS запущен из-под java из jre, а не JDK.

Решение

Поправить PATH системы таким образом, чтобы java бралась из JDK, а не из JRE. 

PostgreSQL: ERROR: could not open extension control file "/usr/pgsql-9.4/share/extension/uuid-ossp.control": No such file or directory

Проблема

Есть PostgreSQL-сервер на Linux'е. Пытаюсь установить расширение uuid-ossp SQL-запросом:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
Получаю ошибку:
ERROR:  could not open extension control file "/usr/pgsql-9.4/share/extension/uuid-ossp.control": No such file or directory
Решение

Не установлен пакет postgresql-contrib, необходимо установить его. Например, для deb-системы с apt-ом:
apt-get install postgresql-contrib

суббота, 21 ноября 2015 г.

git: сохранение данных аутентификации для текущего пользователя

Чтобы логин/пароль для доступа к репозиториям git не запрашивались каждый раз, необходимо выполнить:
git config credential.helper store
После этого однажды введенный логин/пароль будет сохранен в незащищенном виде в файле .git-credentials в домашней папке пользователя. При повторном обращении к данному репозиторию логин/пароль будет браться оттуда.

четверг, 5 ноября 2015 г.

Tomcat 8.0.28 и Netbeans 8.0.2: "The syntax of the command is incorrect"

Проблема

Пытаюсь запустить Tomcat 8.0.28 из-под Netbeans 8.0.2 (под Win), получаю ошибку:
The syntax of the command is incorrect.
Решение

Открываем Catalina.bat, ищем следующие строки:
:noJuliConfig
set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%"
:noJuliManager
set "JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%" 
Удаляем из них двойные кавычки. Радуемся =)

понедельник, 2 ноября 2015 г.

пятница, 11 сентября 2015 г.

AvastVBoxSVC.exe и самопроизвольный выход Windows из ждущего режима

Снова к вопросу о самопроизвольном выходе винды и ждущего режима. Вывод "powercfg -lastwake" указал на некий AvastVBoxSVC.exe, что очевидно является частью антивируса avast! Для того, чтобы этот exe-шник перестал будить компьютер, нужно зайти в Панель управления -> Программы и компоненты, найти там аваст, нажать "Изменить", и удалить "Безопасные виртуальные машины" (если, конечно, этот компонента аваста Вам реально не нужен).

четверг, 10 сентября 2015 г.

YouTube Data API v3: ошибка "YouTubeSignUpRequired" при попытке загрузки видео

Проблема

Пытаюсь загрузить видео на Youtube с использованием YouTube Data API v3 (пока что просто с помощью curl), получаю ответ:
< HTTP/1.1 401 Unauthorized
< Vary: X-Origin
< WWW-Authenticate: Bearer realm="https://accounts.google.com/", error=invalid_token
< Content-Type: application/json; charset=UTF-8
< Date: Thu, 10 Sep 2015 16:57:36 GMT
< Expires: Thu, 10 Sep 2015 16:57:36 GMT
< Cache-Control: private, max-age=0
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< Server: GSE
< Alternate-Protocol: 443:quic,p=1
< Alt-Svc: quic=":443"; p="1"; ma=604800
< Accept-Ranges: none
< Vary: Origin,Accept-Encoding
< Transfer-Encoding: chunked
<
{
 "error": {
  "errors": [
   {
    "domain": "youtube.header",
    "reason": "youtubeSignupRequired",
    "message": "Unauthorized",
    "locationType": "header",
    "location": "Authorization"
   }
  ],
  "code": 401,
  "message": "Unauthorized"
 }
}
При этом с тем же самым токеном другие операции (получение списка подписок, получение списка видео и пр.) работают без проблем, т.е. проблема явно не в токене. 

Решение

У пользователя, которому я хочу загрузить новое видео, еще не создан свой канал. Идем на Youtube через браузер, заходим в "Мой канал", Youtube предлагает создать канал. Соглашаемся. Пробуем еще раз загрузить видео через Data API - ошибка ушла.

среда, 9 сентября 2015 г.

JCP + ruToken: ошибка "java.io.IOException: Can't connect to Aktiv Co. ruToken 0"

Проблема

Используется JCP + ruToken для вычисления ЭЦП. При попытке получить ключ с токена падает ошибка:
Caused by: java.security.UnrecoverableKeyException: Can't connect to Aktiv Co. ruToken 0
at ru.CryptoPro.JCP.KeyStore.s.e(Unknown Source)
at ru.CryptoPro.JCP.KeyStore.ContainerStore.engineGetKey(Unknown Source)
at ru.CryptoPro.JCP.KeyStore.JCPKeyStore.engineGetKey(Unknown Source)
at java.security.KeyStore.getKey(KeyStore.java:792)
...
Caused by: java.io.IOException: Can't connect to Aktiv Co. ruToken 0
at rtjlib.JCP.RutokenReader.lock(Unknown Source)
at ru.CryptoPro.JCP.KeyStore.j.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at ru.CryptoPro.JCP.KeyStore.ContainerStore.a(Unknown Source)
Решение

Текст ошибки не особо содержателен, и по нему совершенно неочевидно, в чем именно проблема. Из того же JCP-шного ControlPane я великолепно вижу Aktiv Co. ruToken 0, включая ключ и сертификат на нем.
Декомпилируем rtjlib.JCP.RutokenReader (rtjlib.jar в jre/lib/ext того JDK, который используется для подписывания). Там IOException с таким текстом кидается в 2 местах, и если в одном он кидается просто в коде после неудачного коннекта, то вот во втором применен замечательный подход "проглатывания исключения":
try
    {
      arrayOfByte = nativeWinJavaReader.getAtr(str, "T=0|T=1");
    }
    catch (Exception localException1)
    {
      throw new IOException("Can't connect to " + str);
    }
Добавляем в бросаемое исключение исходный localException1:
    try
    {
      arrayOfByte = nativeWinJavaReader.getAtr(str, "T=0|T=1");
    }
    catch (Exception localException1)
    {
      throw new IOException("Can't connect to " + str, localException1);
    }
Перекомпилируем класс RutokenReader, подкладываем в целевой JDK. Получаем более развернутую ошибку:
Caused by: java.io.IOException: Can't connect to Aktiv Co. ruToken 0
at rtjlib.JCP.RutokenReader.lock(RutokenReader.java:38)
at ru.CryptoPro.JCP.KeyStore.j.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at ru.CryptoPro.JCP.KeyStore.ContainerStore.a(Unknown Source)
... 25 more
Caused by: java.lang.Exception: Establish context failed with 0x8010001d
at rtjlib.nativeAPI.SCardEstablishContext(Native Method)
at rtjlib.readerImpl.nativeWinJavaReader.getAtr(Unknown Source)
at rtjlib.JCP.RutokenReader.lock(RutokenReader.java:34)
... 28 more
Гуглим код 0x8010001d, узнаем, что расшифровывается он как "SCARD_E_NO_SERVICE - "The Smart card resource manager is not running." (http://blogs.msdn.com/b/alejacma/archive/2011/05/19/scardestablishcontext-fails-with-scard-e-no-service-error.aspx). Гугл же подсказывает и возможную причину: ошибка может быть вызвана нехваткой прав к событию "Global\Microsoft Smart Card Resource Manager Started". На это событие есть права только у интерактивных пользователей, SYSTEM и LOCAL SERVICE. В моем же случае ошибка падала в службе, запускающейся из-под обычного пользователя (но т.к. вход не интерактивный - прав не хватало). Запустили целевую программу в интерактивном режиме (из командной строки) вместо запуска в качестве службы - ошибка ушла. Пока такое решение устроило.

КриптоПРО JCP XMLDSig: java.lang.ClassCastException: content[0] is not a valid X509Data type

При попытки подписывания XML-документа с помощью КриптоПРО JCP падает ошибка:
java.lang.ClassCastException: content[0] is not a valid X509Data type
at ru.CryptoPro.JCPxml.dsig.internal.dom.DOMX509Data.<init>(DOMX509Data.java:68)
at ru.CryptoPro.JCPxml.dsig.internal.dom.DOMKeyInfoFactory.newX509Data(DOMKeyInfoFactory.java:88)
...
Причина - в моем случае был неверно указан keyAlias.

понедельник, 7 сентября 2015 г.

Maven: включение в OSGI-бандл распакованных зависимостей

Задача

Распаковать в собираемый OSGI-бандл некоторые зависимости.

Решение

У maven-bundle-plugin есть инструкция "Embed-Dependency", однако она включает указанные зависимости не распаковывая, т.е. кладет jar-ник внутрь jar-ника. Поэтому приходится использовать комбинацию плагина maven-dependency-plugin и инструкцию "Include-Resource" плагина maven-bundle-plugin:
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.10</version>
        <executions>
          <execution>
            <id>unpack-dependencies</id>
            <phase>package</phase>
            <goals>
              <goal>unpack-dependencies</goal>
            </goals>
            <configuration>
              <includeArtifactIds>saaj-impl,stax-ex,stax-api,mimepull</includeArtifactIds>
              <excludes>META-INF/**</excludes>
              <outputDirectory>${project.build.directory}/depsToPackIntoBundle</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>2.5.4</version>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Bundle-SymbolicName>**</Bundle-SymbolicName>
            <Bundle-Name>***</Bundle-Name>
            <Export-Package>***</Export-Package>
            <Fragment-Host>***</Fragment-Host>
            <Import-Package>***</Import-Package>
            <Private-Package>***</Private-Package>
            <Include-Resource>${project.build.directory}/depsToPackIntoBundle</Include-Resource>
          </instructions>        
        </configuration>
      </plugin>
В данном примере зависимости saaj-impl,stax-ex,stax-api,mimepul будут запакованы в OSGI-бандл, за исключением их директорий META-INF.

Настройки log4j для отладки формирования и валидации XMLDSig средствами КриптоПро JCP

log4j.logger.org.jcp.xml.dsig.internal=DEBUG
log4j.logger.com.sun.org.apache.xml.internal.security=DEBUG
log4j.logger.ru.CryptoPro.JCPxml.dsig.internal=DEBUG
log4j.logger.ru.CryptoPro.JCPxml.dsig.internal.dom=DEBUG
log4j.logger.ru.CryptoPro.JCP=DEBUG

Windows: как узнать причину выхода компьютера из ждущего режима

Столкнулся с достаточно раздражающей проблемой: домашний комп самопроизвольно выходит из ждущего режима. Встал вопрос: кто именно в этом виноват? И тут на помощь приходит powercfg:
powercfg -lastwake
покажет, кто разбудил ПК. 

воскресенье, 6 сентября 2015 г.

maven-bundle-plugin и включение в bundle классов, которые не экспортируются и не используются явно экспортируемыми классами

Проблема

Есть maven-проект, использующий maven-bundle-plugin для сборки OSGI-бандла. В этом проекте есть некий класс. Он не принадлежит экспортируемым из бандла пакетам, и явно не используется никаким экспортируемыми из бандла классами. В таком случае maven-bundle-plugin решает, что класс в бандле не нужен, и не включает его в бандл. Задача - включить класс в бандл.

Решение

Для этого пакет класса необходимо включить в Private-Package-блок конфигурации плагина:
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>1.4.0</version>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Bundle-SymbolicName>***</Bundle-SymbolicName>
            <Bundle-Name>***</Bundle-Name>
            <Export-Package>some.public.package</Export-Package>
            <Fragment-Host>***</Fragment-Host>
            <Import-Package>org.apache.ws.security.message,org.apache.axis2.saaj,*; resolution:=optional</Import-Package>
            <Private-Package>some.private.package</Private-Package>          </instructions>        
        </configuration>
      </plugin>

суббота, 5 сентября 2015 г.

WSS4J: ошибка "SOAP Envelope can not have children other than SOAP Header and Body" при попытке добавить security-заголовок

Проблема

Пытаюсь добавить security-заголовок в имеющееся SOAP-сообщение вызовом org.apache.ws.security.message.WSSecHeader.insertSecurityHeader(). Получаю ошибку:
org.apache.axiom.soap.SOAPProcessingException: SOAP Envelope can not have children other than SOAP Header and Body at org.apache.axiom.soap.impl.dom.SOAPEnvelopeImpl.checkChild(SOAPEnvelopeImpl.java:110)
at org.apache.axiom.soap.impl.dom.SOAPEnvelopeImpl.insertBefore(SOAPEnvelopeImpl.java:164)
at org.apache.ws.security.util.WSSecurityUtil.prependChildElement(WSSecurityUtil.java:646)
at org.apache.ws.security.util.WSSecurityUtil.findWsseSecurityHeaderBlock(WSSecurityUtil.java:722)
at org.apache.ws.security.message.WSSecHeader.insertSecurityHeader(WSSecHeader.java:145)
at ru.croc.security.jcp.JCPSigner.sign(JCPSigner.java:63)
... 26 more
Решение

WSS4J почему-то так странно реагирует на отсутствие блока <soapenv:Header/> в SOAP-конверте. Если его туда добавить (пусть даже пустым) перед вызовом insertSecurityHeader - ошибка пропадает.

Ошибка компиляции "package com.sun.org.apache.xml.internal.security does not exist"

Проблема

При сборке проекта с помощью maven возникает ошибка:
package com.sun.org.apache.xml.internal.security does not exist

Решение

Добавить зависимость в pom.xml:
<dependency>
  <groupId>com.sun.xml.security</groupId>
  <artifactId>xml-security-impl</artifactId>
  <version>1.0</version>
  <scope>provided</scope>
</dependency>

пятница, 4 сентября 2015 г.

WSO2 ESB 4.8.1: "java.lang.RuntimeException: Incorrect inclusion value: -1" при подписывании исходящего SOAP-запроса

Проблема

На WSO2 ESB 4.8.1 есть endoint с включенной безопасностью, для него указана некая policy. Безопасность в ней описана в соответствии со стандартом WS-SecurityPolicy 1.1 (http://specs.xmlsoap.org/ws/2005/07/securitypolicy/ws-securitypolicy.pdf), о чем говорит пространство имен http://schemas.xmlsoap.org/ws/2005/07/securitypolicy. При попытке использовать этот endpoint для отправки запроса возникает ошибка:

org.apache.synapse.SynapseException: Unexpected error during sending message out
        at org.apache.synapse.core.axis2.Axis2Sender.handleException(Axis2Sender.java:172)
        at org.apache.synapse.core.axis2.Axis2Sender.sendOn(Axis2Sender.java:71)
        at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.send(Axis2SynapseEnvironment.java:338)
        at org.apache.synapse.endpoints.AbstractEndpoint.send(AbstractEndpoint.java:333)
        at org.apache.synapse.endpoints.AddressEndpoint.send(AddressEndpoint.java:59)
        ...
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:77)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
        at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:131)
        at org.apache.synapse.core.axis2.ProxyServiceMessageReceiver.receive(ProxyServiceMessageReceiver.java:166)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
        ...
        at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.RuntimeException: Incorrect inclusion value: -1
        at org.apache.ws.secpolicy.model.Token.setInclusion(Token.java:56)
        at org.apache.ws.secpolicy11.builders.X509TokenBuilder.build(X509TokenBuilder.java:61)
        at org.apache.neethi.AssertionBuilderFactory.build(AssertionBuilderFactory.java:99)
        at org.apache.neethi.PolicyEngine.processOperationElement(PolicyEngine.java:225)
        at org.apache.neethi.PolicyEngine.getPolicyOperator(PolicyEngine.java:154)
        at org.apache.neethi.PolicyEngine.getPolicy(PolicyEngine.java:126)
        at org.apache.ws.secpolicy11.builders.InitiatorTokenBuilder.build(InitiatorTokenBuilder.java:40)
        at org.apache.neethi.AssertionBuilderFactory.build(AssertionBuilderFactory.java:99)
        ...
        at org.apache.neethi.PolicyEngine.getPolicy(PolicyEngine.java:126)
        at org.apache.synapse.util.MessageHelper.getPolicy(MessageHelper.java:522)
        at org.apache.synapse.core.axis2.Axis2FlexibleMEPClient.send(Axis2FlexibleMEPClient.java:404)
        at org.apache.synapse.core.axis2.Axis2Sender.sendOn(Axis2Sender.java:59)
        ... 25 more

Причина

В данном случае причина была в том, что в указанной для endpoint'а policy способ включения токена был указан как:
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Always"
Данный URL соответствует спецификации WS-SecutiryPolicy 1.2 (http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/ws-securitypolicy-1.2-spec-os.doc), тогда как для 1.1 он должен иметь следующий вид:
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Always"


пятница, 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-очередь, заработал.

вторник, 7 июля 2015 г.

Asus Zenfone 5 A501CG: самопроизвольная разблокировка экрана

Проблема

Телефон Asus Zenfone 5 A501CG (стоковая прошивка Android 4.4.2, сборка WW_user_2.22.40.54_20150527_44) самопроизвольно разблокируется (если стоит разблокировка обычным слайдером), либо просто включает экран, отображая экран блокировки.

Решение

Настройки -> Индивидуальные настройки ASUS -> снять галочку "Включить обложку ASUS".

четверг, 2 июля 2015 г.

Maven: OutOfMemory при выполнении тестов

Проблема

Есть проект, собираемый maven. При выполнении тестов они падают с OutOfMemory.

Решение

Задать настройки памяти для выполнения тестов в конфигурации maven-surefire-plugin, например:
     <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.18</version>
        <configuration>
          <forkMode>pertest</forkMode>
          <argLine>-Xms512m -Xmx2048m -XX:MaxPermSize=512m -XX:PermSize=128m</argLine>
          <testFailureIgnore>false</testFailureIgnore>
          <skip>false</skip>
        </configuration>
      </plugin>

вторник, 30 июня 2015 г.

TortoiseHG: push и "SSL: Server certificate verify failed"

Проблема

При попытке сделать push через TortoiseHG выдается ошибка:
SSL: Server certificate verify failed
, при этом push не выполняется.

Workaround

Идем в настройки, на вкладке глобальных настроен жмем "Edit File" (либо просто открываем файл mercurial.ini в домашней папке пользователя), добавляем:
[web]
cacerts=

WSO2 ESB: аутентификация на прокси-сервиса с помощью SAML 2.0-токена и ошибка "Version of the SAML token does not match with the required version"

Проблема

Есть защищенный прокси-сервис, policy которого имеет вид:
<wsp:Policy wsu:Id="SAML2HoKProtection31" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:IssuedToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<sp:Issuer>
<Address xmlns="http://www.w3.org/2005/08/addressing">https://localhost:9443/services/wso2carbon-sts</Address>
</sp:Issuer>
<sp:RequestSecurityTokenTemplate>
<t:TokenType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</t:TokenType>
<t:KeyType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://schemas.xmlsoap.org/ws/2005/02/trust/Bearer</t:KeyType>
<t:KeySize xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">256</t:KeySize>
</sp:RequestSecurityTokenTemplate>
<wsp:Policy>
<sp:RequireInternalReference/>
</wsp:Policy>
</sp:IssuedToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<rampart:RampartConfig xmlns:rampart="http://ws.apache.org/rampart/policy">
<!-- ... -->
</rampart:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Запрашиваем необходимый токен у сервиса wso2carbon-sts на той же шине:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
      <!-- ... -->
   </soapenv:Header>
   <soapenv:Body>
      <wst:RequestSecurityToken xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
         <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
         <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
            <wsa:EndpointReference xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
               <wsa:Address>https://localhost:8243/services/MySecuredService.MySecuredServiceHttpsSoap11Endpoint</wsa:Address>
            </wsa:EndpointReference>
         </wsp:AppliesTo>
         <wst:Lifetime>
            <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2015-06-16T21:00:47.099Z</wsu:Created>
            <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2015-07-16T22:00:47.099Z</wsu:Expires>
         </wst:Lifetime>
         <wst:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</wst:TokenType>         <wst:KeyType>http://schemas.xmlsoap.org/ws/2005/02/trust/Bearer</wst:KeyType>
          <wst:KeySize>256</wst:KeySize>
      </wst:RequestSecurityToken>
   </soapenv:Body>
</soapenv:Envelope>

Используем полученный assertion в запросе к нашему защищенному сервису. В итоге получаем неожиданную ошибку:
"Version of the SAML token does not match with the required version"
Причина

При валидации токена Rampart сравнивает указанный в policy TokenType и значение пространства имен полученного в запросе Assertion'а (чтобы понять это, пришлось немного подправить класс org.apache.rampart.PolicyBasedResultsValidator. Для SAML 2.0-токена значение пространства имен равно "urn:oasis:names:tc:SAML:2.0:assertion", т.е. отличается от значения TokenType.

Решение

Пока нашел единственное решение - указывать в policy TokenType = urn:oasis:names:tc:SAML:2.0:assertion. Это не совсем корректно, т.к. в действительности STS-сервис не примет такое значение, если попробовать его использовать при запросе токена, но зато проверка токена в таком случае срабатывает.

суббота, 20 июня 2015 г.

WSO2 ESB 4.8.1: wso2carbon-sts и org.apache.axis2.AxisFault: The specified request failed

Проблема

Установил "чистую" WSO2 ESB 4.8.1, пытаюсь вызвать wso2carbon-sts для получения SAML 2.0 токена. Получаю soap-fault и следующий лог:
TID: [0] [ESB] [2015-06-19 17:59:08,281] ERROR {org.apache.rahas.STSMessageReceiver} -  org.apache.rahas.TrustException: The specified request failed {org.apache.rahas.STSMessageReceiver}
TID: [0] [ESB] [2015-06-19 17:59:08,282] ERROR {org.apache.synapse.transport.passthru.ServerWorker} -  Error processing POST request for : /services/wso2carbon-sts.wso2carbon-stsHttpsSoap12Endpoint {org.apache.synapse.transport.passthru.ServerWorker}
org.apache.axis2.AxisFault: The specified request failed
at org.apache.rahas.STSMessageReceiver.invokeBusinessLogic(STSMessageReceiver.java:66)
at org.apache.axis2.receivers.AbstractInOutMessageReceiver.invokeBusinessLogic(AbstractInOutMessageReceiver.java:40)
at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:110)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:411)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:183)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
При этом в stdout валится стек исключения TrustException целиком, что позволяет залезть в исходники и найти то место, откуда эта ошибка родом (http://grepcode.com/file/repo1.maven.org/maven2/org.apache.rampart/rampart-trust/1.6.2/org/apache/rahas/RahasData.java?av=f):
org.apache.rahas.TrustException: The specified request failed
        at org.apache.rahas.RahasData.processWSS4JSecurityResults(RahasData.java:173)
        at org.apache.rahas.RahasData.<init>(RahasData.java:109)
        at org.apache.rahas.TokenRequestDispatcher.handle(TokenRequestDispatcher.java:55)
        at org.apache.rahas.STSMessageReceiver.invokeBusinessLogic(STSMessageReceiver.java:57)
        at org.apache.axis2.receivers.AbstractInOutMessageReceiver.invokeBusinessLogic(AbstractInOutMessageReceiver.java:40)
        at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:110)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
        at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:411)
        at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:183)
        at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:619)

Причина 

Для сервиса wso2carbon-sts не включена security, соответственно, несмотря на то, что при вызове сервиса я передаю в заголовке UsernameToken, он игнорируется. Соответственно, Rahas не знает, кого использовать в роли принципала в генерируемом токене, и падает с ошибкой.

Решение

Включаем security для сервиса wso2carbon-sts.

пятница, 19 июня 2015 г.

WSO2 ESB 4.8.1: логирование работы Entitlement-медиатора

В log4j.properties шины достаточно добавить строчку:
log4j.logger.org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator=DEBUG
после чего в логах шины появится достаточно отладочной информации, чтобы понять, что происходит внутри медиатора:
TID: [0] [ESB] [2015-06-19 15:16:41,294] DEBUG {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator} -  Mediation for Entitlement started {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator}
TID: [0] [ESB] [2015-06-19 15:16:41,295] DEBUG {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator} -  Subject ID is : ***** Resource ID is : /services/***** Action ID is : ****. {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator}
TID: [0] [ESB] [2015-06-19 15:16:41,993] DEBUG {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator} -  Entitlement Decision is : Deny {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator}
TID: [0] [ESB] [2015-06-19 15:16:41,993] DEBUG {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator} -  User is not authorized to perform the action {org.wso2.carbon.identity.entitlement.mediator.EntitlementMediator}

WSO2 ESB 4.8.1: отключение верификации хостнэймов при выполнении HTTPS-вызова

Предыстория

На dev-стенде в процессе отладки интеграционных сценариев получаем ошибку:
TID: [0] [ESB] [2015-08-13 15:54:12,584] ERROR {org.apache.synapse.transport.passthru.TargetHandler} -  I/O error: Host name verification failed for host : *** {org.apache.synapse.transport.passthru.TargetHandler}
javax.net.ssl.SSLException: Host name verification failed for host : ***
at org.apache.synapse.transport.http.conn.ClientSSLSetupHandler.verify(ClientSSLSetupHandler.java:152)
at org.apache.http.nio.reactor.ssl.SSLIOSession.doHandshake(SSLIOSession.java:285)
at org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:380)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:118)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:160)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:342)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:320)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:280)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:106)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:604)
at java.lang.Thread.run(Thread.java:745)
Ошибка вполне логична, т.к. сертификат черт знает какой, и на данном этапе эта нас устраивает. Решение - отключение верификации хостнэймов при выполнении исходящих HTTPS-вызовов. Выполняется в файле %WSO2_HOME%/repository/conf/axis2/axis2.xml:
<transportSender name="https" class="org.apache.synapse.transport.passthru.PassThroughHttpSSLSender">
<!-- ... -->
<parameter name="HostnameVerifier">AllowAll</parameter>
<!-- ... -->
</transportSender>


понедельник, 13 апреля 2015 г.

IE: отключение прокси-сервера с помощью reg-файла

Задача

Отключить прокси-сервер в IE (а также, например, в Chrome, который использует настройки прокси из IE), т.е. снять галочку "Use a proxy server for your LAN", с помощью скрипта.

Решение

Для начала делаем reg-файл со следующим содержимым:
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings]
"ProxyEnable"=dword:00000000 
Затем создаем bat-ник с одной единственной командой:
regedit.exe /s "C:\path\to\reg-file" 
Если нужно снимать галочку по какому-либо событию либо периодически, то идем в планировщик и создаем там задачу с соотв. action'ом:

На вкладке "General" нужно установить "Run with highest privileges".

понедельник, 6 апреля 2015 г.

Постоянные беспричинные Full GC

Проблема

Есть сервер приложений, на котором крутится несколько достаточно сложных Java-приложений, использующих множество различных фреймворков. Под определенной нагрузкой сервер начинает очень сильно тормозить, отклик на http-запросы падает с долей секунды до нескольких десятков секунд.
Было включено расширенное логирование сборщика мусора ключами:
-Xloggc:\some\path\to\gc.log -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps
Настройки памяти следующие:
-Xms3072m -Xmx3072m -XX:MaxPermSize=512m
Соотношение young- / tenored-разделов в хипе - по-умолчанию (т.е. параметры -XX:NewSize / -XX:MaxNewSize / -XX:NewRatio не используются) , сборщики также используются по-умолчанию.
В итоге в gc.log появилась интересная информация:
...
51222.509: [GC [PSYoungGen: 6003K->128K(995648K)] 418005K->412130K(3092800K), 0.0124632 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

51222.522: [Full GC (System) [PSYoungGen: 128K->0K(995648K)] [PSOldGen: 412002K->412004K(2097152K)] 412130K->412004K(3092800K) [PSPermGen: 160113K->160113K(160640K)], 1.8001088 secs] [Times: user=1.79 sys=0.00, real=1.79 secs]

51224.324: [GC [PSYoungGen: 106K->96K(992448K)] 412110K->412100K(3089600K), 0.0097823 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]

51224.334: [Full GC (System) [PSYoungGen: 96K->0K(992448K)] [PSOldGen: 412004K->412004K(2097152K)] 412100K->412004K(3089600K) [PSPermGen: 160113K->160113K(160640K)], 1.7753052 secs] [Times: user=1.78 sys=0.00, real=1.78 secs]

51226.115: [GC [PSYoungGen: 9595K->128K(1001792K)] 421600K->412132K(3098944K), 0.0120281 secs] [Times: user=0.05 sys=0.00, real=0.02 secs]

51226.128: [Full GC (System) [PSYoungGen: 128K->0K(1001792K)] [PSOldGen: 412004K->409356K(2097152K)] 412132K->409356K(3098944K) [PSPermGen: 160113K->160113K(160576K)], 1.7348557 secs] [Times: user=1.73 sys=0.00, real=1.73 secs]

51227.942: [GC [PSYoungGen: 20781K->6387K(998784K)] 430137K->415744K(3095936K), 0.0125255 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]

51227.955: [Full GC (System) [PSYoungGen: 6387K->0K(998784K)] [PSOldGen: 409356K->415263K(2097152K)] 415744K->415263K(3095936K) [PSPermGen: 160120K->160120K(160576K)], 1.7130215 secs] [Times: user=1.72 sys=0.00, real=1.72 secs]
...
Т.е. видим следующую ситуацию: примерно раз в 2 секунды срабатывает сначала обычный GC, а вслед за ним - Full GC. Причем объективных причин сборки мусора нет: на момент начала работы GC в young generation свободно около 98-99% процентов памяти, в old generation - около 75%, в permament geneartion - 70% (от максимальных 512m). 

Решение

Сказать по правде, ситуация поставила в ступор. Благо, достаточно быстро нагуглилась схожая проблема: http://basisondemand.com/as_java/how_we_resolved_the_issue_of_frequent_full_gc_that_was_running_every_03_seconds_verbose_systemgc. Там парни предположили, что причина такого поведения - явные вызовы System.gc() где-то в коде. Благо, этот вызов можно игнорировать, если установить следующий ключ:
-XX:+DisableExplicitGC
В моем случае это решение также сработало.

ЗЫ Кстати, вот хорошая статейка по сборке мусора в Java: http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html.

четверг, 19 марта 2015 г.

Birt: динамическая генерация SQL-запроса для отчета

Задача

Генерировать SQL-запрос, используемый для построения DataSet-а, динамически, в зависимости от значений параметров отчета.

Решение

Создаем DataSet, указываем у него пустой SQL. Идем в его advanced-свойства, находим там "Before open". Здесь можно писать произвольный JS-скрипт. Сгенерированный SQL необходимо записать в свойство this.queryText:

К параметрам отчета можно обращаться через params["myparam"].value. Если параметры отчета напрямую попадают в текст SQL, нужно не забыть их проэкранировать, чтобы избежать SQL-инъекций. В окне редактирования DataSet'а необходимо описать выходные колонки, которые будет выдавать сгенерированный скриптом SQL. Этот SQL может содержать параметры, тогда их нужно описать также, как это делается для статического SQL, в том же окне редактирования DataSet'а.

WSO2 ESB: MTOM-оптимизация и JMS

Задача

Складывать MTOM-оптимизированные SOAP-сообщения в JMS и читать их оттуда.

Решение

Во-первых, перед тем, как класть сообщение в JMS, включаем для него MTOM-оптимизацию (если она выключена глобально на сервере):
<property action="set" name="enableMTOM" scope="axis2"
                type="STRING" value="true"/>
Далее указываем axis2 на необходимость положить сообщение как бинарное, а не текстовое:
<property action="set" name="JMS_MESSAGE_TYPE" scope="axis2"
                type="STRING" value="JMS_BYTE_MESSAGE"/>
Указываем, что тип сообщения будет multipart/mixed:
<property action="set" name="messageType" scope="axis2"
                type="STRING" value="multipart/mixed"/>
Говорим, что content-type нужно положить в JMS-свойство ContentType (сохранение content-type требуется, т.к. в случае с multipart он будет содержать разделитель частей, необходимый для корректного чтения этого multipart'а):
<property action="set" name="transport.jms.ContentTypeProperty" scope="axis2"
                type="STRING" value="ContentType"/> 
Далее, в принимающей проксе прописываем, что content-type сообщения нужно брать из JMS-свойства ContentType:
    <parameter name="transport.jms.ContentType">
        <rules xmlns="http://ws.apache.org/ns/synapse">
                <jmsProperty>ContentType</jmsProperty>
        </rules>
    </parameter> 
В сценарии JMS -> JMS, когда MTOM-оптимизированное сообщение извлекается из JMS, обрабатывается, и снова кладется в JMS (опять оптимизированным), нужно перед помещением сообщения в исходящую очередь чистить этот самый транспортный заголовок ContentType:
            <property action="remove" name="ContentType" scope="transport"
                type="STRING"/> 
В противном случае WSO2 оставляет в исходящем сообщении тоже значение этого JMS-свойства, что и во входящем сообщении, при этом бинарное тело уже перекодировано с использованием другого MIME-разделителя, что приводит к ошибкам при последующем чтении MIME-а из JMS:
ERROR - JMSMessageReceiver Unknown error processing message
org.apache.axiom.om.OMException: Mime parts not found. Stream ended while searching for the boundary        at org.apache.axiom.attachments.Attachments.<init>(Attachments.java:238)
        at org.apache.axis2.builder.BuilderUtil.createAttachments(BuilderUtil.java:594)
        at org.apache.axis2.builder.BuilderUtil.createAttachmentsMap(BuilderUtil.java:545)
        ...

среда, 18 марта 2015 г.

birt: русские символы в значениях параметров отчета в JavaScript

Проблема

Есть birt-отчет, имеющий параметр, который используется в JavaScript-коде внутри отчета с помощью:
params["myparam1"].value
отчет развернут в веб-приложении birt на Tomcat, параметры в него передаются через GET. Проблема в том, что извлеченное в JavaScript значение параметра содержит некорректные значения для русских символов, как будто utf-8 строка прочиталась как cp1251.

Решение

Оборачиваем следующим образом:
decodeURIComponent(escape(params["component"].value))
Почему это работает, объяснено тут: http://ecmanaut.blogspot.ru/2006/07/encoding-decoding-utf8-in-javascript.html.

среда, 11 февраля 2015 г.

java.lang.UnsatisfiedLinkError: com.sun.glass.ui.win.WinApplication._submitForLaterInvocation

При запуске приложения, использующего JavaFX на достаточно старой JDK 1.7.0_09, получаю:
Exception in thread "Thread-2" java.lang.UnsatisfiedLinkError: com.sun.glass.ui.win.WinApplication._submitForLaterInvocation(Ljava/lang/Runnable;)V
        at com.sun.glass.ui.win.WinApplication._submitForLaterInvocation(NativeMethod)
        at com.sun.glass.ui.win.WinApplication.submitForLaterInvocation(WinApplication.java:215)
        at com.sun.glass.ui.InvokeLaterDispatcher.run(InvokeLaterDispatcher.java:101)
Лечится обновлением Java, в моем случае я обновился до 1.7.0_75. 

среда, 28 января 2015 г.

Ubuntu 14.04 Trusty Tahr на Asus EEEPC T101MT: проблема с яркостью

Поставил Ubuntu 14.04 Trusty Tahr на свой Asus EEEPC T101MT, и стокнулся со старой доброй проблемой с невозможностью поставить максимальную яркость. Решение - такое же старое, но с небольшой поправкой, связанной с тем, что в репозитории plippo/t101mt нет ветки по версию trusty:

  • apt-add-repository plippo/t101mt
  • идем в synaptic (можно конечно и через sources.list, но у меня виндовая привычка пользоваться оконными приложениями, что поделаешь), Настройки -> Репозитории -> Другое ПО, находим запись про plippo/t101mt, выделяем, жмем "Изменить", меняем в поле дистрибутив trusty на quantal
  • сохраняем, synaptic предложит обновить списки пакетов, обновляем
  • после этого устанавливаем пакет eeepc-brightness-workaround, яркость поднимется до максимальной даже без перезагрузки
  • теперь яркость максимальна, но не регулируется Fn-комбинациями. Ползунок бегает, а эффекта нет. Идем в /etc/default/grub, меняем значение GRUB_CMDLINE_LINUX_DEFAULT на "quiet splash acpi_backlight=vendor" ("acpi_osi=Linux", как я в свое время делал для Lenovo B460e, ставить не надо). Делаем update-grub, перезагружаемся.
ЗЫ По проблеме с щелчками винчествера также работает старое решение (http://barbitoff.blogspot.ru/2011/04/ubuntu.html).

Netbeans: maven и оффлайн сборка

Включить оффлайн сборку maven-проектов в Netbeans версии 8.0.2, можно, к сожалению, только глобально. Делается это следующим образом: Tools -> Options -> Java -> Maven -> Global Execution Options = --offline.