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)

Reply via email to