Question

I've built a proxy in WSO2 ESB that receives a xml, transforms it, forwards to a WSO2 Data Service, transforms the result and give it back to the requester.

According the log, the DataService is being correctly called, since the result XML is printed. The problem is on the transforming of the result, where this happens:

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)

The XLST file is:

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

And the XML returned by DataService is:

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

I've tested the XSLT with the XML in another tools and the tranformation works! =/

I'm thinking that may be caused by the inline namespace added by the DSS to the GetAppointmentResponse tag. Using JRE1.6.0_43, ESB 4.6.0 and DSS 3.1.0. Please help.

EDIT

I've noticed that this problem is really caused by an empty body in the response, as @Kallja mentioned.

Resuming, I have the following scenario:

     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 directly PROXY3 via soapUI, the webservice is correctly called and the response is received.
But, calling PROXY2, the log sequence appears in the following order: log2, log3, log5, log4

It means that the PROXY2 is making an asynchronous call to the PROXY3. It do not wait for the XML of the response before return to the soapUI the answer. It generates an empty body.

Then, how to make it synchronous? I've tried to replace the Send mediator by the Callout mediator, but the result is the same.

Was it helpful?

Solution

The NullPointerException you are getting seems to indicate that the XPath expression (which in this case is the WSO2 ESB default when nothing else is provided) pointing at the data you wish to transform returns null. In this case that would mean that you have a blank SOAP body.

You haven't posted your sequence configuration, so I don't really have a lot to work with.

My suggestion is that you add a full log (below), which prints the entire SOAP envelope along with several properties into the ESB console and the carbon log file, just before the XSLT mediator to see whether or not you actually have content in your payload.

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

I tested your transformation with the following config and it performed flawlessly.

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

As a side note I'd suggest you add the following attribute to your xsl:stylesheet element to remove the unnecessary SOAP xmlns declaration from your XSLT output.

exclude-result-prefixes="soapenv"


EDIT
This simple sample config is based on the description of the flow of execution edited in to the question. It shows how to properly implement the flow in question. When Proxy1 is called the log statements do appear in sequence as expected.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top