S9API / Saxon XQuery可独立运行,但不能在EJB或servlet容器中运行

时间:2019-11-13 08:19:20

标签: java saxon

当尝试从EJB上下文中调用XQuery时,我遇到了这个奇怪的问题。当我在Java主上下文中运行此程序时,我没有任何问题-它按计划工作。

但是当我在容器上下文中运行相同的逻辑时,总是会遇到此异常:

net.sf.saxon.s9api.SaxonApiException: No function with name {http://www.w3.org/2005/xquery-local-functions} func and arity 1 has been declared in the query
    at net.sf.saxon.s9api.XQueryEvaluator.callFunction(XQueryEvaluator.java:593)
    at com.acme.xquery.controller.QueryControl.runQuery(QueryControl.java:76)
    at com.acme.kafka.KafkaRecordHandler.run(KafkaRecordHandler.java:25)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: net.sf.saxon.trans.XPathException: No function with name {http://www.w3.org/2005/xquery-local-functions}func and arity 1 has been declared in the query
    at net.sf.saxon.s9api.SaxonApiException.<init>(SaxonApiException.java:36)
    ... 8 more

可以正常工作的简单测试类如下:

import java.io.File;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api.DocumentBuilder;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;  
import net.sf.saxon.s9api.XQueryCompiler;
import net.sf.saxon.s9api.XQueryEvaluator;
import net.sf.saxon.s9api.XQueryExecutable; 
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.XdmValue;

public class Test {
    private static HashMap<String, XQueryExecutable> cache = new HashMap<String, XQueryExecutable>();
    Processor saxon = new Processor(false);
    XQueryCompiler compiler = saxon.newXQueryCompiler(); 

    public static void main(String[] args) throws Exception {

        Test t = new Test();
        t.prep();

        byte[] bytes = Files.readAllBytes(Paths.get("C:\\dev\\booking.xml"));
        String content = new String(bytes);

        // transform xml 1000 times
        for (int i = 0; i < 1; i++)
            t.transform(content);
    }

    private void prep() throws Exception {
        XQueryExecutable exec = compiler.compile(new File("C:\\project\\cbcPrio\\src\\main\\resources\\createBooking.xqy"));
        cache.put("TEST", exec);
    }

    private XQueryExecutable getExpression(String key) {
        return cache.get(key);
    }

    private void transform(String xml ) throws Exception {

        XQueryExecutable exec = getExpression("TEST");

        XQueryEvaluator query = exec.load();

        DocumentBuilder builder = saxon.newDocumentBuilder();

        Source src = new StreamSource(new StringReader(xml));
        XdmNode doc = builder.build(src);

        XdmValue result = query.callFunction(new QName("http://www.w3.org/2005/xquery-local-functions", "func"), new XdmValue[]{doc});
        System.out.println( result );
    }

}

用作EJB上下文一部分的逻辑(这将引发上面的异常)如下:

import java.io.StringReader;
import java.util.HashMap;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import net.sf.saxon.s9api.DocumentBuilder;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.XQueryCompiler;
import net.sf.saxon.s9api.XQueryEvaluator;
import net.sf.saxon.s9api.XQueryExecutable;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.XdmValue;

public final class QueryControl {

    private enum xqFiles {      

        CREATEBOOKING("/createBooking.xqy");    

        private final String fileLocation;      
        xqFiles(String fileLocation){
            this.fileLocation = fileLocation;
        }

        public String getFileLocation(){
            return fileLocation;
        }       
    }

    private static HashMap<String, XQueryExecutable > cache = new HashMap<String, XQueryExecutable>();
    Processor saxon = new Processor(false);
    XQueryCompiler compiler = saxon.newXQueryCompiler();    
    private static QueryControl qc = null;

    private void loadXQCache(String key, String fileLocation) throws Exception {                
        try {

            XQueryExecutable exec = compiler.compile(fileLocation);     
            cache.put(key, exec);                           
        } catch (Exception e) {
            throw new RuntimeException("Problem with loading XQuery files!", e);
        }
    }   

    public static QueryControl newInstance() throws Exception {
        if (qc == null)
            qc = new QueryControl();
        return qc;
    }

    private QueryControl() throws Exception {       
        loadXQCache(xqFiles.CREATEBOOKING.name(), xqFiles.CREATEBOOKING.getFileLocation());
    }

    public void stop() {
        try {
            //this.con.close();
        } catch (Exception xe) {
            xe.printStackTrace();
        }
    }

    public void runQuery(String xml) throws Exception { 

        XQueryExecutable exec  = getPreparedExpression(xqFiles.CREATEBOOKING.name());

        XQueryEvaluator query = exec.load();
        DocumentBuilder builder = saxon.newDocumentBuilder();       
        Source src = new StreamSource(new StringReader(xml));
        XdmNode doc = builder.build(src);
        XdmValue result = query.callFunction(new QName("http://www.w3.org/2005/xquery-local-functions", "func"), new XdmValue[]{doc});

        System.out.println( result );       
    }

    private static XQueryExecutable getPreparedExpression(String key) throws Exception {        
        return cache.get(key);
    }

}

XQuery(xqy)看起来像这样:

xquery version "1.0" encoding "utf-8";

(:: OracleAnnotationVersion "1.0" ::)

declare namespace dtl="http://soa.acme.com/Account/createBooking";
(:: import schema at "../../../../ABC_Booking_V1.0/xsd/DTLModels/createBooking.xsd" ::)

declare variable $ind as document-node() (:: schema-element(dtl:createBookingRequest) ::) external;

declare function local:func($ind as document-node() (:: schema-element(dtl:createBookingRequest) ::) ) as element() (:: schema-element(dtl:createBookingRequest) ::) {

let $createBookingOriginalRequest := $ind/dtl:createBookingRequest

return
   <dtl:createBookingRequest>
       <dtl:AccountingUnit>{fn:data($createBookingOriginalRequest/dtl:AccountingUnit)}</dtl:AccountingUnit>
       <dtl:RequestingApplCode>{fn:data($createBookingOriginalRequest/dtl:RequestingApplCode)}</dtl:RequestingApplCode>
       <dtl:DeliveryId>{fn:data($createBookingOriginalRequest/dtl:DeliveryId)}</dtl:DeliveryId>
       <dtl:MessageSeqNo>{fn:data($createBookingOriginalRequest/dtl:MessageSeqNo)}</dtl:MessageSeqNo>
       <dtl:OrigTimeStamp>{fn:data($createBookingOriginalRequest/dtl:OrigTimeStamp)}</dtl:OrigTimeStamp>
       <dtl:TransForcingCode>1</dtl:TransForcingCode>
       <dtl:WantResponse>N</dtl:WantResponse>
       <dtl:CommLayerTimeStamps>
           <dtl:CommLayerTime>
               <dtl:CommLayer>TM CR Booking Creation</dtl:CommLayer>
               <dtl:CommLayerTimeStamp>{fn:current-dateTime()}</dtl:CommLayerTimeStamp>
           </dtl:CommLayerTime>
       </dtl:CommLayerTimeStamps>
        {
       for $request in $createBookingOriginalRequest/dtl:RequestTransactionList
       return
       <dtl:RequestTransactionList>
           <dtl:TransactionSeqNo>{fn:data($request/dtl:TransactionSeqNo)}</dtl:TransactionSeqNo>
           <dtl:TransactionType>0002</dtl:TransactionType>
           {
               if ($request/dtl:ExposureDate)
               then <dtl:ExposureDate>{fn:data($request/dtl:ExposureDate)}</dtl:ExposureDate>
               else ()
           }
           {
               if ($request/dtl:TradeExecutionDateTime)
               then <dtl:TradeExecutionDateTime>{fn:data($request/dtl:TradeExecutionDateTime)}</dtl:TradeExecutionDateTime>
               else ()
           }

 //majority of contents removed due to length restrictions on SO

       </dtl:RequestTransactionList>
       }
   </dtl:createBookingRequest>
};

local:func($ind)

最后是XML(简称):

<v2:createBookingRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      xsi:schemaLocation="http://soa.acme.com/Account/createBooking C:\development\acme-Services\integration-services\abc\ABC_Booking_Txx_v1.0\interface\ABC\DTLModels\createBooking_v20.xsd"
                      xmlns:v2="http://soa.acme.com/Account/createBooking">
            <v2:AccountingUnit>1764</v2:AccountingUnit>
            <v2:RequestingApplCode>YE</v2:RequestingApplCode>
            <v2:DeliveryId>delID1</v2:DeliveryId>
            <v2:MessageSeqNo>100003</v2:MessageSeqNo>
            <v2:OrigTimeStamp>2018-07-09T13:05:30.738+02:00</v2:OrigTimeStamp>
            <v2:TransForcingCode>1</v2:TransForcingCode>
            <v2:WantResponse>Y</v2:WantResponse>

           <v2:RequestTransactionList>
                        <v2:TransactionSeqNo>00000001</v2:TransactionSeqNo>

<!-- removed a large part of this file due to length limitation on SO -->

            </v2:RequestTransactionList>
    </v2:createBookingRequest>

0 个答案:

没有答案