barbitoff programmer`s blog

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

суббота, 20 апреля 2013 г.

bat: задержки в скриптах

Для реализации задержки в bat-скрипте на определенное количество секунд можно воспользоваться командой timout. Например, так реализуется пауза в 20 секунд:
timeout /T 20 /NOBREAK
Проблема в том, что в некоторых средах (например, на билд-сервере Teamcity) попытка выполнить эту команду завершается ошибкой:
ERROR: Input redirection is not supported, exiting the process immediately.
Выход - заменить timeout на ping:
ping -n 20 127.0.0.1 > NUL
Эффект будет практически тот же (все же пинги будут выполняться не точно раз в секунду), а ошибка уйдет. 

пятница, 19 апреля 2013 г.

WSO2 ESB 4.5.1: enrich-медиатор и заполнение значений атрибутов

К сожалению, заполнение атрибутов enrich-медиатором не работает, по крайней мере, при попытке его выполнить так:
<enrich>
<source clone="false" type="custom" xpath="synapse:get-property('transport','FILE_NAME'")/>
<target action="replace" type="custom"
xmlns:myns="http://my.ns/" xpath="//myns:MyNode/@attr1"/>
</enrich>
приводит к ошибке:
"Invalid Target object to be enrich."
(если указывать action="child", эффект тот же).
На жире WSO2 заведен соответствующий баг, но пофикшен он к сожалению только в 4.7: https://wso2.org/jira/browse/ESBJAVA-1607.

cmd: копирование файлов в шару с аутентификацией

Задача:

Скопировать некоторый файл в сетевую виндовую шару, требующую аутентификации.

Решение:
echo "Authenticating on file share"
net use \\<host>\<share> <password> /user:<user>
echo "Copying file"
copy my.file \\<host>\<share>
echo "Unauthenticating on file share"
net use \\<host>\<share> /delete

среда, 17 апреля 2013 г.

WSO2 Carbon: сборка car-ников maven`ом

Пусть для примера есть некий проекта типа "Carbon Application Project", с 1 дочерним проектом типа "ESB Config Project", содержащим некоторое число endpoint`ов и прокси-сервисов.  Структура проектов следующая:
MyCarProject
|- pom.xml
|- MyEsbConfigProject
    |- pom.xml
    |- src
        |- main
            |- synapse-config
                |- endpoints
                    |- MyEndpoint.xml
                |- proxy-services
                |- sequences
Хочется, чтобы проект можно было собирать командой:
mvn clean package 
вместо того, чтобы делать это через Carbon Studio.
Более того, есть желание использовать в xml-ках ESB-артифактов переменные, которые будут заменяться некоторыми значениями при сборке (например, будут подставляться реальные URL`ы в endoint`ы). Например, чтобы такой endpoint:
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="MyEndpoint">
    <address format="soap11"
statistics="disable"
trace="disable"
uri="${endpoint.MyEndpoint.url}">
       ...
    </address>
</endpoint>
при сборке превращался в:
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="MyEndpoint">
    <address format="soap11"
statistics="disable"
trace="disable"
uri="http://real.url">
        ...
    </address>
</endpoint>
путем задание URL`а в параметре сборки:
mvn clean package -Dendpoint.MyEndpoint.url=http://real.url
Если просто выполнить "mvn clean package" в папке проекта Carbon Application Project, сборка завалится с ошибкой. Связана она с тем, что pom-ка проекта Carbon имеет зависимости от артифактов, создаваемых при сборке дочернего проекта ESB Config. Однако, т.к. Carbon Application Project никак не связан с дочерним проектом ESB Config, сборка первого не приводит к предварительной сборке последнего, что и приводит к невозможности разрешить зависимости.
Решается эта проблема созданием модульного проекта, родительского по отношению к первым двум (Carbon Application Project и ESB Config):

MyCarProjectRoot
    |- pom.xml
    |- MyCarProject
       |- pom.xml
       |- MyEsbConfigProject
           |- pom.xml
           |- src
               |- main
                   |- synapse-config
                       |- endpoints
                           |- MyEndpoint.xml
                       |- proxy-services
                       |- sequences
Содержимое родительской pom-ки примерно следующее:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>my.group</groupId>
  <artifactId>MyCarProjectRoot</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  <name>MyCarProjectRoot</name>
  <modules>
      <module>MyCarProject/MyEsbConfigProject</module>
      <module>MyCarProject</module>
  </modules>
