0
votes

In WSO2 ESB, I have created an rest API. This API needs to connect to two different services, and combine the results.

For this, I use an API, with in de insequence a clone mediator that sends out the appropriate messages. This works fine.

In the outsequence, I use a logger to see the incoming messages. Both are json and come back ok. I then want to use an aggregate mediator to combine the two. With this, I have two issues:

  • when using a rootElementProperty to place the two items under one parent, a NPE happens,
  • when using enrich mediators or whatever else to make a correct message, and ending with send, the resulting message is never sent back.

What can be the cause of this?

This is the actual API:

<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse" name="Cale-StreetsAPI" context="/Cale-StreetsAPI">
    <resource methods="GET" uri-template="/getStreets?lat={lat}&amp;lon={lon}&amp;radius={radius}">
        <inSequence>
            <property name="aggRoot" scope="default">
                <red:jsonObject xmlns:red="redora"/>
            </property>
            <log description="">
                <property name="lat" expression="get-property('uri.var.lat')"/>
                <property name="lon" expression="get-property('uri.var.lon')"/>
                <property name="radius" expression="get-property('uri.var.radius')"/>
            </log>
            <clone continueParent="true" id="deCartaStreets">
                <target>
                    <sequence>
                        <sequence key="DeCartaDDS"/>
                    </sequence>
                </target>
                <target>
                    <sequence>
                        <sequence key="DeCartaReverseGeo"/>
                    </sequence>
                </target>
            </clone>
        </inSequence>
        <outSequence>
            <property name="messageType" value="application/xml" scope="axis2" type="STRING" description="messageType"/>
            <log level="full" description="">
                <property name="WSANSWER" value="true"/>
            </log>
            <aggregate>
                <completeCondition>
                    <messageCount min="2" max="-1"/>
                </completeCondition>
                <onComplete expression="$body/jsonObject">
                    <enrich>
                        <source clone="true" xpath="$body//jsonObject"/>
                        <target type="property" property="ResultItems"/>
                    </enrich>
                    <log level="custom">
                        <property name="ResultItems" expression="get-property('ResultItems')"/>
                    </log>
                    <enrich>
                        <source type="inline" clone="true">
                            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                                <soapenv:Header/>
                                <soapenv:Body>
                                    <JsonResponse xmlns="dummy"/>
                                </soapenv:Body>
                            </soapenv:Envelope>
                        </source>
                        <target type="envelope"/>
                    </enrich>
                    <enrich>
                        <source type="property" clone="true" property="ResultItems"/>
                        <target xmlns:red="dummy" action="child" xpath="//red:JsonResponse"/>
                    </enrich>
                    <log level="full" description="">
                        <property name="AGGREGATE_END" value="true"/>
                    </log>
                    <property name="messageType" value="application/json" scope="axis2" type="STRING" description="messageType"/>
                    <send/>
                </onComplete>
            </aggregate>
        </outSequence>
        <faultSequence>
            <log level="full" category="WARN"/>
        </faultSequence>
    </resource>
</api>
1

1 Answers

0
votes

I faced the same problem you did. According to number of posts over Internet APIs doesn't support aggregation.

So my solution was to introduce aggregating Proxy service which did all the job where API just made a call to that proxy service.

So if you modify your solution as follows you should be able to achieve what you expect:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"  name="AggregatingProxy" transports="local https http"  startOnLoad="true" trace="disable">
<target>
    <inSequence>
        <log level="full"/>
        <property name="enclosing_element">
            <result xmlns=""/>
        </property>
        <clone continueParent="true">
            <property name="aggRoot" scope="default">
                <red:jsonObject xmlns:red="redora"/>
            </property>
            <log description="">
                <property name="lat" expression="get-property('uri.var.lat')"/>
                <property name="lon" expression="get-property('uri.var.lon')"/>
                <property name="radius" expression="get-property('uri.var.radius')"/>
            </log>
            <clone continueParent="true" id="deCartaStreets">
                <target>
                    <sequence>
                        <sequence key="DeCartaDDS"/>
                    </sequence>
                </target>
                <target>
                    <sequence>
                        <sequence key="DeCartaReverseGeo"/>
                    </sequence>
                </target>
            </clone>
        </clone>
    </inSequence>
    <outSequence>
        <property name="messageType" value="application/xml" scope="axis2" type="STRING" description="messageType"/>
        <log level="full" description="">
            <property name="WSANSWER" value="true"/>
        </log>
        <aggregate>
            <completeCondition>
                <messageCount min="2" max="-1"/>
            </completeCondition>
            <onComplete expression="$body/jsonObject">
                <enrich>
                    <source clone="true" xpath="$body//jsonObject"/>
                    <target type="property" property="ResultItems"/>
                </enrich>
                <log level="custom">
                    <property name="ResultItems" expression="get-property('ResultItems')"/>
                </log>
                <enrich>
                    <source type="inline" clone="true">
                        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                            <soapenv:Header/>
                            <soapenv:Body>
                                <JsonResponse xmlns="dummy"/>
                            </soapenv:Body>
                        </soapenv:Envelope>
                    </source>
                    <target type="envelope"/>
                </enrich>
                <enrich>
                    <source type="property" clone="true" property="ResultItems"/>
                    <target xmlns:red="dummy" action="child" xpath="//red:JsonResponse"/>
                </enrich>
                <log level="full" description="">
                    <property name="AGGREGATE_END" value="true"/>
                </log>
                <property name="messageType" value="application/json" scope="axis2" type="STRING" description="messageType"/>
                <send/>
            </onComplete>
        </aggregate>
    </outSequence>
    <faultSequence>
        <log level="full" category="WARN"/>
    </faultSequence>
</target>
</proxy>

API Configuration:

<api xmlns="http://ws.apache.org/ns/synapse" name="Cale-StreetsAPI" context="/Cale-StreetsAPI">
<resource methods="GET" uri-template="/getStreets?lat={lat}&amp;lon={lon}&amp;radius={radius}">
    <inSequence>
        <call>
            <endpoint>
                <address uri="http://localhost:8280/services/AggregatingProxy" format="soap12"></address>
            </endpoint>
        </call>
        <respond/>
    </inSequence>
</resource>
</api>

This actually worked out for me and hopefully will help you too.

Also consider using:

<property name="enclosing_element">
            <result xmlns=""/>
        </property>
   ...
   <onComplete expression="$body/jsonObject" enclosingElementProperty="enclosing_element">

In case your service return different type of results.

Thanks, Vladimir.