barbitoff programmer`s blog

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

понедельник, 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).