问题
I want to send a query to the database and return the result to the client using WSO2 rest api. Here is the synapse config:
<api xmlns="http://ws.apache.org/ns/synapse" name="RestDBLookup" context="/dblookup">
<resource methods="POST GET" uri-template="/channel/{name}" protocol="http">
<inSequence>
<dblookup>
<connection>
<pool>
<password>pass</password>
<driver>oracle.jdbc.driver.OracleDriver</driver>
<url>jdbc:oracle:thin:@localhost:1521:ORCL</url>
<user>user</user>
</pool>
</connection>
<statement>
<sql>SELECT ID, CHANNEL_NAME FROM CHANNEL where CHANNEL_NAME = ?</sql>
<parameter expression="get-property('uri.var.name')" type="VARCHAR"/>
<result name="channel_id" column="ID"/>
</statement>
</dblookup>
<log level="custom">
<property name="ID" expression="get-property('channel_id')"/>
<property name="State" value="after db"/>
</log>
</inSequence>
<outSequence>
<property name="messageType" value="application/json" scope="axis2" type="STRING"/>
<log level="full"/>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>
When I call the url http://localhost:8280/dblookup/channel/someChannel
with rest client I get the log after the dblookup
LogMediator ID = 40810162, State = after db
but the outSequence
is not executed and I only get Status 202 Accepted on the rest client with no body.
So the question is how can I construct some response (in JSON format for example) and send it to the client?
回答1:
Synapse mediation has three flows:
- inSequence - handle in coming request and define how request should be processed (mediate) before send to target endpoint
- outSequence - handle response coming back from endpoint and define how response should be processed (mediate) before send to client
- faultSequence - if error occurred during service mediation, then fault message hand-over to fault sequence. You can write down logic in fault sequence based on your requirement (log error, drop message and send back fault).
Now let's see your use-case. What you trying to do is query database in inSequence. Also you getting result as well. But problem is result not send back to client. Here problem was the mediation you written in inSequence not calling the outSequence. Therefore outSequence not getting hit. For an example if you call backend service in inSequence, then response hit to outSequence. In your case response come back to inSequence. Therefore we can do either one of following option:
- Adding
<loopback/>
mediator after</log>
mediator in inSequence. This will move message from inSequence to outSequence. - Move logic written in outSequence to inSequence. Then add
<respond/>
at the end of inSequence. This will send current message back to client. So you may not need to have outSequence.
Hope above answer helps.
Cheers!
回答2:
As Indika suggested I used <respond/>
and ended up with this configuration:
<api context="/dblookup" name="RestDBLookup" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST GET" protocol="http" uri-template="/channel/{name}">
<inSequence>
<dblookup>
<connection>
<pool>
<password>pass</password>
<driver>oracle.jdbc.driver.OracleDriver</driver>
<url>jdbc:oracle:thin:@localhost:1521:ORCL</url>
<user>user</user>
</pool>
</connection>
<statement>
<sql><![CDATA[SELECT ID, CHANNEL_NAME FROM CHANNEL where CHANNEL_NAME = ?]]></sql>
<parameter expression="get-property('uri.var.name')" type="VARCHAR"/>
<result column="ID" name="channel_id"/>
</statement>
</dblookup>
<log level="custom">
<property expression="get-property('channel_id')" name="ID"/>
<property name="State" value="after db"/>
</log>
<payloadFactory media-type="json">
<format>
{
"channelId":"$1"
}
</format>
<args>
<arg evaluator="xml" expression="get-property('channel_id')"/>
</args>
</payloadFactory>
<property action="remove" name="NO_ENTITY_BODY" scope="axis2"/>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
来源:https://stackoverflow.com/questions/34722299/apache-synapse-wso2-api-no-response