2014-01-08 3 views
1

Я создал прокси-сервер в WSO2 ESB, который получает XML-код, преобразует его, передает в службу данных WSO2, преобразует результат и возвращает его реквестеру.NPE при попытке преобразовать результат DataService

Согласно журналу, DataService правильно вызывается, поскольку XML-результат выводится. Проблема на преобразующей результата, где это происходит:

ERROR - XSLTMediator Unable to perform XSLT transformation using : Value {name ='null', keyValue ='GetAppointmentSchedulePortalReqCS_Response'} against source XPath : s11:Body/child::*[position()=1] | s12:Body/child::*[position()=1] 
java.lang.NullPointerException 
    at org.apache.synapse.util.jaxp.StreamSourceBuilder.getSource(StreamSourceBuilder.java:55) 
    at org.apache.synapse.mediators.transform.XSLTMediator.performXSLT(XSLTMediator.java:289) 
    at org.apache.synapse.mediators.transform.XSLTMediator.mediate(XSLTMediator.java:191) 
    at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:71) 
    at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:114) 
    at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:230) 
    at org.apache.synapse.core.axis2.SynapseCallbackReceiver.handleMessage(SynapseCallbackReceiver.java:443) 
    at org.apache.synapse.core.axis2.SynapseCallbackReceiver.receive(SynapseCallbackReceiver.java:166) 
    at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180) 
    at org.apache.synapse.transport.passthru.ClientWorker.run(ClientWorker.java:217) 
    at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) 
    at java.lang.Thread.run(Thread.java:662) 

Файл XLST является:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://ws.wso2.org/dataservice" version="2.0" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xpath-default-namespace="http://www.algartelecom.com.br/SOA/Service/GetAppointmentSchedulePortalReqCS"> 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:template match="//xs:GetAppointmentResponse"> 
     <AppointmentRequest> 
      <serviceOrderID> 
       <xsl:value-of select="xs:NewAppointment" /> 
      </serviceOrderID> 
      <opportunityID> 
       <xsl:value-of select="xs:ServiceTOA" /> 
      </opportunityID> 
      <customerOrderID> 
       <xsl:value-of select="xs:MinimalTime" /> 
      </customerOrderID> 
     </AppointmentRequest> 
    </xsl:template> 
</xsl:transform> 

И XML, возвращаемый DataService является:

<?xml version='1.0' encoding='utf-8'?> 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soapenv:Body> 
     <GetAppointmentResponse xmlns="http://ws.wso2.org/dataservice"> 
      <NewAppointment>147</NewAppointment> 
      <ServiceTOA>TT_P</ServiceTOA> 
      <MinimalTime>1</MinimalTime> 
      <ReturnCode>0</ReturnCode> 
      <ErrorMessage>SUCESSO</ErrorMessage> 
     </GetAppointmentResponse> 
    </soapenv:Body> 
</soapenv:Envelope> 

Я ve проверил XSLT с XML в других инструментах и ​​работает tranformation! =/

Я думаю, что это может быть вызвано встроенным пространством имен, добавленным DSS в тег GetAppointmentResponse. Использование JRE1.6.0_43, ESB 4.6.0 и DSS 3.1.0. Пожалуйста помоги.

EDIT

Я заметил, что эта проблема действительно вызвана пустым телом в ответ, как уже упоминалось @Kallja.

Резюмируя, у меня есть следующий сценарий:

 PROXY1   ->   PROXY2  ->  PROXY3  ->  ENDPOINT 
in xslt->log1->header->send log2->header->send xslt->log3  address web service 
out log6->xslt->send   log5->send   xslt->log4->send 

Calling непосредственно PROXY3 через SoapUI, то вебсервис правильно называется и будет получен ответ.
Но, называя PROXY2 последовательность журнала появится в следующем порядке: log2, log3, log5, log4

Это означает, что PROXY2 делает асинхронный вызов к PROXY3. Он не дожидается XML ответа до того, как вернется в soapUI ответ. Он генерирует пустое тело.

Затем, как сделать его синхронным? Я попытался заменить посредника Send посредником Callout, но результат тот же.

+0

Трансформации работает с Saxon 9.5 тоже - только для информации. –

+0

Если трансформация работает вне вашего кода и в саксоне, это говорит о потенциальной проблеме с вашим Java-кодом, а не с XSLT. Вы можете нам это показать? Сообщение об ошибке относится к 'GetAppointmentSchedulePortalReqCS_Response' и' s11: Body/child :: * [position() = 1] | s12: Тело/ребенок :: * [position() = 1] ', ни один из которых нигде в коде, который вы нам предоставили. Вы знаете, на что они могут ссылаться? – JLRishe

+0

'GetAppointmentSchedulePortalReqCS_Response' - это описанный файл xsl. Нет кода, поскольку он работает на WSO2 ESB. – elias

ответ

1

Исключение NullPointerException, похоже, указывает на то, что выражение XPath (которое в этом случае является стандартом WSO2 ESB, когда ничего не предусмотрено), указывающее на данные, которые вы хотите преобразовать, возвращает null. В этом случае это означает, что у вас есть пустой SOAP-модуль.

Вы не разместили свою конфигурацию последовательности, поэтому мне не с чем работать.

Мое предложение состоит в том, что вы добавляете полный журнал (ниже), который печатает весь конверт SOAP вместе с несколькими свойствами в консоли ESB и в файле журнала углерода, непосредственно перед посредником XSLT, чтобы узнать, действительно ли у вас есть контента в вашей полезной нагрузке.

<log category="INFO" level="full" separator=","/> 

Я проверил ваше преобразование со следующей конфигурацией, и оно выполнено безупречно.

