Niels Bertram created CAMEL-12154:
-------------------------------------
Summary: Camel does not set Saxon parameters in a XQuery 3.0
compatible way
Key: CAMEL-12154
URL: https://issues.apache.org/jira/browse/CAMEL-12154
Project: Camel
Issue Type: Bug
Components: camel-saxon
Affects Versions: 2.20.1, 2.19.4, 2.18.5
Environment: any
Reporter: Niels Bertram
When injecting parameters into the Saxon XQuery engine, the Camel component is
not sophisticated enough to inject the parameter as the right type for Saxon to
bind it properly.
Let's say we have a XQuery 3.0 compliant variable definition:
{code:java}
declare variable $extParam as xs:boolean external := false();
{code}
and we set a property on the exchange
{code:java}
exchange.setProperty("extParam ", true);
{code}
our XQuery execution will fail with the following error as the value bound into
Saxon is not a Boolean type:
{code:java}
Type error on line 3 column 5
XPTY0004: Required item type of value of variable $extParam is xs:boolean;
supplied value
has item type xs:string
{code}
The part(s) that need to get more sophisticated are:
*
[XQueryBuilder.addParameter()|https://github.com/apache/camel/blob/camel-2.20.x/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryBuilder.java#L656]
* [XQueryBuilder.configureQuery() - set in
body|https://github.com/apache/camel/blob/camel-2.20.x/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryBuilder.java#L626]
* [XQueryBuilder.configureQuery() - set out
body|https://github.com/apache/camel/blob/camel-2.20.x/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryBuilder.java#L638]
At the bare minimum probably should be supporting to set query parameters for
all the basic types like string, boolean, int, decimal etc.
I was thinking of a simple if then else block to check the content type and
then call the appropriate Saxon value wrapper but am a bit unsure as the body
could be simple type or DOM or Source or something else depending on the
marshalling that is going on beforehand.
Here a very basic setup that shows what is happening when Saxon parameters are
just bound as Object values:
{code:java}
package com.virginaustralia.bind.xquery;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import net.sf.saxon.Configuration;
import net.sf.saxon.om.Item;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.query.DynamicQueryContext;
import net.sf.saxon.query.XQueryExpression;
import net.sf.saxon.value.BooleanValue;
import net.sf.saxon.value.ObjectValue;
public class ParameterDynamicTest {
private static final String TEST_QUERY = new StringBuilder()
.append("xquery version \"3.0\" encoding \"UTF-8\";\n")
.append("declare variable $extParam as xs:boolean external := false();\n")
.append("if($extParam) then(true()) else (false())")
.toString();
Configuration conf = new Configuration();
XQueryExpression query;
DynamicQueryContext context;
@Before
public void setup() throws Exception {
conf.setCompileWithTracing(true);
query = conf.newStaticQueryContext().compileQuery(TEST_QUERY);
context = new DynamicQueryContext(conf);
}
/**
* This is what Camel XQueryBuilder executes, which leads to a parameter
binding type error.
*
*/
@Test
public void testObjectParameter() throws Exception {
context.setParameter(StructuredQName.fromClarkName("extParam"), new
ObjectValue<>(true));
Item result = query.iterator(context).next();
assertTrue(result instanceof BooleanValue);
assertEquals(true, ((BooleanValue) result).getBooleanValue());
}
/**
* This is what Camel XQueryBuilder should execute to allow Saxon to bind the
parameter type properly.
*/
@Test
public void testBooleanParameter() throws Exception {
context.setParameter(StructuredQName.fromClarkName("extParam"),
BooleanValue.TRUE);
Item result = query.iterator(context).next();
assertTrue(result instanceof BooleanValue);
assertEquals(true, ((BooleanValue) result).getBooleanValue());
}
}
{code}
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)