Search code examples
apache-camelcamel-sql

Accessing OUT parameters with Apache Camel SQL Stored Procedure Component


I'm calling an Oracle Stored Procedure using Apache Camel's SQL Stored Procedure Component.

The Stored Procedure that I'm calling has several OUT parameters which are all returned in the BODY as a String, for example:

{param1=0, param2=-, param3=<?xmlversion="1.0"?><Client><Item><PHONE>1234567890</PHONE></Item></Client>}

Currently I'm tokenizing/parsing the BODY to be able to extract the parameters. This works but it's not efficient (and error prone).

My code looks like this:

...
<bean id="od" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    <property name="driver">
        <bean class="oracle.jdbc.OracleDriver"/>
    </property>
    <property name="url" value="${connURL}"/>
</bean>
...
<camel:to uri="sql-stored:PACKAGE.STORED_PROCEDURE(VARCHAR ${exchangeProperty.param0},OUT VARCHAR param1,OUT VARCHAR param2,OUT VARCHAR param3,OUT VARCHAR param4)?dataSource=od"> 
...
<!-- I tried this but "abc" always has no value -->
<camel:setHeader headerName="abc">
    <camel:description layoutX="280" layoutY="20" layoutWidth="120" layoutHeight="120"/>
    <camel:simple>$simple{header.param3}</camel:simple>
</camel:setHeader>
<!-- This is how I parse the BODY (inefficient!) -->
<camel:groovy><![CDATA[

    def outParams = [
        param1: "NO_VALUE",
        param2: "NO_VALUE",
        param3: "NO_VALUE",
        param4: "NO_VALUE"   
    ]
    def retERR = "yes"
    def t = ""
    def bd = exchange.getIn().getBody(String.class)

    try {
        def varList = bd.replaceAll("\n","").replaceAll("^\\{","").replaceAll("\\}\$","")
        varList = varList.tokenize(',')
        for (keyVal in varList) {
            keyVal = keyVal.trim()
            i = keyVal.indexOf('=')
            outParams[keyVal.take(i)] = keyVal.substring(i+1)
        }
        retERR = "no"
    } catch(all) {
        retERR = "yes"
    }

    exchange.setProperty("outParams",outParams)
    exchange.setProperty("retERR",retERR)

]]>
</camel:groovy>
...
<camel:to uri="bean:varpop?method=MYBEAN(&apos;outParams,retERR,param3,abc&apos;)">
    <camel:description layoutX="20" layoutY="470" layoutWidth="120" layoutHeight="120"/>
</camel:to>

Is there a direct way of accessing param1, param2, etc... directly without having to parse the BODY?


Solution

  • sql-stored-component producer already returns Map to body. Throw away all your parsing logic, because the String, you are parsing, is just toString() representation of Map.

    ...
    <camel:to uri="sql-stored:PACKAGE.STORED_PROCEDURE(VARCHAR ${exchangeProperty.param0},OUT VARCHAR param1,OUT VARCHAR param2,OUT VARCHAR param3,OUT VARCHAR param4)?dataSource=od"/> 
    
    <!-- Variant 1: Pass Map to MYBEAN method -->
    <camel:to uri="bean:varpop?method=MYBEAN(${body})"/>
    
    <!-- Variant 2: Get params from Map and pass it as arguments -->
    <camel:to uri="bean:varpop?method=MYBEAN(${body[param1]},${body[param2]},${body[param3]},${body[param4]})"/>
    

    And then use it in your varpop bean:

    public class Varpop{
        // Variant 1: Map as argument
        public void MYBEAN(Map<String, String> procedureResult){
            System.out.println(procedureResult.get("param1"));
            System.out.println(procedureResult.get("param2"));
            //...
        }
    
        // Variant 2: Multiple arguments
        public void MYBEAN(String param1, String param2, String param3, String param4){
            System.out.println(param1);
            System.out.println(param2);
            //...
        }
    }