stored procedure invokation through camel sql-stored component - apache-camel

I am new to camel sql-stored component. Currently I am using Camel 2.17.5. And I am trying to invoke oracle stored procedure from camel route. This is my route:
<setHeader headerName="test">
<simple>John</simple>
</setHeader>
<log loggingLevel="INFO" message="value: ${headers.test}" />
<to uri="sql-stored:HELLO(VARCHAR ${headers.test},OUT VARCHAR outparam1)?dataSource=oracleDataSource"/>
<log loggingLevel="INFO" message="SP result: ${body}" />
This is my stored procedure:
CREATE OR REPLACE PROCEDURE hello(param1 IN varchar2, outparam1 OUT varchar2)
AS
BEGIN
select password INTO outparam1 from dbuser WHERE USERNAME=param1;
END;
But when I run my route it gives me error:
org.apache.camel.component.sql.stored.template.ast.ParseRuntimeException: org.apache.camel.component.sql.stored.template.generated.ParseException: Encountered " " " " "" at line 1, column 35.
Was expecting one of:
<NUMBER> ...
<IDENTIFIER> ...
at org.apache.camel.component.sql.stored.template.TemplateParser.parseTemplate(TemplateParser.java:36)
at org.apache.camel.component.sql.stored.CallableStatementWrapperFactory.getTemplateStoredProcedure(CallableStatementWrapperFactory.java:71)
could you help me, what is wrong here?

As pointed above Claus it was my syntax error. I just removed double spaces and it works!
So invokation line should be like this:
<to uri="sql-stored:hello(VARCHAR ${headers.test},OUT VARCHAR outparam1)?dataSource=oracleDataSource"/>

Related

Typed XML Update in SQL Server table

I have 3rd party table with XML column and I need to change the recipient value in the value if the key\string = 'recipient'. Here is a slice of the original XML with 2 items:
DECLARE #myDoc XML
SET #myDoc = '<Root>
<item>
<key>
<string>subject</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="q1:string">test subject</anyType>
</value>
</item>
<item>
<key>
<string>recipient</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="q1:string">prodops#company.com</anyType>
</value>
</item>
</Root>'
SET #myDoc.modify('
declare namespace q1="http://www.w3.org/2001/XMLSchema"; declare namespace p5="http://www.w3.org/2001/XMLSchema-instance";
replace value of (/q1:Root/q1:item/q1:value/p5:type="q1:string")[1]
with ("devops#company.com")
')
SELECT #myDoc
I have kind of hacked my way to this point - XML is not my strong suit. Based on BOL, I need to do something with namespace in the modify()? Right? I'm missing an if statement I am sure but just a mystery as to how to de-reference that value for recipient. Someone has done this before - I am sure. The goal is to incorporate into a post-restore script after refreshing production data to test.
Note that this fails as-is with
Msg 2337, Level 16, State 1, Line 125
XQuery [modify()]: The target of 'replace' must be at most one node, found 'xs:boolean ?'"
You need to specify text() to replace the inner text of a node. You also need to reference the anyType node, which you have not.
By the looks of things, none of the relevant nodes actually use the namespaces, so we don't need them at all.
SET #myDoc.modify('
replace value of (/Root/item[key[string[text()="recipient"]]]/value/anyType/text())[1]
with ("devops#company.com")
');
Explanation:
Descend to /Root, no namespace needed
Descend to /item[ with a predicate...
... must have key[ node ...
... which has string[ node ...
... which has inner text()="recipient"]]]
Back to the original item we descend /value then /anyType then inner /text()
All bracketed to [1] to ensure a single node
The title of the question specifies "Typed XML Update in SQL Server table".
The provided XML is not bound by any XSD schema. That's why that XML is not typed. A real typed XML is updated differently.
Please try the following solution. It has the following:
Somewhat simpler XPath predicate expression.
Using SQL variable for a new value.
All credit goes to #Charlieface.
SQL
DECLARE #myDoc XML =
N'<Root>
<item>
<key>
<string>subject</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema"
xmlns:p5="http://www.w3.org/2001/XMLSchema-instance"
p5:type="q1:string">test subject</anyType>
</value>
</item>
<item>
<key>
<string>recipient</string>
</key>
<value>
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema"
xmlns:p5="http://www.w3.org/2001/XMLSchema-instance"
p5:type="q1:string">prodops#company.com</anyType>
</value>
</item>
</Root>';
DECLARE #anyType VARCHAR(30) = 'devops#company.com';
SET #myDoc.modify('
replace value of (/Root/item[key/string/text()="recipient"]/value/anyType/text())[1]
with (sql:variable("#anyType"))
');
-- test
SELECT #myDoc;

MyBatis Callable with SQL temp variable

I am trying to get a Stored Procedure to use SQL date instead of Java date.
But I want to do this without modifying the SP.
This is what I would like to do.
<select id="updateThing" statementType="CALLABLE">
{
DECLARE #tmp DATETIME
SET #tmp = GETDATE()
CALL dbo.thingUpdate (
#{..., javaType=java.lang.Integer, jdbcType = NUMERIC},
...,
<choose>
<when test="datePassed != null">
#tmp,
</when>
<otherwise>
NULL,
</otherwise>
</choose>
...
)
}
</select>
I have tried moving the bracers around and I have tried doing the GETDATE() in place and using TIMESTAMP, but all of them seem to trigger an exception.
In the case of the above version the error is:
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '{'
Any advice would be appreciated.
You can create another stored procedure that acts as a wrapper for the existing one. It should get the date if needed and invoke the original stored procedure.

Camel Splitter XML DSL how to log message index

