我的任务是使用Camel版本2.20.0创建Camel路由,从CSV文件中取一行,使用SQL语句where子句中该行的值,并合并结果并再次输出它们。如果我在SQL语句中对标识符进行硬编码,它可以正常工作,如果我尝试使用动态URI,我会收到错误。
路线是:
from("file:///tmp?fileName=test.csv")
.split()
.tokenize("\n")
.streaming()
.parallelProcessing(true)
.setHeader("userID", constant("1001"))
//.enrich("sql:select emplid,name from employees where emplid = '1001'",
.enrich("sql:select name from employees where emplid = :#userID",
new AggregationStrategy() {
public Exchange aggregate(Exchange oldExchange,
Exchange newExchange) {...
正如我所说的,如果我用硬编码的1001取消注释该行,它会查询数据库并按预期工作。但是使用':#userID'语法我得到一个Oracle错误:
java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId ProcessorId Processor Elapsed (ms)
[route3 ] [route3 ] [file:///tmp?fileName=test.csv ] [ 43]
[route3 ] [log5 ] [log ] [ 2]
[route3 ] [setHeader2 ] [setHeader[userID] ] [ 0]
[route3 ] [enrich2 ] [enrich[constant{sql:select name from employees where emplid = :#userID] [ 40]
表格显然是存在的,因为它在值被硬编码时起作用,因此它与传递动态值有关。我已经尝试了很多关于如何在单引号内传递变量的变体,使用来自正文的值而不是标题等等。尽管我已经看过,但还没有找到工作组合许多类似的看似工作的例子。
我已经转过跟踪,看来标题也正确设置了:
o.a.camel.processor.interceptor.Tracer : >>> (route3) setHeader[userID, 1001] --> enrich[constant{sql:select name from employees where emplid = :#userID}] <<< Pattern:InOnly, Headers:{CamelFileAbsolute=true, CamelFileAbsolutePath=/tmp/test.csv, CamelFileLastModified=1513116018000, CamelFileLength=26, CamelFileName=test.csv, CamelFileNameConsumed=test.csv, CamelFileNameOnly=test.csv, CamelFileParent=/tmp, CamelFilePath=/tmp/test.csv, CamelFileRelativePath=test.csv, userID=1001}, BodyType:String, Body:1001,SomeValue,MoreValues
需要改变什么来使这项工作?
我还应该注意到我已经尝试过这种方法,使用各种语法选项来引用标题值,没有任何好运:
.enrich().simple("sql:select * from employees where emplid = :#${in.header.userID}").aggregate ...
答案 0 :(得分:1)
来自Camel文档:
pollEnrich或enrich 不访问当前的任何数据 交换意味着在轮询时不能使用任何现有的 您可能在Exchange上设置的标题。
实现目标的推荐方法是使用recipientList
,所以我建议你阅读。
修改强>
正如Ricardo Zanini在他的回答中正确指出的那样,实际上可以通过2.16以后的Camel版本实现这一目标。由于OP使用2.20,我的回答无效。
但是,我会保留我的答案,但是要指出这只有在您使用旧版本而不是2.16时才有效。
答案 1 :(得分:1)
来自docs:
从 Camel 2.16 开始 充实和 pollEnrich 支持使用Expression计算uri的动态端点,允许使用当前Exchange的数据。换句话说,上面说的所有内容都不再适用,只是有效。
当你使用2.20时,我想你可以试试这个例子:
from("file:///tmp?fileName=test.csv")
.split()
.tokenize("\n")
.streaming()
.parallelProcessing(true)
.setHeader("userID", constant("1001"))
//.enrich("sql:select emplid,name from employees where emplid = '1001'",
.enrich("sql:select name from employees where emplid = ':#${in.header.userID}'",
new AggregationStrategy() {
public Exchange aggregate(Exchange oldExchange,
Exchange newExchange) {...
请查看文档中的Expression主题以获取更多示例。
总结一下,表达式可能是:
"sql:select name from employees where emplid = ':#${in.header.userID}'"
修改强>:
抱歉,我错过了:#
suffix。你可以看到unit test working here。
请注意列类型。如果它是整数,则不需要引号。
干杯!