</project>
Теперь, если выполнить mvn clean install для корневой pom-ки, сначала произойдет сборка и установка проекта  MyEsbConfigProject, а затем, уже успешно, проекта MyCarProject, на выходе которого мы получим заветный car-ник. 
Сборка работает, но с ней не всё идеально. Во-первых, pom-ка проекта ESB Config устроена очень хитро. Она сначала запускает плагины wso2-esb-proxy-plugin / wso2-esb-endpoint-plugin и др. для генерации pom-ки для сборки esb-артифактов (сгенерированная pom-ка помещается в ${project.build.directory}), после чего с помощью exec-maven-plugin запускает mvn для сборки этих сгенерированных pom-ок. Все бы ничего, но только при использовании exec-maven-plugin дочерние mvn-процессы не получают параметров, переданных родительскому mvn. Например, если родительскому mvn был передан путь к специфичному settings.xml, который нужно использовать при сборке, дочерние mvn знать о нем не будут (это особенно критично при сборке на build-сервере, когда зачастую разные сборки используют свои settings.xml). Выход их ситуации - замена exec-maven-plugin на maven-invoker-plugin, т.е. вместо:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2</version>
<extensions>true</extensions>
<executions>
 <execution>
<phase>install</phase>
<goals>
 <goal>exec</goal>
</goals>
<configuration>
 <executable>mvn</executable>
 <workingDirectory>${project.build.directory}</workingDirectory>
 <arguments>
<argument>clean</argument>
<argument>install</argument>
<argument>-Dmaven.test.skip=${maven.test.skip}</argument>
 </arguments>
</configuration>
 </execution>
</executions>
<configuration />
  </plugin>
в pom-ку нужно поместить:
<!-- Replaces exec-maven-plugin plugin, used in origin -->
  <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<version>1.8</version>
<configuration>
 <debug>true</debug>
 <pom>${project.build.directory}/pom.xml</pom>
 <goals>
<goal>clean</goal>
<goal>install</goal>
 </goals>
 <properties>
<maven.test.skip>${maven.test.skip}</maven.test.skip>
 </properties>
</configuration>    
<executions>
 <execution>
<phase>install</phase>
<goals>
 <goal>run</goal>
</goals>          
 </execution>
</executions>
  </plugin>  
Эффект будет тот же, но дочерние сборки будут сохранять параметры родительской.
Теперь насчет фильтрации xml-ек esb-артифактов. Во-первых, в pom-ке проекта ESB Config необходимо настроить maven-resources-plugin, добавив:
<!-- Filter ESB artifacts -->
  <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
 <outputDirectory>${project.build.directory}/../capp.filtered</outputDirectory>
 <resources>
<resource>
 <directory>${project.build.directory}</directory>
 <filtering>true</filtering>
</resource>
 </resources>
 <includeEmptyDirs>true</includeEmptyDirs>
 <escapeWindowsPaths>false</escapeWindowsPaths>
</configuration>
<executions>
 <execution>
<id>filter-esb-artifacts</id>
<phase>package</phase>
<goals>
 <goal>copy-resources</goal>
</goals>
 </execution>        
</executions>
  </plugin>
Теперь на фазе package (после того, как была сгенерирована pom-ка для сборки артефактов  а сами артефакты были перемещены в ${project.build.directory}) содержимое ${project.build.directory} копируется в директорию ${project.build.directory}/../capp.filtered с выполнением фильтрации. Теперь нужно настроить maven-invoker-plugin на эту директорию:
  <!-- Replaces exec-maven-plugin plugin, used in origin -->
  <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<version>1.8</version>
<configuration>
 <debug>true</debug>
 <pom>${project.build.directory}/../capp.filtered/pom.xml</pom>
                ...
</configuration>    
        ...
  </plugin> 
Также, чтобы директория capp.filtered чистилась при выполнении clean, нужно добавить соотв. настройки в maven-clean-plugin:
 <!-- Clean settings to clean capp.filtered directiry -->
 <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
<configuration>
 <filesets>
<fileset>
 <directory>${project.build.directory}/../capp.filtered</directory>
</fileset>
 </filesets>
</configuration>
  </plugin> 
Также, на данный момент properties, устанавливаемые при сборке корневого проекта, не подхватываются сборкой проекта  ESB Config. Причина в том, что хотя коревой проект и ссылается на проект ESB Config как на дочерний, обратная связь не установлена. Чтобы её установить, нужно добавить в pom-ку проекта ESB Config следующее:
  <parent>
    <groupId>ru.project.integration.xxx</groupId>
    <artifactId>MyCarProjectRoot</artifactId>
    <version>1.0.0</version>
    <relativePath>../../</relativePath>
  </parent>
