barbitoff programmer`s blog

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

вторник, 16 февраля 2016 г.

WSO2 ESB: wso2-esb-sequence-plugin и заглавные буквы "И"

wso2-esb-sequence-plugin версии 2.0.х, где x>5, при сборке бьет кодировку, превращая заглавные буквы "И" в сиквенсах в кракозябры. Workaround'а, кроме отката на 2.0.4, пока не нашел.

пятница, 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 - нет. 

пятница, 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"


среда, 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).

пятница, 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 г.

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

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

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>


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

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)
        ...

вторник, 16 декабря 2014 г.

WSO2 ESB 4.5.1: использование пространства имен http://ws.apache.org/ns/synapse в XPath-выражениях

Проблема

Есть прокси-сервис, в нем есть property-медиатор, у которого в xpath-выражении в атрибуте expression используется пространство имен "http://ws.apache.org/ns/synapse" с помощью некоторого префикса, который объявлен в этом же property-теге:
<property name="XXXProp" expression="//syn:abc/text()" xmlns:syn="http://ws.apache.org/ns/synapse"/>
Если прокси-сервис отредактировать через веб-консоль шины, объявление префикса пропадает, после чего property-медиатор, естественно, начинает выдавать ошибки из-за неизвестного префикса пространства имен. Если объявление префикса перенести из медиатора выше (хотя даже в сам корневой тег прокси-сервиса), ситуация не меняется.

Решение

Похоже на баг, и вызван он скорее всего тем, что сам конфигурационный xml прокси-сервиса имеет пространство имен по-умолчанию "http://ws.apache.org/ns/synapse". Копаться в исходниках времени не было, поэтому пришлось воспользоваться workaround'ом:
<property name="XXXProp" expression="//*[local-name()='abc']/text()" />

четверг, 2 октября 2014 г.

WSO2 ESB 4.5.1: реализация Splitter-паттерна с JMS-endpoint'ами и транзакицонностью

Задача

Реализовать прокси-сервис, который:

  • принимает по http входящее сообщение, являющееся "пакетным", т.е. состоящим из составных частей, которые должны обрабатываться отдельно друг от друга (Splitter EIP)
  • разбивает "пакет" на отдельные сообщения, складывает их по одному в JMS-очедерь
  • если все сообщения положились успешно, отвечает на входящий запрос успехом
  • если при помещении в JMS хотя бы одного из сообщений возникла ошибка, вся jms-транзакция должны быть откачена и в ответ на входящий запрос должен быть отправлен soapFault
Проблема

Вроде бы, реализация очевидна: iterate-медиатор для итерации по отдельным частям "пакета" и отправка этих "частей" на jms-endpoint посредством send-медиатора. Но проблема заключается в том, что JMSSender (входит в axis2-transport-jms) не умеет работать с jms-транзакциями. Т.е., если посмотреть в исходники, видим:
session = ((QueueConnection) connection).
            createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
, где false говорит об отсутствии поддержки транзакций. Т.е. не то что распределенные транзакции, а даже локальные транзакции не поддерживаются при записи в jms с помощью send-медиатора.
Другой вариант - использовать store-медиатор и JMSMessageStore. Однако, открыв исходники JMSMessageStore, видимо практически тоже самое:
return connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
Т.о., для реализации указанных требований придется что-то пилить руками, используя напрямую JMS-API.

пятница, 22 августа 2014 г.

WSO2 ESB: передача параметра из synapse-окружения в xslt

Задача

Есть некий xslt, выполняемый посредством xslt-медиатора. Есть некое свойство в default synapse-scope, хочется им воспользоваться внутри xslt.

Решение

Просто вызвать xpath-функцию syn:get-property изнутри xstl не получится - получим ругань на то, что функция отсутствует. Но есть другой вариант - через xslt-параметры. В xslt объявляем параметр:
<xsl:stylesheet ...>
<xsl:param name="MyParam" />
<!-- ... -->
</xsl:stylesheet>
А при вызове xslt-медиатора передать нужно значение в этот параметр:
<xslt key="...">
<property name="MyParam" expression="get-property('xxx')"/>
</xslt>

среда, 30 июля 2014 г.

WSO2 ESB 4.5.1: создание Scheduled Message Forwarding Processor через веб-консоль и настройка числа попыток повторной доставки

При создании Scheduled Message Forwarding Processor через веб-консоль WSO2 ESB есть возможность настройки числа попыток повторной отправки сообщения:


Однако, задаваемое здесь значение не применяется к Message Processor'у, и вот почему. В xml-файл конфигурации прокси-сервиса прописывается следующее:
<parameter name="max.delivery.attempts">2</parameter>
Тогда как в документации (https://docs.wso2.com/display/ESB451/Message+Forwarding+Processor) указано имя параметра "max.deliver.attempts". Если поправить имя на указанное в документации, настройка применяется.

среда, 26 марта 2014 г.

AxisFault: The system cannot infer the transport information from the vfs:file: ...

Проблема

WSO2 ESB 4.5.1. При попытке отправить сообщение на Endpoint с URL вида "vfs:file://..." в лог валится ошибка:
ERROR - Axis2Sender Unexpected error during sending message out
org.apache.axis2.AxisFault: The system cannot infer the transport
information from the vfs:file://...

Причина

В %WSO2_HOME%/repository/conf/axis2/axis2.xml не включен vfs-transportSender.

Решение

Раскомментировать:
<transportSender name="vfs" class="org.apache.synapse.transport.vfs.VFSTransportSender"/>

среда, 25 декабря 2013 г.

WSO2 ESB 4.5.1: Callout-mediator и ConnectionPoolTimeoutException

Проблема

В прокси-сервисе используется callout-медиатор для вызова некоторого веб-сервиса. Вызов приводит к ошибке (ошибка может быть любым AxisFault'ом, например, таймаутом, но в моем случае это была HTTP-ошибка 404). Проблема заключается в том, что после 2-3 вызов корректная ошибка сменяется на "org.apache.commons.httpclient.ConnectionPoolTimeoutException: Timeout waiting for connection", которая продолжает валиться даже после того, как вызываемый сервис починен и начал корректно отвечать. Через некоторое время проблема сама собой уходит, и конечный сервис начинает вызываться (если же его не починили - снова начинает падать с 404-ой ошибкой).

Причина

При возникновении AxisFault'а callout-медиатор не возвращает http-соединение в Connection-пул, в итоге пул кончается, и попытки достать из него соединение заканчиваются ошибкой (таймаутом ожидания соединения из пула). Через некоторое время такие невозвращенные коннекты сами закрываются по таймауту, и пул снова начинает выдавать коннекты.
Был заведен соответствующий баг (https://wso2.org/jira/browse/ESBJAVA-922), вроде бы исправленный в 4.5.0 M4, тем не менее, он снова воспроизводится на 4.5.1, может смерджить забыли =)

Решение

Берем сорцы synapse 2.1.0 (http://svn.apache.org/viewvc/synapse/tags/2.1.0/), там открываем проект synapse-core (modules/core), идем в класс org.apache.synapse.mediators.builtin.CalloutMediator, на строку 114, и приводим catch-блок к виду:
            } catch (AxisFault axisFault) {
                sc.cleanupTransport();
                handleFault(synCtx, axisFault);
            }
Собираем проект, берем скомпилированный класс CalloutMediator.class, подкладываем его в %WSO2_HOME%/repository/components/plugins/synapse-core_2.1.0.wso2v8.jar/org/apache/synapse/mediators/builtin/ (на остановленной шине), стартуем шину, радуемся.