I'm using Apache Camel version 2.15.1. My route has a splitter which splits the body in chunks and each chunk is saved into database. I would like to log a progress of this route. Unfortunately CamelSplitIndex header is 0-based, how do I do "+ 1" using XML DSL?
<route id="insertInDb">
<from uri="direct:listOfDataInBodyArrivesHere" />
<split>
<simple>${body}</simple>
<log message="Insert ${header.CamelSplitIndex} of ${header.CamelSplitSize}" />
<to uri="mybatis:insertData?statementType=Insert" />
</split>
<log message="Insert done" />
</route>
The output is
Insert 0 of 3
Insert 1 of 3
Insert 2 of 3
My desired output is
Insert 1 of 3
Insert 2 of 3
Insert 3 of 3
How do I achieve the desired output? I tried with ${header.CamelSplitIndex++} with no result.
I think it should be ${header.CamelSplitIndex}++

Call a procedure or function in Oracle DB with return = array of UDT from WSO2 DSS

I follow this post[1] as a guide to build an example of query an array of UDT in WSO2 DSS. In the post just query an UDT, my config try to query an UDT array.
I created this in my DB, a dummy PROCEDURE to try this:
create or replace
TYPE "LIST_CUSTOMERS" IS TABLE OF customer_t
CREATE OR REPLACE
PROCEDURE getCustomer2(listcust OUT list_customers) IS
cust customer_t;
cust2 customer_t;
BEGIN
listcust := list_customers();
cust := customer_t(1, 'prabath');
cust2 := customer_t(2, 'jorge');
listcust.extend;
listcust(1) := cust;
listcust.extend;
listcust(2) := cust2;
END;
My DS is this:
<?xml version="1.0" encoding="UTF-8"?>
<data name="UDTSample2">
<config id="default">
<property name="org.wso2.ws.dataservice.driver">oracle.jdbc.driver.OracleDriver</property>
<property name="org.wso2.ws.dataservice.protocol">jdbc:oracle:thin:#localhost:1521:DBMB</property>
<property name="org.wso2.ws.dataservice.user">****</property>
<property name="org.wso2.ws.dataservice.password">****</property>
</config>
<query id="q3" useConfig="default">
<sql>call getCustomer2(?)</sql>
<result element="customers">
<element name="customer" arrayName="custArray" column="cust" optional="true"/>
</result>
<param name="cust" paramType="ARRAY" sqlType="ARRAY" type="OUT" structType="LIST_CUSTOMERS" />
</query>
<operation name="op3">
<call-query href="q3" />
</operation>
</data>
ant return:
<customers xmlns="http://ws.wso2.org/dataservice">
<customer>{1,prabath}</customer>
<customer>{2,jorge}</customer>
</customers>
but I want something like this:
<customers xmlns="http://ws.wso2.org/dataservice">
<customer>
<id>1</id>
<name>prabath<name>
</customer>
<customer>
<id>2</id>
<name>Jorge<name>
</customer>
</customers>
How can I accomplish this?
[1] http://prabathabey.blogspot.com/2012/05/query-udtsuser-defined-types-with-wso2.html
Not sure whether this kind of transformation can be done at DSS level because DSS gives back what it recieves from database. Better use WSO2 esb for this kind of transformation.
By the moment it's not possible to accomplish this scenario using just DSS. the DS response must be send to the WSO2 ESB to do the corresponding transformation before send the response to the client. A JIRA was created to do this in the future https://wso2.org/jira/browse/DS-1104
As a workaround, you can use a procedure returning a sys_refcursor.
It would look like this:
PROCEDURE getCustomer_CUR(cur_cust OUT SYS_REFCURSOR)
l_cust LIST_CUSTOMERS;
IS
-- Retrieve cust list:
getCustomer2(l_cust);
OPEN cur_cust for
select cast(multiset(select * from TABLE(l_cust)) as customer_t) from dual;
...
END;
Then you can do your DSS mapping something like:
<sql>call getCustomer_CUR(?)</sql>
<result element="customers">
<element arrayName="custArray" name="Customers">
<element column="custArray[0]" name="col0" xsdType=.../>
...
</element>
</result>
<param name="cust" sqlType="ORACLE_REF_CURSOR" type="OUT"/>
It is tedious but it works.

Count the Occurrences of an Attribute?

I have an XML column in a large table that looks like this, in TSQL how would i count the number of times an attribute (LCPID) occurs?
Thanks,
The code:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<PingAutoRequest xmlns="http://Reply.LeadMarketPlace.Services.Ping.ServiceContracts/2007/10/ServiceContracts">
<AutomotiveLead>
<LCPId>766</LCPId>
<Zipcode>33544</Zipcode>
<Make>Ford</Make>
<Model>Escape</Model>
<LeadType>New</LeadType>
<Year>2013</Year>
<Trim>FWD S</Trim>
<ExteriorColor />
<InteriorColor />
<Transmission />
<TradeIn>false</TradeIn>
<LastFourPhoneDigits />
<LastName />
</AutomotiveLead>
</PingAutoRequest>
</soap:Body>
</soap:Envelope>
OK, as your XML doesn't contain any attributes (apart from the namespaces) I'm going to assume you mean you want to count the number of <LCPId> elements. If so, then you could do that like this...
;WITH XMLNAMESPACES ('http://Reply.LeadMarketPlace.Services.Ping.ServiceContracts/2007/10/ServiceContracts' as ns)
SELECT XmlColumn.value('(count(//ns:LCPId))','int')
FROM YourTableName
Note, we need to handle the XML namespace using the WITH statement, the semi-colon is not a mistake. Then we count the number of elements with an XPath expression count(//ns:LCPId).
You can see it in action at SQL Fiddle here.

Resources