barbitoff programmer`s blog

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

суббота, 8 декабря 2012 г.

WSO2 ESB: UnmappableCharacterException при отправке сообщения sender`ом HttpCoreNIOSender

Проблема:

Есть 2 прокси-сервиса, один - VFS -> JMS, принимающий файлы, обрабатывающий их и сладывающий сформированный SOAP в очередь, и другой - JMS->HTTP, отправляющий это сообщение конечному сервису. В последнем при отправке сообщения sender`ом HttpCoreNIOSender валится исключение:
[2012-12-06 10:20:18,108] ERROR - ClientHandler I/O Error submitting request : Input length = 1
java.nio.charset.UnmappableCharacterException: Input length = 1
        at java.nio.charset.CoderResult.throwException(CoderResult.java:278)
        at org.apache.http.impl.nio.reactor.SessionOutputBufferImpl.writeLine(SessionOutputBufferImpl.java:160)
        at org.apache.http.impl.nio.codecs.AbstractMessageWriter.write(AbstractMessageWriter.java:93)
        at org.apache.synapse.transport.nhttp.LoggingNHttpClientConnection$LoggingNHttpMessageWriter.write(LoggingNHttpC
lientConnection.java:137)
        at org.apache.http.impl.nio.DefaultNHttpClientConnection.submitRequest(DefaultNHttpClientConnection.java:241)
        at org.apache.synapse.transport.nhttp.LoggingNHttpClientConnection.submitRequest(LoggingNHttpClientConnection.ja
va:78)
        at org.apache.synapse.transport.nhttp.ClientHandler.processConnection(ClientHandler.java:256)
        at org.apache.synapse.transport.nhttp.ClientHandler.connected(ClientHandler.java:204)
        at org.apache.http.impl.nio.DefaultClientIOEventDispatch.connected(DefaultClientIOEventDispatch.java:134)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.sessionCreated(BaseIOReactor.java:284)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processNewChannels(AbstractIOReactor.java:419)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:286)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
        at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:54
2)
        at java.lang.Thread.run(Thread.java:722)

Причина:

Причина оказалась в русских именах файлов. Дело в том, что VFS кладет имя файла и полный путь к нему в транспортные заголовки "FILE_NAME" и "FILE_PATH". Эти заголовки сохраняются при прохождении сообщения через JMS и попадают sender`у. А тот, видимо, не любит не-ASCII-символы в заголовках и валится. В качестве workaround`а можно удалять проблемные заголовки перед отправкой сообщения:
<property action="REMOVE" name="FILE_NAME"
                scope="transport" value=""/>
<property action="REMOVE" name="FILE_PATH"
                scope="transport" value=""/>
, или, если они нужны, скажем, в out sequence, можно перекладывать значения в свойства в области видимости default.

среда, 5 декабря 2012 г.

DFC: получение идентификатора объекта, созданного с помощью CREATE DQL-запроса

При выполнении CREATE DQL-запроса с помощью DfQuery идентификатор объекта возвращается как аттрибут "object_created" единственной строки результирующей коллекции:
IDfCollection col = query.execute(session, DfQuery.DF_QUERY);
col.next();
IDfId newId = col.getId("object_created");

WSO2 ESB 4.5.1: "org.apache.axis2.AxisFault: Transport error: 415 Error: Unsupported Media Type" при отправке сообщения на backend-сервис

Проблема:

При проксировании запроса возникает ошибка:
[2012-12-05 18:21:58,341]  INFO - HTTPSender Unable to sendViaPost to url[http://localhost:8084/mysrv]
org.apache.axis2.AxisFault: Transport error: 415 Error: Unsupported Media Type
        at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.java:308)
        at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:194)
        at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75)
        at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSende
.java:450)
        at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:277)
        at org.apache.axis2.engine.AxisEngine$TransportNonBlockingInvocationWorker.run(AxisEngine.java:627)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)
Причина:

Заголовок Content-Type, передаваемый шиной конечному веб-сервису, не поддерживается последним. В моем случае значение заголовка было "application/xml", тогда как сервис ожидал "text/xml" (о чем кстати он и писал в свои логи).

Решение:

В цепочке медиации установить свойство "messageType" в области видимости "axis2":
<property name="messageType" value="text/xml" scope="axis2"/>
Тогда Message Builder сформирует правильное значение HTTP-заголовка. 

WSO2 ESB: Установка заголовка SOAPAction

Установка заголовка SOAPAction для исходящего сообщения выполяется с помощью медиатора "header":
<header action="set" name="Action" value="someSoapAction"/>

вторник, 4 декабря 2012 г.

Synapse: использование пространств имен в Xpath в конфигурации

Чтобы конфигурации Synapse использовать пространства имен в выражениях Xpath, нужно в в том теге, в котором xpath используется (или в любом теге-предшественнике этого тега) объявить нужный namespace, после чего его префикс можно будет использовать в Xpath:
<switch source="count($body/myns:MyNode)" xmlns:myns="http://my.ns"

Commons Codec 1.4: encodeBase64String и multi-line chunking

Версии Commons Codec до 1.5 выполняют multi-line chunking (разбитие результата на строки равной длины) при вызове encodeBase64String(byte[] binaryData): http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html#encodeBase64String(byte[]). Т.к. в WSO2 ESB 4.5.1 входит именно версия 1.4, приходится с этим мириться. Если нужно все же получить результат одной строкой, придется сделать replace:
Base64.encodeBase64String(strToEncode).replace(System.lineSeparator(),"")
Или, для 6ой явы:
Base64.encodeBase64String(strToEncode).replace(System.getProperty("line.seperator"),"")

понедельник, 3 декабря 2012 г.

WSO2 ESB 4.5.1: установка имени очереди для JMS-транспорта прокси-сервиса

По-умолчанию, JMS-транспорт прокси-сервиса слушает очередь, имя которой совпадает с именем самого сервиса. Чтобы указать имя очереди явно, нужно задать параметр  сервиса "transport.jms.Destination":
<proxy xmlns="http://ws.apache.org/ns/synapse"
    name="myProxy" transports="jms">
    ...
<parameter name="transport.jms.Destination">myQueue</parameter>
</proxy>