2014-01-08 17 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> 

而且通過的DataService返回的XML是:

<?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> 

我在另一個工具中測試了帶有XML的XSLT,並且轉換工作正常! =/

我在想這可能是由DSS添加到GetAppointmentResponse標記中的內聯命名空間引起的。 使用JRE1.6.0_43,ESB 4.6.0和DSS 3.1.0。請幫忙。

編輯

我注意到,這個問題是由一個空體在應對真正引起的,如@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 

通過的soapUI直接PROXY3調用,web服務正確調用並接收響應。
但是,調用PROXY2,日誌序列出現在以下順序:log2log3log5log4

這意味着PROXY2正在爲PROXY3的異步調用。它不會在返回soapUI之前等待響應的XML。它產生一個空的身體。

那麼,如何讓它同步呢?我試着用Callout中介替換Send中介,但結果是一樣的。

+0

改造工程與撒克遜9.5太 - 只爲信息。 –

+0

如果轉換在您的代碼和撒克遜以外的地方工作,那麼這意味着您的Java代碼而不是XSLT的潛在問題。你能告訴我們嗎?錯誤消息引用'GetAppointmentSchedulePortalReqCS_Response'和's11:Body/child :: * [position()= 1] | s12:身體/孩子:: * [位置()= 1]',這兩者都不是您提供給我們的代碼中的任何地方。你知道這些可能是指什麼嗎? – JLRishe

+0

'GetAppointmentSchedulePortalReqCS_Response'是描述的xsl文件。沒有代碼,因爲它運行在WSO2 ESB上。 – elias

回答

1

您所得到的NullPointerException似乎表明指向您希望轉換的數據的XPath表達式(在本例中爲WSO2 ESB缺省值時)將返回null。在這種情況下,這意味着你有一個空白的SOAP體。

你還沒有發佈你的序列配置,所以我真的沒有太多的工作。

我的建議是,你添加一個完整的日誌(如下圖),打印與幾個屬性到ESB控制檯和碳日誌文件在整個SOAP信封,只是在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:stylesheet元素,去掉你XSLT輸出不必要的SOAP xmlns聲明。

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