<?xml version="1.0" encoding="UTF-8"?> 
<proxy xmlns="http://ws.apache.org/ns/synapse" 
     name="XsltTestProxy" 
     transports="https,http" 
     statistics="disable" 
     trace="disable" 
     startOnLoad="true"> 
    <target> 
     <inSequence> 
     <payloadFactory> 
      <format> 
       <GetAppointmentResponse xmlns="http://ws.wso2.org/dataservice"> 
        <NewAppointment>147</NewAppointment> 
        <ServiceTOA>TT_P</ServiceTOA> 
        <MinimalTime>1</MinimalTime> 
        <ReturnCode>0</ReturnCode> 
        <ErrorMessage>SUCESSO</ErrorMessage> 
       </GetAppointmentResponse> 
      </format> 
      <args/> 
     </payloadFactory> 
     <log level="custom"> 
      <property name="message" value="Before XSLT transformation"/> 
      <property name="payload" expression="$body"/> 
     </log> 
     <xslt key="gov:GetAppointmentSchedulePortalReqCS_Response"/> 
     <log level="custom"> 
      <property name="message" value="After XSLT transformation"/> 
      <property name="payload" expression="$body"/> 
     </log> 
     <property name="RESPONSE" value="true"/> 
     <header name="To" action="remove"/> 
     <send/> 
     </inSequence> 
    </target> 
    <description/> 
</proxy> 

Как примечание стороны я предлагаю вам добавить следующий атрибут в вашу XSL: таблицы стилей элемент, чтобы удалить ненужную SOAP Xmlns заявления от вашего выхода XSLT.

exclude-result-prefixes="soapenv" 


EDIT
Этот простой пример конфигурации основан на описании потока исполнения отредактированный, чтобы вопрос. Он показывает, как правильно реализовать рассматриваемый поток. Когда вызывается Proxy1, операторы журнала отображаются в последовательности, как ожидалось.

<definitions xmlns="http://ws.apache.org/ns/synapse"> 
<proxy name="Proxy1" statistics="disable" trace="disable"> 
    <target endpoint="Proxy2Endpoint"> 
     <inSequence> 
      <!-- Do some XSLT here --> 
      <log category="INFO" level="custom" separator=","> 
       <property name="message" value="Proxy1 in (1)"/> 
       <property expression="$body" name="body"/> 
      </log> 
      <!-- Do some header magic here --> 
      <!-- Implicit send to the endpoint specified in the target element --> 
     </inSequence> 
     <outSequence> 
      <log category="INFO" level="custom" separator=","> 
       <property name="message" value="Proxy1 out (6)"/> 
       <property expression="/*" name="body"/> 
      </log> 
      <!-- Do some more XSLT here --> 
      <send/> 
     </outSequence> 
    </target> 
</proxy> 
<proxy name="Proxy2" statistics="disable" trace="disable" transports="https http"> 
    <target endpoint="Proxy3Endpoint"> 
     <inSequence> 
      <log category="INFO" level="custom" separator=","> 
       <property name="message" value="Proxy2 in (2)"/> 
       <property expression="$body" name="body"/> 
      </log> 
      <!-- Do some header magic here --> 
      <!-- Implicit send to the endpoint specified in the target element --> 
     </inSequence> 
     <outSequence> 
      <log category="INFO" level="custom" separator=","> 
       <property name="message" value="Proxy2 out (5)"/> 
       <property expression="/*" name="body"/> 
      </log> 
      <send/> 
     </outSequence> 
    </target> 
</proxy> 
<proxy name="Proxy3" statistics="disable" trace="disable"> 
    <target endpoint="ImaginaryWebServiceEndpoint"> 
     <inSequence> 
      <!-- Do some XSLT here --> 
      <log category="INFO" level="custom" separator=","> 
       <property name="message" value="Proxy3 in (3)"/> 
       <property expression="$body" name="body"/> 
      </log> 
     </inSequence> 
     <outSequence> 
      <!-- Do some more XSLT here --> 
      <log category="INFO" level="custom" separator=","> 
       <property name="message" value="Proxy3 out (4)"/> 
       <property expression="/*" name="body"/> 
      </log> 
      <send/> 
     </outSequence> 
    </target> 
</proxy> 
<proxy name="ImaginaryWebService" statistics="disable" trace="disable"> 
    <target> 
     <inSequence> 
      <log category="INFO" level="custom" separator=","> 
       <property name="message" value="Imaginary WebService in"/> 
       <property expression="$body" name="body"/> 
      </log> 
      <payloadFactory> 
       <format> 
        <proxy3Response xmlns="">This is the response from the Imaginary WebService</proxy3Response> 
       </format> 
       <args/> 
      </payloadFactory> 
      <log category="INFO" level="custom" separator=","> 
       <property name="message" value="Imaginary WebService out"/> 
       <property expression="/*" name="body"/> 
      </log> 
      <header action="remove" name="To"/> 
      <property action="set" name="RESPONSE" scope="default" 
       type="STRING" value="true"/> 
      <send/> 
     </inSequence> 
    </target> 
</proxy> 
<endpoint name="Proxy2Endpoint"> 
    <address statistics="disable" trace="disable" uri="http://localhost:8280/services/Proxy2" /> 
</endpoint> 
<endpoint name="Proxy3Endpoint"> 
    <address statistics="disable" trace="disable" uri="http://localhost:8280/services/Proxy3" /> 
</endpoint> 
<endpoint name="ImaginaryWebServiceEndpoint"> 
    <address statistics="disable" trace="disable" uri="http://localhost:8280/services/ImaginaryWebService" /> 
</endpoint> 

+0

Спасибо за ответ. Проблема в том, что это действительно пустое тело. Я отредактировал вопрос. – elias

Смежные вопросы