Всё, теперь можно задавать свойства при сборке корневого проекта, и они будут использоваться при фильтрации xml-конфигураций esb-артефактов.
При сборке более сложных carbon-проектов возникают и другие сложности. Например, при закатывании в car-ник java-библиотек (дочерних проектов типа "Java Library Project") сборка непосредственно мавеном генерирует manifest-файлы, не дающие полученному osgi-бандлу установиться на wso2. Проблема связана с тем, что в Import-Package манифеста включаются все без исключения классы, импортируемые внутри библиотеки, и при установке бандла wso2 ругается на недоступность некоторых из них (чтобы увидеть эту ошибку, пришлось изрядно повозиться: http://barbitoff.blogspot.ru/2013/04/wso2-esb-error-defaultappdeployer-error.html). Если же car-ник собирать из Carbon Studio, в получаемом манифесте блока Import-Package вообще нет. 
Исправляется эта проблема внесением соотв. настройки в pom-ку проекта Java Library Project, а именно:
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>my.group</groupId>
  <artifactId>my-lib</artifactId>
  <version>4.4.0</version>
  <packaging>bundle</packaging>
  <name>my-lib</name>
  <description>my-lib</description>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>2.3.4</version>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Bundle-SymbolicName>my-lib</Bundle-SymbolicName>
            <Bundle-Name>my-lib</Bundle-Name>
            <Export-Package>my.package.*</Export-Package>
            <DynamicImport-Package>*</DynamicImport-Package>
            <Import-Package></Import-Package>
          </instructions>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
Также, если библиотека содержит не только классы, но и ресурсы, Carbon Studio почему-то не включает их пакеты в pom-ку проекта в блок Export-Package настройки плагина maven-bundle-plugin. Соответственно, при сборке в бандл ресурсы не попадают. Лечится проблема добавлением нужных пакетов в Export-Package.
В общем заморочек много, но имхо они того стоят. Во-первых, такой проект можно собрать, не имея Eclipse и Carbon Studio. Во-вторых, он может вообще собираться автоматически на build-сервере, а благодаря maven-car-deploy-plugin - еще и деплоиться прямо оттуда автоматом на wso2 (благо за счет фильтрации мы можем настроить сборку на нужные url'ы / папки, используемые vfs-транспортом / др. прямо во время сборки). Правда, с деплоем уже не все так радостно. Например, для передеплоивания car-ников, содержащих бандлы, зачастую необходим рестарт шины, а тут уже одним maven-car-deploy-plugin не обойдешься.

Maven: unbind maven-deploy-plugin`а с фазы deploy

Делать unbind плагинов, которые жестко завязаны на фазы сборки, нельзя, но, в случае с maven-deploy-plugin, можно просто пропустить его выполнение, указав в конфигурации:
<plugin>
  <artifactId>maven-deploy-plugin</artifactId>
  <version>2.7</version>
  <configuration>
<skip>true</skip>
  </configuration>
</plugin>

Weblogic 10.3.5: ошибка "java.io.FileNotFoundException: class path resource [...] cannot be resolved to absolute file path because it does not reside in the file system: zip:.../_wl_cls_gen.jar!/..."

Проблема:

При деплое war-ника на Weblogic 10.3.5 (без распаковки) вываливается ошибка:
java.io.FileNotFoundException: class path resource [...] cannot be resolved to absolute file path because it does not reside in the file system: zip:.../_wl_cls_gen.jar!/...
при попытке разворачиваемого приложения прочитать какой-либо из файлов, размещенных в WEB-INF/classes. Деплою плагином weblogic-maven-plugin.

Причина:

Судя по форуму Oracle (https://forums.oracle.com/forums/thread.jspa?threadID=842786), это некая известная проблема Weblogic'а, связанная с тем, что он зачем-то при деплое все классы из WEB-INF/classes запаковывает в _wls_cls_gen.jar, после чего возникают проблемы, если приложение пытается прочитать какой-нибудь ресурс, который до этого располагался в WEB-INF/classes (этот ресурс получается дважды упакован: в _wls_cls_gen.jar, а затем и в war). 

Решение:

Workaround`ом для этой проблемы является развертывание приложений не в war-никах, а в распакованном виде. Т.к. weblogic-maven-plugin развернуть приложение в распакованном виде не может, то подойдет другой вариант: приложение в распакованном виде запаковать в EAR, и его уже задеплоить. Как собирать распакованные war-ники в EAR, я уже писал: http://barbitoff.blogspot.ru/2013/04/maven-ear-plugin-war-ear.html. Деплой ear-ника плагином weblogic-maven-plugin ничем не отличается от деплоя war.

maven-ear-plugin: включение WAR-ников в EAR в распакованном виде

Чтобы war-ники включались в EAR в распакованном (exploded) виде, нужно добавить тип "war" в параметр конфигурации unpackTypes:
  <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.6</version>
<configuration>
<unpackTypes>war</unpackTypes>
<version>6</version>
<defaultLibBundleDir>lib</defaultLibBundleDir>
</configuration>
  </plugin>
О том, как настроить распакову лишь некоторых war-ников, почитать можно тут: http://maven.apache.org/plugins/maven-ear-plugin/examples/unpacking-a-module.html

Pentaho: получение параметра трансформации из Java-кода step'а

String paramValue= getTrans().getVariable("paramValue");

вторник, 16 апреля 2013 г.

multiline grep

Собственно сабж:
pcregrep -M
Вообще очень удобная команда, имеет perl-совместимый синтаксис регулярных выражений. 

воскресенье, 14 апреля 2013 г.

dijit: отображения toolip`а ValidationTextBox`а рядом с другим элементом

Задача:

Сделать так, чтобы подсказка ValidationTextBox`а отображалась не рядом с ним, а рядом с другим dom-узлом. В моем случае я хочу вместо:
получить:

Решение:

Переопределить у ValidationTextBox метод displayMessage таким образом, чтобы методу Tooltip.show() он передавал не текущий узел, а некоторый другой. Этот самый "другой" узел я вынес в отдельное свойство:
define("my/form/ValidationTextBox", [
"dojo/_base/declare",
"dijit/form/ValidationTextBox",
"dijit/Tooltip"
], function(declare, ValidationTextBox, Tooltip){
var ValidationTextBoxExt;
return ValidationTextBoxExt = declare("my/form/ValidationTextBox", ValidationTextBox, {
/**
* Узел для отображения подсказки
*/
tooltipAroundNode: null,
  /** * Отображает подсказку рядом с текущим элементом, * если tooltipAroundNode = null, либо с заданным * в tooltipAroundNode элементом */
displayMessage: function(/*String*/ message){
if(message && this.focused){
Tooltip.show(message, this.tooltipAroundNode==null?this.domNode:this.tooltipAroundNode, this.tooltipPosition, !this.isLeftToRight());
}else{
Tooltip.hide(this.tooltipAroundNode==null?this.domNode:this.tooltipAroundNode);
}
} });
});
Теперь остается лишь где-то в коде установить этот самый tooltipAroundNode:
require(["dijit/registry"], function(registry) {
     registry.byId("my-input").set("tooltipAroundNode",registry.byId("my-button").domNode);
}

пятница, 12 апреля 2013 г.

Работа служб Windows с сетевыми дисками

Проблема:

Есть служба Windows (в моем случае - WSO2 ESB), настроенная на работу с некоторой папкой, размещенной на подключенном сетевом диске (mapped network drive). Диск подключался пользователем. Служба работает от "Local System Acount" и диска не видит (пишет, что "The file does not exists").

Решение:

Подключить диск от имени системы. Для этого:
2) Запускаем cmd от Администратора, переходим в папку Sysinternals, выполняем:
psexec -i -s cmd.exe
Откроется консоль от имени "nt authority\system".
3) Подключаем сетевой диск, при необходимости задавая данные для доступа к нему:
NET USE V: \\host\share <pass> /USER:<domain>\<user> /PERSISTENT:YES
Эта команда подключит сетевую шару \\host\share как сетевой диск V:, используя имя пользователя <domain>\<user> и пароль <pass> для доступа к этой шаре.
4) Всё, после этого служба будет иметь доступ к сетевому диску. Диск восстановится после перезагрузки благодаря ключу /PERSISTENT:YES.
5) Есди диск вдруг понадобилось отключить, нужно выполнить описанные выше манипуляции для входа в консоль "nt authority\system", после чего вызывать:
NET USE V: /DELETE
Спасибо http://stackoverflow.com/questions/182750/map-a-network-drive-to-be-used-by-a-service

среда, 10 апреля 2013 г.

Подключение к LocalDB из Microsoft SQL Server Managment Studio 2012

Приведу небольшой пример, как создать и запустить БД LocalDB, после чего подключиться к ней, используя Microsoft SQL Server Managment Studio 2012.
1) Создаем БД (я назвал её "TestLocalDB"):
> C:\Program Files\Microsoft SQL Server\110\Tools\Binn>SqlLocalDB.exe create TestLocalDB
LocalDB instance "TestLocalDB" created with version 11.0.
2) Стартуем её:
> C:\Program Files\Microsoft SQL Server\110\Tools\Binn>SqlLocalDB.exe start TestLocalDB
LocalDB instance "TestLocalDB" started.
3) Смотрим информацию:
> C:\Program Files\Microsoft SQL Server\110\Tools\Binn>SqlLocalDB.exe info TestLocalDB
Name:               TestLocalDB
Version:            11.0.3000.0
Shared name:
Owner:              DOMAIN\user
Auto-create:        No
State:              Running
Last start time:    08.04.2013 19:37:04
Instance pipe name: np:\\.\pipe\LOCALDB#A7D28F1F\tsql\query
В последней строчке указано имя канала, к которому мы и будем подключаться из SQL Server Managment Studio:

JavaMail и avast!

При попытке с помощью JavaMail отправить почту, используя smtp-сервер mail.ru, вывалилась такая ошибка:
javax.mail.AuthenticationFailedException: 535 No SMTP server defined. Use real server address instead of 127.0.0.1 in your account.
at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:823)
at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:756)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:673)
at javax.mail.Service.connect(Service.java:295)
Решение оказалось неожиданным - отключить антивирус avast!

вторник, 9 апреля 2013 г.

maven-jar-plugin: задание имени Main-класса для установки в манифесте

Чтобы задать имя Main-класса, который будет прописан в манифест jar-ника, нужно задать соответствующую конфигурацию плагину maven-jar-plugin:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.maventest.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
Тогда созданный jar-ник будет иметь такой манифест:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: dbarbitov
Build-Jdk: 1.7.0_17
Main-Class: com.maventest.App


WSO2 ESB: невнятная ошибка "ERROR - DefaultAppDeployer Error while installing bundle" при развертывании OSGI-бандла

Проблема:

При развертывании пользовательского OSGI-бандла на WSO2 ESB 4.5.1 валится совершенно ни о чем не говорящая ошибка:
ERROR - DefaultAppDeployer Error while installing bundle : file:///.../MyBundle.jar
Исходники класса DefaultAppDeployer подтвердили опасения: исключение-причина ошибки попросту теряется:

package org.wso2.carbon.application.deployer.handler;
...
public class DefaultAppDeployer implements AppDeploymentHandler {
...
private void installBundle(String bundlePath) {
...
try {
Bundle bundle = AppDeployerServiceComponent
.getBundleContext().installBundle(bundlePath);
bundle.start();
} catch (BundleException e) {
log.error("Error while installing bundle : " + bundlePath);
}
...
}
...
}
Решение 

Исправить DefaultAppDeployer, добавив в лог исключение-причину:
log.error("Error while installing bundle : " + bundlePath, e);
Как именно вносить правку - есть варианты:
  1. Декомпилировать класс из jar-ник в шине, поправить и скомпилировать обратно
  2. Собрать класс из исходников на сайте wso2. Этот вариант проблемнее - в WSO2 ESB 4.5.1 лежит версия jar-ника org.wso2.carbon.application.deployer 4.0.2, где взять её исходники, я не нашел. На сайте wso2 доступны только исходники версии 4.0.0-SNAPSHOT, если собрать  org.wso2.carbon.application.deployer из них, шина не будет стартовать, т.к. эта версия существенно отличается от 4.0.2 даже по составу классов.

воскресенье, 7 апреля 2013 г.

Yandex Maps: определение геокоординат в обработчике клика на карте

Делается так:
map.events.add('click', onMapClick);
onMapClick = function(ev) {
var projection = map.options.get('projection');
var geoCoords = projection.fromGlobalPixels(
map.converter.pageToGlobal(
[
ev.get('domEvent').get('clientX'),
ev.get('domEvent').get('clientY')
]
),
map.getZoom()
);
console.debug(geoCoords);
}

суббота, 6 апреля 2013 г.

WSO2 ESB: некорректное поведение throttle-медиатора при fault`ах конечного сервиса

Проблема:

В прокси-сервисе WSO2 ESB 4.5.1 нужно ограничить число параллельных вызовов конечного веб-сервиса. Для этого использован throttle-медиатор (используется именно медиатор, а не policy сервиса по той причине, что необходимо контролировать поведение при превышении лимита, что при использовании policy невозможно):

<?xml version="1.0" encoding="UTF-8"?>
<proxy name="MyThrottlingProxy" ... >
<target>
<inSequence>
<throttle id="wsthrottle">
<policy>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:throttle="http://www.wso2.org/products/wso2commons/throttle">
<throttle:ThrottleAssertion>
<throttle:MaximumConcurrentAccess>1</throttle:MaximumConcurrentAccess>
</throttle:ThrottleAssertion>
</wsp:Policy>
</policy>
<onAccept>
<!-- ... -->
<send/>
</onAccept>
<onReject>
<!-- ... -->
<drop/>
</onReject>
</throttle>
</inSequence>
<outSequence>
<throttle id="wsthrottle"/>
<!-- ... -->
</outSequence>
<faultSequence>
<throttle id="wsthrottle"/>
<!-- ... -->
</faultSequence>
</target>
<!-- ... -->
</proxy>
(в данном случае число параллельных вызовов ограничено одним).
Здесь throttle-медиаторы с одинаковыми id размещены во всех трех последовательностях: in, out и fault. При выполнении медиатора в inSequence счетчик параллельно выполняющихся запросов инкрементируется и сравнивается с установленным ограничением. Если порог не превышен - запрос на конечный сервис отправляется, если превышен - сообщение отбрасывается. Выполнение throttle-медиатора в outSequence/faultSequence должно декрементировать счечик, т.к. запрос уже выполнился. Однако не тут то было. При выполнении faultSequence декремента не происходит, что приводит к тому, что упавший с ошибкой запрос с точки зрения throttle-медиатора становится бесконечно выполняющимся, что моментально парализует прокси-сервис, т.к. установлено ограничение всего в 1 параллельный запрос.
Чтобы разобраться в проблеме, пришлось включить логирование для throttle-медиатора добавлением в log4j.properties шины строчки:
log4j.logger.org.apache.synapse.mediators.throttle.ThrottleMediator=DEBUG
, а также посмотреть таки в исходники медиатора: http://www.docjar.com/html/api/org/apache/synapse/mediators/throttle/ThrottleMediator.java.html. Выяснилось, что декремент происходит, только если медиатор выполняется в последовательности обработки ответа, коей faultSequence почему-то не считается. Чтобы скорректировать поведение throttle-медиатора в faultSequence, пришлось перед ним добавить установку свойства RESPONSE в true:
<faultSequence>
<property name="RESPONSE" value="true"/>
<throttle id="wsthrottle"/>
<!-- ... -->
</faultSequence>


WSO2 ESB 4.5.1: используемая имплементация JavaMail

Возникла необходимость узнать, какая именно имплементация JavaMail используется в WSO2 ESB 4.5.1 (в mailto-транспортах). Как оказалось, используется Reference Implmementation, которая тянется из jar-ника axiom_1.2.11.wso2v3.jar (сама имплементация из osgi-бандла не экспортируется). А вот версия этой имплементации пока для меня остается загадкой.

пятница, 5 апреля 2013 г.

bat: создать N копий файла

Задача

Есть файл test.pdf, нужно создать N его копий с именами test_<n>.pdf, где <n> меняется от 1 до N.

Решение

Для N=2000:
for /L %%i IN (1,1,2000) DO copy test_.pdf test_%%i.pdf

VMWare не видит поддержку Intel VT-x

Проблема:

Есть машина с Intel Core i7-3770. Пытаюсь запустить виртуалку с помощью VMWare Player 5.0.2, включив в свойствах виртуалки поддержку "Intel VT-x" (поддержка есть в процессоре). Хост крутится на Win7 x64 Enterprise. Однако при запуске получаю ошибку, говорящую об отсутствии поддержки VT-x.

Решение:

Решение нашлось, как ни странно, на форуме VirtualBox: https://forums.virtualbox.org/viewtopic.php?p=108857. Заключается оно в следующем:
  1. Перезагружаем хост
  2. Заходим в БИОС, отключаем поддержку виртуализации (у меня там 2 отдельных пункта, касающихся виртуализации, я отключил оба)
  3. Сохраняем настройки, машина перезагружается
  4. После загрузки БИОС отключаем машину, обесточиваем на 10 сек.
  5. Включаем, заходим в БИОС, включаем поддержку виртуализации
  6. Сохраняем настройки, машина перезагружается
  7. После загрузки БИОС отключаем машину, обесточиваем на 10 сек.
  8. Загружаем машину. VT-x в VMWare становится доступен.